BM12 单链表的排序
描述
给定一个节点数为n的无序单链表,对其按升序排序。
数据范围:
要求:时间复杂度 
示例1
输入:
{1,3,2,4,5}复制返回值:
{1,2,3,4,5}复制
示例2
输入:
{-1,0,-2}复制返回值:
{-2,-1,0}题解
思路:
对于链表的排序,其实也可以借鉴数组排序。比如冒泡排序、插入排序、选择排序等也可以很容易的在链表上使用。这里借鉴归并排序的思想对链表进行 排序。通过以下几个步骤完成:
- 找到链表的尾节点
- 以头尾节点为参数进行归并排序
- 归并排序:
- 找到头尾节点的中间节点,以中间节点为界将链表划分成2部分,一定要将中间节点的next指针设置为空
- 对划分后的2个链表分别使用归并排序,得到2个有序的链表
- 将2个有序链表连接起来,得到新的有序链表
- 排序完成
struct ListNode
{
  int val;
  struct ListNode *next;
  ListNode(int x) : val(x), next(nullptr)
  {
  }
  ListNode() = default;
};
void swap_node(ListNode *left, ListNode *right)
{
  std::swap(left->val, right->val);
}
ListNode *find_mid_node(ListNode *left, ListNode *right)
{
  ListNode *slow = left;
  ListNode *fast = left;
  while (fast != right && fast->next != right)
  {
    slow = slow->next;
    fast = fast->next->next;
  }
  return slow;
}
ListNode *link_sorted_list(ListNode *left, ListNode *right)
{
  if (left == nullptr)
  {
    return right;
  }
  if (right == nullptr)
  {
    return left;
  }
  if (left->val > right->val)
  {
    return link_sorted_list(right, left);
  }
  auto head = left;
  auto tail_node = head;
  left = left->next;
  // 这里其实是可以优化的,当某一个链表的指针为空的时候,跳出循环,然后直接让tail_node->next指向非空链表即可!!
  while (left != nullptr || right != nullptr)
  {
    if (left == nullptr)
    {
      auto next = right->next;
      tail_node->next = right;
      tail_node = tail_node->next;
      right = next;
      continue;
    }
    if (right == nullptr)
    {
      auto next = left->next;
      tail_node->next = left;
      tail_node = tail_node->next;
      left = next;
      continue;
    }
    if (left->val <= right->val)
    {
      tail_node->next = left;
      left = left->next;
      tail_node = tail_node->next;
    }
    else
    {
      tail_node->next = right;
      right = right->next;
      tail_node = tail_node->next;
    }
  }
  return head;
}
ListNode *merge_sort(ListNode *left, ListNode *right)
{
  if (left == nullptr)
  {
    return right;
  }
  if (right == nullptr)
  {
    return left;
  }
  if (left == right)
  {
    return left;
  }
  auto mid_node = find_mid_node(left, right);
  auto next_node = mid_node->next;
  mid_node->next = nullptr;
  auto pre_list = merge_sort(left, mid_node);
  auto after_list = merge_sort(next_node, right);
  return link_sorted_list(pre_list, after_list);
}
ListNode *sortInList(ListNode *head)
{
  if (head == nullptr || head->next == nullptr)
  {
    return head;
  }
  auto cur_node = head;
  while (cur_node->next != nullptr)
  {
    cur_node = cur_node->next;
  }
  return merge_sort(head, cur_node);
}
ListNode *create_list(const std::vector<int> &v)
{
  ListNode head;
  ListNode *phead = &head;
  for (auto &data : v)
  {
    auto node = new ListNode;
    node->val = data;
    node->next = nullptr;
    phead->next = node;
    phead = phead->next;
  }
  return head.next;
}
int main()
{
  // auto list = create_list(std::vector<int>{105, 25, 89, 67, 49, 38, 52});
  auto list = create_list(std::vector<int>{1, 3, 2, 4, 5});
  auto head = sortInList(list);
  while (head != nullptr)
  {
    std::cout << head->val << " ";
    head = head->next;
  }
  std::cout << std::endl;
  return 0;
}








