试图使用链接列表实现冒泡排序,但不起作用

问题描述

试图使用链表实现冒泡排序,但不起作用。谁能在我的代码中识别出问题。我认为在类singlylinkedist中有一个名为bubblesort函数,其中的for循环不起作用,用于对链表进行完全排序。它只会对列表进行一次排序,而不会对链表的大小进行排序。

#include<iostream>

using namespace std;

class Node{
    public:
        int data;
        Node *next;
        
    Node()
    {
        data = 0;
        next = NULL;
    }
    
    Node(int d)
    {
       data = d;
    }
};

class singlylinkedlist{
    public:
        Node *head,*tail;
        
        singlylinkedlist()
        {
            head = NULL;
            tail = NULL;
        }
        
        void appendNode(Node *temp)
        {
          if (head == NULL) 
          {
            head = temp;
            tail = temp;
            cout << "Node Appended" << endl;
          } 
          else 
          {
            tail->next = temp;
            tail = tail->next;
            cout << "Node Appended" << endl;
           }
        }
        
        void prependNode(Node *temp)
        {
            temp->next = head;
            head = temp;
            cout<< "Node Prepended" << endl;
        }
        
        int getdata(int pos)
        {
            Node *curr = new Node;
            curr = head;
            for(int i=1;i<pos;i++)
            {
                curr = curr->next;
            }
            return curr->data;
        }
        
        void printList() 
        {
            if (head == NULL) 
            {
              cout << "No Nodes in Singly Linked List";
            } 
            else 
            {
              cout << endl << "Singly Linked List Values : ";
              Node *temp = head;
         
              while (temp != NULL) 
              {
                cout << "--> "<<temp -> data;
                temp = temp -> next;
              }
              cout<<"\n";
            }
         }
         
         int ListSize() 
        {
            int count=0;
            if (head == NULL) 
            {
              cout << "No Nodes in Singly Linked List";
            } 
            else 
            {
              Node *temp = head;
         
              while (temp != NULL) 
              {
                temp = temp -> next;
                count = count+1;
              }
            }
            return count;
         }
         
         void bubblesort(Node *temp)
         {
            temp= head;
            Node *ptr;
            Node *prev = NULL;
            
            for(int j=0;j<ListSize();j++)
            {
                while(temp!=NULL && temp->next!=NULL){
                    
                    if(temp->data  > temp->next->data){
                        
                        if(prev == NULL){
                           ptr = temp->next;
                           temp->next = ptr->next;
                           ptr->next = temp;
                           head = prev = ptr;
                        }
                        
                        else{
                            ptr = temp->next;
                            prev->next = ptr;
                            temp->next = ptr->next;
                            ptr->next = temp;
                            prev = ptr;
                            
                        }  
                       
                     }
                     
                     else{
                        ptr = temp->next;
                        prev = temp;
                        temp = ptr;
                     }
                }
             }
                
        }
};

int main()
{
   singlylinkedlist s;
   int option;
   int data1;
   int pos;
   
   do{
    cout << "\nWhat operation do you want to perform? Select Option number. Enter 0 to exit." << endl;
    cout << "1. appendNode()" << endl;
    cout << "2. prependNode()" << endl;
    cout << "3. getdata()" << endl;
    cout << "6. printList()"  << endl;
    cout << "7. bubblesort()" << endl;
    
    cin>>option;
    
    Node *temp = new Node;
    
    switch (option) {
    case 0:
      break;
    case 1:
      cout << "Append Node Operation \nEnter data of the Node to be Appended" << endl;
      cin >> data1;
      temp->data = data1;
      temp->next = NULL;
      s.appendNode(temp);
      break;
    
    case 2:
       cout<<"Prepend Node Operation \nEnter data of the Node to be Prepended" << endl;
       cin>>data1;
       temp->data = data1;
       temp->next = NULL;
       s.prependNode(temp);
       break;
    
    case 3:
        cout<<"enter position to get data"<<endl;
        cin>>pos;
        cout<<"DATA AT GIVEN INDEX IS " << s.getdata(pos);
        break;
    
    case 6:
      s.printList();
      break;
      
    case 7:
      s.bubblesort(temp);
      s.printList();
      break;
    } 

}while (option != 0);

}

解决方法

撇开其余残破的代码,排序的主要问题是无法在最外层循环的每次迭代中重置prevtemp。列表的每次扫描都需要将其重置(prev应该重新启动为null,temp应该重新启动为head。这样做是:

void bubblesort()
{
    for(int j=0;j<ListSize();j++)
    {
        Node *prev = nullptr;
        Node *temp = head;
        
        while(temp != nullptr && temp->next != nullptr)
        {
            if(temp->data  > temp->next->data)
            {
                
                if(prev == nullptr)
                {
                    Node *ptr = temp->next;
                    temp->next = ptr->next;
                    ptr->next = temp;
                    head = prev = ptr;
                }
                else
                {
                    Node *ptr = temp->next;
                    prev->next = ptr;
                    temp->next = ptr->next;
                    ptr->next = temp;
                    prev = ptr;
                }
            }
            else
            {
                Node *ptr = temp->next;
                prev = temp;
                temp = ptr;
            }
        }
    }
}

替代

一些注意事项。这只是半气泡排序。 Bubblesort的重点是,每次扫描时,“最大”节点都会冒泡到末端。例如。它不再需要再次访问,因为 nothing 会“更大”(这就是它首先冒泡到最后的方式)。但是,使用您的算法,您会反复扫描整个列表,而不是比先前的迭代少一个少的节点。

执行此操作的一种简单方法是在列表末尾将其从列表中卸下,然后将其移至整个新链的最前面。然后该算法变为。

  1. 扫描列表,将活动列表的最大节点起泡到最后
  2. 从该列表中删除节点,并将其添加到新链之前。
  3. 继续(1)和(2),直到旧列表中没有更多节点为止。
  4. 新链现在是新列表。设置head,您就完成了。

以可视方式进行此操作,假设我们列表中有五个元素,最初是一个空的“结果”列表。

list: 7 4 5 2 6
result: null

在(1)和(2)的第一遍之后,我们得到:

list: 4 5 2 6
result: 7

第二遍:

list: 4 2 5
result: 6 7

第三遍:

list: 2 4
result: 5 6 7

第四遍:

list: 2
result: 4 5 6 7

最后:

list: null
result 2 4 5 6 7

这时,我们可以简单地将list设置为result,现在我们的列表已排序。

以下是使用指针到指针方法实现此目的的实现。请注意,我们无需在任何地方获取或关心列表大小(即,无需调用ListSize())。

void bubblesort()
{
    Node *result = nullptr;
    while (head != nullptr)
    {
        // starts at the beginning of the list
        Node **pp = &head;
        while ((*pp)->next != nullptr)
        {
            Node **pp2 = &(*pp)->next;
            if ((*pp2)->data < (*pp)->data)
            {
                // swap pointers,then swap back their next members.
                std::swap(*pp,*pp2);
                std::swap((*pp)->next,(*pp2)->next);
            }
            
            // advance to next node in the list.
            pp = &(*pp)->next;
        }
        
        // prepend to new list,unlink from old one.
        (*pp)->next = result;
        result = *pp;
        *pp = nullptr;
    }
    
    // new list is built
    head = result;
}

测试

在{1..99}中生成二十个值的随机序列,打印,然后排序,然后再次打印。对于香料,首先会生成所有奇数值;所有偶数值都被附加。列表建立后,我们将气泡松开,然后打印最终结果。

#include <iostream>
#include <utility>
#include <random>

class Node{
public:
    int data;
    Node *next;
    
    Node(int d=0)
        : data(d),next(nullptr)
    {
    }
};

class singlylinkedlist{
public:
    Node *head,*tail;
    
    singlylinkedlist()
        : head(nullptr),tail(nullptr)
    {
    }
    
    ~singlylinkedlist()
    {
        while (head)
        {
            Node *tmp = head;
            head = head->next;
            delete tmp;
        }
    }
    
    // squelch these; copying not supported.
    singlylinkedlist(const singlylinkedlist&) = delete;
    singlylinkedlist& operator =(const singlylinkedlist&) = delete;
    
    void appendNode(int data)
    {
        Node *p = new Node(data);
        if (head == nullptr)
            head = p;
        else
            tail->next = p;
        tail = p;
    }
    
    void prependNode(int data)
    {
        Node *p = new Node(data);
        p->next = head;
        if (head == nullptr)
            tail = p;
        head = p;
    }
    
    int getdata(int pos)
    {
        Node *curr = head;
        while (curr != nullptr && pos-- > 0)
            curr = curr->next;
        return curr ? curr->data : 0; // TODO: throw an exception if out of range?
    }
    
    void printList() const
    {
        for (const Node *p = head; p != nullptr; p = p->next)
            std::cout << p->data << ' ';
        std::cout << '\n';
    }
    
    int size() const
    {
        int count=0;
        for (const Node *p = head; p != nullptr; p = p->next)
            ++count;
        return count;
    }

    void bubblesort()
    {
        Node *result = NULL;
        while (head != nullptr)
        {
            // starts at the beginning of the list
            Node **pp = &head;
            while ((*pp)->next != nullptr)
            {
                Node **pp2 = &(*pp)->next;
                if ((*pp2)->data < (*pp)->data)
                {
                    // swap pointers,then swap back their next members.
                    std::swap(*pp,*pp2);
                    std::swap((*pp)->next,(*pp2)->next);
                }
                
                // advance to next node in the list.
                pp = &(*pp)->next;
            }
            
            // link to new list,unlink from old one.
            (*pp)->next = result;
            result = *pp;
            *pp = nullptr;
        }
        
        // new list is built
        head = result;
    }
    
};

int main()
{
    // fixed seed for repetitive testing. replace 42 with
    //  std::random_device{}() for random sequence
    std::mt19937 rng{ 42 };
    std::uniform_int_distribution<> dist(1,99);
    
    singlylinkedlist s;
    for (int i=0; i<20; ++i)
    {
        int data = dist(rng);
        if (data % 2)
            s.prependNode(data);
        else
            s.appendNode(data);
    }
    s.printList();
    
    s.bubblesort();
    s.printList();
}

输出

53 3 75 75 87 83 21 61 15 93 52 72 88 24 22 2 88 30 38 2 
2 2 3 15 21 22 24 30 38 52 53 61 72 75 75 83 87 88 88 93