簡體   English   中英

在C ++中對雙向鏈接列表實現合並排序時遇到問題

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM