递归合并排序错误

时间:2015-04-07 15:45:46

标签: c++ sorting recursion merge

我正在使用C ++为自己的链表类编写自己的合并排序函数。我测试了我的Split_List和Merge函数,它们运行良好。但是我遇到了Merge_Sort递归函数的问题:它可以合并排序链表的左右部分,但最终合并整个链表时会出错。

输出:

第一份清单: [100] - > [2] - > [37] - > [ - 10] - > |||

排序第一个清单: [37] - > [100] - > |||

node.h

#ifndef NODE_H
#define NODE_H
#include <iostream>

template <typename T>
class node{
public:
    node(const T& data){item=data; link=NULL;}
    int item;
    node* link;
};

#endif // NODE_H

linked_list.h

#ifndef Linked_List_H
#define Linked_List_H
#include "node.h"
#include <iostream>

using namespace std;

template<typename T>
class Linked_List{
public:
    Linked_List(){tail=head=NULL; count=0;}
    void Insert_Head(const T& item);
    void Append_Tail(const T& item);
    void Insertion_Sort();
    void Merge_Sort();
    void Print();
    int Size() {return count;}
private:
    node<T>* head;
    node<T>* tail;
    int count;
    void InsertHead(node<T>* &list_head, const T& item);
    void InsertBefore(node<T>* &list_head, node<T>* here, const T& item);
    void Append_Tail(node<T>* &list_head, node<T>* end);
    void Delete(node<T>* &list_head, node<T>* deleteHere);
    node<T>* DeleteHead(node<T>* &list_head);
    void Merge_Sort(node<T>* list_head, int size);
    node<T>* Merge(node<T>* left, node<T>* right);
    node<T>* Split_List(node<T>* list_head, int size);
    void Print(node<T>* list_head);
};

template<typename T>
void Linked_List<T>::Merge_Sort(){
    Merge_Sort(head, count);
}

template<typename T>
void Linked_List<T>::Merge_Sort(node<T>* list_head, int size){
    int n1;
    int n2;
    node<T>* right_head;

    if(size>1){
        right_head=Split_List(list_head, size);
        n1=size/2;
        n2=size-n1;
        Merge_Sort(list_head, n1);
        Merge_Sort(right_head, n2);
        head=Merge(list_head, right_head);
    }
}

template<typename T>
node<T>* Linked_List<T>::Split_List(node<T>* list_head, int size){
    if (size==0){
        return NULL;
    }else if (size==1){
        return list_head;
    }else{
        node<T>* iter=list_head;
        node<T>* right_head=NULL;
        int i=0;
        while (i<size/2-1){
            iter=iter->link;
            i++;
        }
        right_head=iter->link;
        iter->link=NULL;
        return right_head;
    }
}

template<typename T>
node<T>* Linked_List<T>::Merge(node<T>* left, node<T>* right){
    node<T>* newHead=NULL;
    while (left!=NULL && right!=NULL){
        if (left->item<=right->item){
            Append_Tail(newHead, DeleteHead(left));
        }else{
            Append_Tail(newHead, DeleteHead(right));
        }
    }
    if (left==NULL){
        while (right!=NULL){
            Append_Tail(newHead, DeleteHead(right));
        }
    }else{
        while (left!=NULL){
            Append_Tail(newHead, DeleteHead(left));
        }
    }
    return newHead;
}


template<typename T>
void Linked_List<T>::Insertion_Sort(){
    node<T>* end=head;
    while (end!=NULL){
        for (node<T>* iter=head; iter!=end; iter=iter->link){
            if (iter->item>=end->item){
                InsertBefore(head, iter, end->item);
                Delete(head, end);
                break;
            }
        }
        end=end->link;
    }
}

template<typename T>
void Linked_List<T>::Insert_Head(const T& item){
    InsertHead(head, item);
}

template<typename T>
void Linked_List<T>::InsertHead(node<T>* &list_head, const T& item){
    node<T>* tempPtr=new node<T> (item);     //create new node
    tempPtr->link=list_head;         //connect the new node to orignal 1st node
    list_head=tempPtr;               //make the head point to the new node as the new 1st node
    count++;
}

template <typename T>
void Linked_List<T>::InsertBefore(node<T>* &list_head, node<T>* here, const T& item){
    if (list_head==NULL || list_head==here)
    {
        InsertHead(head, item);      //add "head" node
        return;
    }else{
        node<T>* tempPtr=new node<T>(item);     //create new node

        node<T>* previous=head;
        while (previous->link!=here){
            previous=previous->link;        //if the previous node cannot be found, go to the link node
        }
        tempPtr->link=here;                 //if the previous node is found, connect the new node to "here" node
        previous->link=tempPtr;
        count++;
    }
}

template<typename T>
void Linked_List<T>::Append_Tail(const T& item){
    if (head==NULL)
    {
        InsertHead(head, item);      //add "head" node
        tail=head;
    }else{
        node<T>* tempPtr=new node<T>(item);     //create new node
        tail->link=tempPtr;
        tail=tail->link;
        count++;
    }
}

template<typename T>
void Linked_List<T>::Append_Tail(node<T>* &list_head, node<T>* end){
    if (list_head==NULL)
    {
        end->link=list_head;         //connect the new node to orignal 1st node
        list_head=end;               //make the head point to the new node as the new 1st node
        count++;
        tail=list_head;
    }else{
        tail->link=end;
        tail=tail->link;
        count++;
    }
}

template<typename T>
void Linked_List<T>::Delete(node<T>* &list_head, node<T>* deleteHere){
    node<T>* here=list_head;
    if (here==NULL)
    {
        cout<<"Empty linked list!";             //empty linked list
        return;
    }
    else{
        node<T>* previous=list_head;
        if (deleteHere==list_head){
            list_head=deleteHere->link;              //if the deleted node is the 1st node, let the head point to the link node
            count--;
        }
        else{
            while (previous->link!=deleteHere){
                previous=previous->link;        //if the previous node cannot be found, go to the link node
            }
            previous->link=deleteHere->link;
            //if the previous node is found, connect the previous node to the node after the deleted node
            count--;
        }
    }
}

template<typename T>
node<T>* Linked_List<T>::DeleteHead(node<T>* &list_head){
    node<T>* deleted=list_head;
    list_head=list_head->link;              //if the deleted node is the 1st node, let the head point to the link node
    count--;
    deleted->link=NULL;
    return deleted;
}


template<typename T>
void Linked_List<T>::Print(){
    Print(head);
}

template<typename T>
void Linked_List<T>::Print(node<T>* list_head){
    node<T>* iter;
    for (iter=list_head; iter!=NULL; iter=iter->link){
        cout<<"["<<(iter->item)<<"]->";
    }
    cout<<"|||"<<endl<<endl;
}

#endif // Linked_List_H

的main.cpp

#include <iostream>
#include "linked_list.h"

using namespace std;

int main()
{
    Linked_List<int> list1;
    list1.Insert_Head(-10);
    list1.Insert_Head(37);
    list1.Insert_Head(2);
    list1.Insert_Head(100);
    cout<<"1st list: "<<endl;
    list1.Print();

    cout<<"sorted 1st list: "<<endl;
    list1.Merge_Sort();
    list1.Print();
}

1 个答案:

答案 0 :(得分:1)

如果您在代码中添加了一些过多的Print来电,您就会看到问题所在。您可以正确排序size-2列表,但在顶级列表中,在:

之后
Merge_Sort(list_head, n1);
Merge_Sort(right_head, n2);

list_head将成为列表[100]->|||right_head将成为列表[37]->|||。你实际上正在合并和排序,只是那些指针没有改变,所以你开始:

[100] -> [2] -> Nil
  ^
  list_head

最后:

[2] -> [100] -> Nil
         ^
         list_head

和其他名单一样。因此,只要您担心这一点,您只需合并两个大小为1的列表,这些列表就是您正确执行的 - 这就是您最终只使用37100的方式。

这应该指向正确的方向。