有几种方法可以进行合并排序,但我特别需要它像自然合并排序一样工作。该算法中发生的情况是在文件中生成较小的数字列表,如下所示:
原始列表:35 27 24 28 31 37 1 4 7 6 8 9
较小的列表部分:[35],[27],[24,28],[31,37],[1,4,7],[6,8,9]
正如您所注意到的,每次未排序列表遇到的数字小于其当前值时,都会创建一个新单元。一旦列表结束,这个列表会以另一种方式分成另外两个列表:
第一个清单:[35],[24,28],[1,4,7]
第二个清单:[27],[31,37],[6,8,9]
最后一步涉及再次将两个列表拉在一起,并且在遍历第一个列表项和第二个列表项中的单元之间比较值。例如,列表1中的第一个单元与列表2中的第一个单元进行比较,并按顺序保存数字。最后将添加剩余的单位(未显示)。
合并两个名单:[27,35],[24,28,31,37],[1,4,6,7,8,9]
此过程将重复,直到列表在一个单元中排序。
除了合并两个列表之外,我已经在此算法中设置了所有内容,并且调试或找到问题非常困难。它在进入分段故障之前大约一半。无论如何,我不能在这个程序上使用mergesort STL,而且它都在一个链表中。
注意:构造函数和其他必要的函数已经到位。我故意遗漏了其他功能,以理解特定的功能。
class mergeList
{
public:
//Setters
void setNumber(int item);
void setStart(bool newStatus);
void setEnd(bool newStatus);
void setPrev(mergeList* node);
void setNext(mergeList* node);
//Getters
int getNumber();
bool getStart();
bool getEnd();
mergeList* getPrev();
mergeList* getNext();
private:
int number;
bool startSection;
bool endSection;
mergeList* prev;
mergeList* next;
};
class mergeListObject
{
public:
mergeList* firstNode;
mergeList* lastNode;
void mergeLists(mergeListObject &firstList,
mergeListObject &secondList);
//Other functions in program are in here.
};
void mergeListObject::mergeLists(mergeListObject &firstList,
mergeListObject &secondList)
{
mergeList* combTraverse = firstNode;
mergeList* firstTraverse = firstList.firstNode;
mergeList* secondTraverse = secondList.firstNode;
bool listDone = false;
//This will clear the combination list for insertion
while (combTraverse != NULL)
{
combTraverse->setNumber(-1);
combTraverse->setStart(false);
combTraverse->setEnd(false);
combTraverse = combTraverse->getNext();
}
combTraverse = firstNode;
combTraverse->setStart(true);
while (listDone == false)
{
//This will go until the first list is traversed.
do
{
bool exception = false;
int j = firstTraverse->getNumber();
int k;
//If the second list is still active, this will
//grab its current value for comparison.
if (secondTraverse != NULL)
k = secondTraverse->getNumber();
//Second list is done, will automatically grab
//first list's value and traverse through to the end.
if (secondTraverse == NULL)
combTraverse->setNumber(firstTraverse->getNumber());
else
{
//Both values from both lists are compared.
if (j <= k)
combTraverse->setNumber(firstTraverse->getNumber());
else
{
exception = true;
combTraverse->setNumber(secondTraverse->getNumber());
}
}
//If the first value unit was used, move the first list iterator up.
//Otherwise, the second list's iterator moves up.
if (exception == false)
firstTraverse = firstTraverse->getNext();
else
secondTraverse = secondTraverse->getNext();
exception = false;
}
while (firstTraverse->getEnd() == false);
//If the second list isn't done, this will finish it.
do
{
combTraverse->setNumber(secondTraverse->getNumber());
secondTraverse = secondTraverse->getNext();
combTraverse = combTraverse->getNext();
}
while (secondTraverse->getEnd() == false);
combTraverse->setEnd(true);
//Marks the end of the section and sets the next one,
//considering it isn't the end of the list.
if (combTraverse->getNext() != NULL)
combTraverse->getNext()->setStart(true);
//Both of these should end up at the start of a unit in their own lists.
firstTraverse = firstTraverse->getNext();
secondTraverse = secondTraverse->getNext();
//Are both lists done?
if (firstTraverse == NULL &&
secondTraverse == NULL)
listDone = true;
}
return;
}
int main()
{
mergeListObject one;
mergeListObject two;
mergeListObject combined;
//The two lists are already separated. All
//other functions have already been called.
combined.mergeLists(one, two);
return 0;
}
答案 0 :(得分:1)
我能发现的第一个错误是在你的合并功能结束时:
firstTraverse = firstTraverse->getNext();
secondTraverse = secondTraverse->getNext();
可能会产生运行时错误(“访问冲突”或“分段错误”,具体取决于编译器和操作系统),您必须将其更改为
if (firstTraverse)
firstTraverse = firstTraverse->getNext();
if (secondTraverse)
secondTraverse = secondTraverse->getNext();
请注意,这些指针实际上可以为NULL。
您还必须将while (firstTraverse->getEnd() == false);
再次更改为while(firstTraverse & firstTraverse->getEnd() == false);
firstTravers
可以为NULL,只要第一个列表的分区数少于第二个列表即可。