[英]Trouble implementing merge sort on doubly-linked list in C++
(仅供参考,首次发布到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;
}
这是一个双向链接的列表类,仅精简了构建列表并对其进行排序所需的那些功能:(FYI,这遵循DS第六版“ C ++编程:包括数据结构的程序设计”中介绍的算法。马利克)
#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却未将其反向显示。
希望我已提供足够的信息以寻求帮助! 我想在合并步骤中进行向后链接的部分一定有问题,我只是看不到!
干杯,并预先感谢!
合并步骤中的主要问题发生在首先用尽一个子列表的情况下。 另一个列表的其余部分被追加到合并列表的末尾,但是没有任何prev指针被维护。 在mergeList()的底部,它应如下所示:
if (first1 == NULL) {
lastSmall->next = first2;
first2->prev = lastSmall; <------
}
else {
lastSmall->next = first1;
first1->prev = lastSmall; <------
}
return newHead;
此外,主while循环中存在不对称现象,这似乎是一个错误
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()。
希望有帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.