力扣刷题148:归并对链表排序c++

解题思路:

1.先分割:
寻找链表中点,将链表分成两个子链表,中点用快慢指针找,慢指针走一步,快指针走两步,慢指针到中点时,快指针到末尾,
2.再合并
对列表排序,合并两个排好序的列表

代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 
 */
class Solution {
public:
    ListNode* sortList(ListNode* head) {
        return depart(head, nullptr);//进入归并
    }
    //1.分割  分割截至的条件是当前链表长度为1.即头指针下一个节点是空
    //处理归并排序问题,下面两种场景不需要分和操作
    ListNode* depart(ListNode* head,ListNode* tail){
        if(head == nullptr){ //第一种场景是头指针是否为空
            return head;//返回此节点
        }
        if(head->next == tail){//第二种场景是头指针的下一个指针是否是尾部
            head->next = nullptr;//尾部也指向为空,分割到只剩一个节点了
            return head;//返回此节点
        }
        ListNode* slow = head,*fast = head;//定义快慢两个指针都指向头节点
        while(fast != tail){//当快指针没有到尾部,就一直循环
            slow = slow->next;//慢指针指向下一个
            fast = fast->next;//快指针也指向下一个,
            if(fast != tail){//判断快指针是否到末尾,因为存在奇数链表
                fast = fast->next;//如果没到的话就再走一步
            }
        }
        ListNode* mid = slow;
        return merge(depart(head,mid),depart(mid,tail));//将链表分开的部分合并
    }
    //2.排序合并
    ListNode* merge(ListNode* head1,ListNode* head2){
      ListNode* dumyHead = new ListNode(0);//创建一个空链表
      ListNode* temp = dumyHead, *temp1 = head1, *temp2 = head2;//用temp代替dumyHead,否则dumyHead一直会变,定义两个指针,
      while(temp1 != nullptr && temp2 != nullptr){//左指针和右指针的数都不为空
          if(temp1->val <= temp2->val){//左指针指向的值小于右指针的值
              temp->next = temp1;//把左指针的地址放到新链表第一个位置
              temp1 = temp1->next;//左指针向右走一步
          }else{
              temp->next = temp2;//否则把右指针的地址放到新链表第一个位置
              temp2 = temp2->next;//右指针向右走一步
          }
         temp = temp->next;//左右序列都为空后,新列表指针向后走一步
      }
      if(temp1 != nullptr){//判断左序列是否为空
          temp->next = temp1;//不为空把最后的一个地址放到新链表
      }else if(temp2 != nullptr){//判断右序列是否为空
          temp->next = temp2;//不为空把最后的一个地址放到新链表
      }
      return dumyHead->next;//最终返回排好序的新链表
    }

};

你可能感兴趣的:(力扣刷题,链表,归并,c++)