[英]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.