【问题标题】:Sorting Linked List C++ with pointers使用指针对链表 C++ 进行排序
【发布时间】:2013-10-25 01:25:56
【问题描述】:

我已经为这个问题苦苦挣扎了好几个小时。我的目标是仅使用指针对链表进行排序(我不能将链表放入 vec 或数组中然后排序)。我得到了指向列表头节点的指针。我可以在指针上调用的唯一方法是 head->next(下一个节点)和 head->key(存储在节点中的 int 值,用于进行比较)。我一直在过度使用我的白板,并且几乎尝试了所有我能想到的东西。

Node* sort_list(Node* head)
{
   Node* tempNode = NULL;
   Node* tempHead = head;
   Node* tempNext = head->next;

   while(tempNext!=NULL) {

       if(tempHead->key > tempNext->key) {
           tempNode = tempHead;
           tempHead = tempNext;
           tempNode->next = tempNode->next->next;
           tempHead->next = tempNode;
           tempNext = tempHead->next;
           print_list(tempHead);


        }
        else {  
            tempHead = tempHead->next;
            tempNext = tempNext->next;

        }
    }
    return head;
}

【问题讨论】:

  • 发布您尝试修复的代码。我们不介意读者 - 没有看到您尝试过的内容,就无法提供帮助。
  • 你试过什么?你在找人为你写代码吗?
  • code 抱歉,我发帖时忘记粘贴代码了。在过去的 5 个小时里,我尝试了很多事情。如果您批评我的代码,那将非常好,但一般的想法也很有帮助。 print_list 方法接收一个节点并打印出从该节点到列表末尾的节点。
  • 请将代码添加到问题中,而不是在评论中作为指向外部网站的链接。
  • 您发布的代码看起来更像是冒泡排序的尝试,并且它失去了对节点的跟踪。您应该先解决交换两个相邻元素这个更简单的问题。

标签: c++ sorting pointers


【解决方案1】:

既然是单链表,我们可以这样做:(伪代码)

bool unsorted = true;
while(unsorted) {
    unsorted = false;
    cur = head;         

    while(cur != nullptr) {
        next = cur->next;
        if(next < cur) {
            swap(cur, next)
            unsorted = true;
        }

        cur = cur->next;
    }       
}

【讨论】:

  • 我试过你的代码(很确定几个小时前我做了类似的事情)。如果我输入 5 4 3 2 1 进行排序并返回头部,它仍然返回 5 4 3 2 1。code
  • @user2113277。链接中的code 不会执行外部while 循环,因为您已排序设置为false。它直接到代码的末尾。
【解决方案2】:

我知道它很晚,但我也在寻找它,但没有找到,所以我自己做。也许它会帮助某人。 我正在使用冒泡排序(一种排序算法)对单个链表中的数据进行排序。它只是交换节点内的数据。

void sorting(){
        Node* cur1 = head;
        Node* cur2 = head;

       for (int i = 0; i < getSize(); i++) {
        for (int j = 0; j < getSize() - 1; j++) {
            if (cur1->data < cur2->data) {
                int temp = cur1->data;
                cur1->data = cur2->data;
                cur2->data = temp;

            }
            cur2 = cur2->next;
        }
         cur2 = head;
         cur1 = head->next;
         for (int k = 0; k < i; k++) {
                cur1 = cur1->next;
         }
    }
}

【讨论】:

  • 为什么需要第三个循环?你可以使用 cur1 = cur1.next;
【解决方案3】:

别难过,这比听起来要难得多。如果这是在一个数组中,那将容易得多。如果列表是双重链接的,那就更容易了。看看这段代码,它实现了一个插入排序

struct Node {
    int key;
    Node *next;
    } *NodePtr;

// do a simple selection sort http://en.wikipedia.org/wiki/Selection_sort
Node* sort_list(Node* head) {
    Node *top = nullptr; // first Node we will return this value
    Node *current = nullptr;
    bool sorted = false;
    while (sorted == false) {
        // we are going to look for the lowest value in the list
        Node *parent = head;
        Node *lowparent = head; // we need this because list is only linked forward
        Node *low = head; // this will end up with the lowest Node
        sorted = true;
        do {
            // find the lowest valued key
            Node* next = parent->next;
            if (parent->key > next->key) {
                lowparent = parent;
                low = next;
                sorted = false;
                }
            parent = parent->next;
            } while (parent->next != nullptr);
        if (current != nullptr) { // first time current == nullptr
            current->next = low;
            }
        // remove the lowest item from the list and reconnect the list
        // basically you are forming two lists, one with the sorted Nodes 
        // and one with the remaining unsorted Nodes
        current = low;
        if (current == head) { head = current->next; }
        lowparent->next = low->next;
        current->next = nullptr;
        if (top == nullptr) {
            top = current;
            }
        };
    current->next = head;
    return top;
    }

int _tmain(int argc, _TCHAR* argv []) {
    Node nodes[4];
    nodes[0].key = 3;
    nodes[1].key = 4;
    nodes[2].key = 5;
    nodes[3].key = 1;

    nodes[0].next = &nodes[1];
    nodes[1].next = &nodes[2];
    nodes[2].next = &nodes[3];
    nodes[3].next = nullptr;

    auto sortedNodes = sort_list(&nodes[0]);

    return 0;
    }

【讨论】:

    【解决方案4】:

    使用递归方法,因为它是处理链接结构的最简单方法:

    伪代码:

    SORT(head)
    if (head->next == null) 
        return
    tempNode = head->next
    SORT(tempNode)
    if (tempNode->value < head->value) 
        SWAP(head, tempNode)
        SORT(head)
    return
    

    假设你有 5 4 3 2 1

    1) 5 4 3 1 2

    2) 5 4 1 3 2

    3) 5 4 1 2 3

    4) 5 1 4 2 3

    5) 5 1 2 4 3

    ...

    n) 1 2 3 4 5

    【讨论】:

    • 返回什么?
    • 它不返回任何东西,我假设 SORT 是 void 类型。因此它不返回任何东西,因为它只交换值。
    【解决方案5】:

    假设节点是这样的:

    struct Node
    {
        Node *next;
        int key;
        Node(int x) : key(x), next(NULL) {}
    };
    

    使用插入排序算法对 List 进行排序:

    Node* sort_list(Node* head)
    {
        Node dumy_node(0);
        Node *cur_node = head;
    
        while (cur_node)
        {
            Node *insert_cur_pos =  dumy_node.next;
            Node *insert_pre_pos = NULL;
    
            while (insert_cur_pos)
            {
                if (insert_cur_pos->key > cur_node->key)
                    break;
    
                insert_pre_pos = insert_cur_pos;
                insert_cur_pos = insert_cur_pos->next;
            }
    
            if (!insert_pre_pos)
                insert_pre_pos = &dumy_node;
    
            Node *temp_node = cur_node->next;
    
            cur_node->next = insert_pre_pos->next;
            insert_pre_pos->next = cur_node;
    
            cur_node = temp_node;
        }
    
        return dumy_node.next;
    }
    

    【讨论】:

      【解决方案6】:
      int swapNode( node * &first, node * &second)
       {
          //first we will declare the 
          //previous of the swaping nodes
          node *firstprev=NULL;
          node*secprev=NULL;
          node*current=head;
          //set previous first
          while(current->next!=first)
          {
              current=current->next;
          }
          firstprev=current;
          //seting 2nd previous
          while(current->next!=second)
          {
              current=current->next;
          }
      
      // swap datas, assuming the payload is an int:
      int tempdata = first->data;
      first->data = second->data;
      second->data = tempdata;
      //swaping next of the nodes
      firstprev->next=second;
      secprev->next=first;
      }
      

      【讨论】:

        【解决方案7】:

        这是我的合并排序实现,具有 O(N*logN) 时间复杂度和恒定的附加空间。使用 C++11

        /**
         * Definition for singly-linked list.
         * struct ListNode {
         *     int val;
         *     ListNode *next;
         *     ListNode(int x) : val(x), next(NULL) {}
         * };
         */
        
        typedef pair<ListNode*, ListNode*> PP;
        
        class Solution {
        public:
            ListNode* sortList(ListNode* head) {
                if (head==nullptr)return head;
                if (head->next==nullptr) return head;
                if (head->next->next==nullptr){
                    if (head->val<=head->next->val){
                        return head;
                    }
                    else {
                        ListNode* second=head->next;
                        second->next=head;
                        head->next=nullptr;
                        return second;
                    }
                }else {
                    PP splitted=split(head);
                    return merge(sortList(splitted.first),sortList(splitted.second));
                }
            }
        
        private:  
        
            ListNode* merge(ListNode* l1, ListNode* l2) {
                ListNode * head=new ListNode(0);
                ListNode * current=head;
                if (l1==nullptr)return l2;
                if (l2==nullptr)return l1;
                do {
                    if (l1->val<=l2->val){
                        current->next=l1;
                        l1=l1->next;
                    }else{
                        current->next=l2;
                        l2=l2->next;
                    }
                    current=current->next;
                }while (l1!=nullptr && l2!=nullptr);
                if (l1==nullptr)current->next=l2;
                else current->next=l1;
                return head->next;
            }
        
            PP split(ListNode* node){
                ListNode* slow=node;
                ListNode* fast=node;
                ListNode* prev;
                while(fast!=nullptr){
                    if (fast->next!=nullptr){
                        prev=slow;
                        slow=slow->next;
                        fast=fast->next;
                    }else break;
                    if(fast->next!=nullptr){
                            fast=fast->next;
                        }
                    else break;            
                }
                prev->next=nullptr;
                return {node,slow};
            }
        
        };
        

        【讨论】:

          【解决方案8】:

          使用std::list&lt;T&gt;::sort 方法。或者如果你早熟,std::forward_list&lt;T&gt;::sort

          为什么要重新发明轮子。

          【讨论】:

            猜你喜欢
            • 2013-11-02
            • 2020-12-04
            • 2020-07-06
            • 1970-01-01
            • 2017-12-13
            • 1970-01-01
            • 1970-01-01
            • 2011-02-03
            • 2020-10-01
            相关资源
            最近更新 更多