(仅供参考,首次发布到StackOverflow)
我正在尝试在C ++中为双向链表实现合并排序。虽然排序确实有效,但它并没有正确地重建列表。它似乎是一个没有“先前”指针的单链表;列表可以向前读取,但是当我尝试向后显示时,只显示最后一个节点。我认为“合并”例程肯定有问题,但我找不到它的位置。
首先,这是列表所在的双向链接节点的代码:
#include <iostream>
using namespace std;
class DLNode
{
public:
int data;
DLNode* prev;
DLNode* next;
DLNode();
DLNode(int entry);
};
DLNode::DLNode()
{
data = -99999;
prev = NULL;
next = NULL;
}
DLNode::DLNode(int entry)
{
data = entry;
prev = NULL;
next = NULL;
}
这是双向链接列表类,仅限于构建列表并对其进行排序所需的那些函数:(仅供参考,这遵循“C ++编程:程序设计包括数据结构”中提出的算法,第6版。作者:DS Malik)
#include "DLNode.h" //the doubly-linked node class above
using namespace std;
class DblLinkList
{
private:
DLNode* head; //pointer to head of list
DLNode* last; //pointer to end of list
int count; //keeps count of number of items in list
//these 3 methods are used only to implement a mergeSort, called within sort() function
void splitList(DLNode* first1, DLNode*& first2);
DLNode* mergeList(DLNode* first1, DLNode* first2);
void recMergeSort(DLNode* &head);
public:
DblLinkList();
void displayForwards();
void displayBackwards();
int getCount();
void addToFront(int entry);
void addToBack(int entry);
int popFront();
int popBack();
void sort();
};
DblLinkList::DblLinkList()
{
head = NULL;
last = NULL;
count = 0;
}
void DblLinkList::addToFront(int entry)
{
DLNode* tmpDLNode = new DLNode();
tmpDLNode->data = entry;
head->prev = tmpDLNode;
tmpDLNode->next = head;
head = tmpDLNode;
head->prev = NULL;
count++;
if (last==NULL)
last=tmpDLNode;
//cout << head->data << endl;
//cout << last->data << endl;
}
void DblLinkList::addToBack(int entry)
{
DLNode* tmpDLNode = new DLNode();
tmpDLNode->data = entry;
tmpDLNode->next = NULL;
tmpDLNode->prev = NULL;
if (head==NULL) //if list is empty
{
head=tmpDLNode;
last=tmpDLNode;
}
else //if list is not empty
{
tmpDLNode->prev = last;
last->next = tmpDLNode;
last = tmpDLNode;
last->next = NULL;
//cout << head->data << endl;
//cout << last->data << endl;
}
count++;
}
int DblLinkList::popFront()
{
DLNode* trash;
int popval;
if (head==NULL)
cout << "List empty, nothing to pop." << endl;
else
{
trash = head;
popval = head->data;
head = head->next;
head->prev = NULL;
count--;
delete trash;
}
return popval;
}
int DblLinkList::popBack()
{
DLNode* trash;
int popval;
if (head==NULL)
cout << "List empty, nothing to pop." << endl;
else if (head==last)
popFront();
else
{
trash = last;
popval = last->data;
last = last->prev;
last->next = NULL;
count--;
delete trash;
}
return popval;
}
void DblLinkList::displayForwards()
{
DLNode* yad;
yad = head;
while (yad != NULL)
{
cout << yad->data << " ";
yad = yad->next;
}
cout << endl;
}
void DblLinkList::displayBackwards()
{
DLNode* yad;
yad = last;
while (yad != NULL)
{
cout << yad->data << " ";
yad = yad->prev;
}
cout << endl;
}
int DblLinkList::getCount()
{
return count;
}
//private function used only to implement sort()
void DblLinkList::splitList(DLNode* first1, DLNode* &first2)
{
DLNode* middle;
DLNode* current;
if(first1==NULL)
first2 = NULL;
else if (first1->next == NULL)
first2 = NULL;
else
{
middle = first1;
current = first1->next;
if (current != NULL)
current = current->next;
while (current != NULL)
{
middle = middle->next;
current = current->next;
if (current != NULL)
current = current->next;
}
first2 = middle->next;
middle->next = NULL;
first2->prev = NULL;
}
}
DLNode* DblLinkList::mergeList(DLNode* first1, DLNode* first2)
{
DLNode* lastSmall;
DLNode* newHead;
if (first1==NULL)
return first2;
else if (first2==NULL)
return first1;
else
{ //first figure out which list's head should be the head of the merged list
if (first1->data < first2->data)
{
newHead = first1;
first1 = first1->next;
lastSmall = newHead;
}
else
{
newHead = first2;
first2 = first2->next;
lastSmall = newHead;
}
while ((first1 != NULL) && (first2 != NULL))
{
if (first1->data < first2->data)
{
lastSmall->next = first1;
lastSmall = lastSmall->next;
first1 = first1->next;
}
else
{
first2->prev = lastSmall;
lastSmall->next = first2;
lastSmall = lastSmall->next;
first2 = first2->next;
}
}
if (first1 == NULL)
lastSmall->next = first2;
else
lastSmall->next = first1;
return newHead;
}
}
void DblLinkList::recMergeSort(DLNode* &head)
{
DLNode* otherHead;
if (head != NULL)
if (head->next != NULL)
{
splitList(head, otherHead);
recMergeSort(head);
recMergeSort(otherHead);
head = mergeList(head,otherHead);
}
}
//public sort function
void DblLinkList::sort()
{
recMergeSort(head);
if (head == NULL)
last = NULL;
else
{
last = head;
while (last->next != NULL)
last = last->next;
}
}
这是一个测试它的驱动程序:
#include <iostream>
#include "DblLinkList.h" //the doubly-linked list class above
using namespace std;
int main()
{
DblLinkList myDLList;
myDLList.addToBack(10);
myDLList.addToBack(40);
myDLList.addToBack(30);
myDLList.addToBack(20);
myDLList.addToBack(50);
myDLList.addToBack(70);
myDLList.addToBack(80);
myDLList.addToBack(60);
myDLList.addToBack(90);
myDLList.addToBack(100);
myDLList.displayForwards();
myDLList.displayBackwards();
myDLList.sort();
myDLList.displayForwards();
myDLList.displayBackwards();
cout << myDLList.getCount() << endl;
system("pause");
return 0;
}
如果你可以运行它,你会看到displayForwards正确显示了排序列表,但是displayBackwards没有反向显示。
我希望我已经提供了足够的帮助信息!我想合并步骤的一部分必须是错误的,其中有向后链接,我只是看不到它!
欢呼,并提前感谢!答案 0 :(得分:0)
合并步骤中的主要问题发生在首先耗尽一个子列表的情况下。另一个列表的其余部分将附加到合并列表的末尾,但不会保留任何prev指针。在mergeList()的底部,它应该如下所示:
if (first1 == NULL) {
lastSmall->next = first2;
first2->prev = lastSmall; <------
}
else {
lastSmall->next = first1;
first1->prev = lastSmall; <------
}
return newHead;
此外,主循环中的不对称似乎是一个错误
while ((first1 != NULL) && (first2 != NULL))
{
if (first1->data < first2->data)
{
first1->prev = lastSmall; <------ missing?
lastSmall->next = first1;
lastSmall = lastSmall->next;
first1 = first1->next;
}
else
最后,有一些地方没有正确处理单个元素列表,例如addToFront()。
希望有所帮助!