简体   繁体   English

在C ++中对双向链接列表实现合并排序时遇到问题

[英]Trouble implementing merge sort on doubly-linked list in C++

(FYI, first ever post to StackOverflow) (仅供参考,首次发布到StackOverflow)

I am trying to implement a merge sort for doubly-linked lists in C++. 我正在尝试为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 DS Malik) 这是一个双向链接的列表类,仅精简了构建列表并对其进行排序所需的那些功能:(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;
    }
}

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. 如果可以运行此命令,则将看到displayForwards正确显示了已排序列表,但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! 干杯,并预先感谢!

The main issue in the merge step occurs in the case when one sublist is exhausted first. 合并步骤中的主要问题发生在首先用尽一个子列表的情况下。 The remainder of the other list is appended to the end of the merge list but none of the prev pointers are being maintained. 另一个列表的其余部分被追加到合并列表的末尾,但是没有任何prev指针被维护。 At the bottom of mergeList(), it should look like this: 在mergeList()的底部,它应如下所示:

    if (first1 == NULL) {
        lastSmall->next = first2;
        first2->prev = lastSmall; <------
    }
    else {
        lastSmall->next = first1;
        first1->prev = lastSmall; <------
    }
    return newHead;

Also, there asymmetry in the main while loop that seems like a mistake 此外,主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

Lastly, there are a few places where an single element list isn't being handled properly, eg addToFront(). 最后,在某些地方,单个元素列表的处理不正确,例如addToFront()。

Hope that helps! 希望有帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM