(FYI, first ever post to StackOverflow)
I am trying to implement a merge sort for doubly-linked lists in C++. While the sort does work, it's not rebuilding the list properly. It seems to be coming out as a singly-linked list with no "previous" pointers; the list can be read forward, but when I try to display it backwards, only the last node is shown. I think something must be wrong with the "merge" routine but I can't find where it is.
To start, here is the code for the doubly-linked node of which the list is made:
#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;
}
Here is the doubly-linked list class, stripped down to only those functions needed to build up a list and sort it: (FYI, this follows the algorithm presented in "C++ Programming: Program Design Including Data Structures", 6th ed. by D.S. 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;
}
}
Here is a driver program to test it:
#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;
}
If you can run this, you'll see that the sorted list is shown properly by displayForwards, but not shown in reverse by displayBackwards.
I hope I've provided enough information for help! I guess something must be wrong with the part of the merge step where the backwards link is made, I just don't see it!
cheers, and thanks in advance!