对线性表进行归并排序

算法流程

归并排序通常是线性表(即,链表)排序的优先选择算法。链表的慢随机访问特性使得某些排序算法(比如,快速排序)的执行效率偏低,也使得某些算法(比如,堆排序)难以实现。

链表的归并排序伪代码如下:

// Head is the head node of a linked list
MergeSort(Head)
1. 如果头节点为空或只有一个节点,则返回
2. 其次,将链表分成两个子链表
  Split(Head, &a, &b); // a, b分别为两个子链表
3. 对两个子链表进行归并排序
  MergeSort(a);
  MergeSort(b);
4. 合并已经排序的a, b两个子链表,并更新头节点
  *Head = Merge(a, b);

时间复杂度为:O(nLogn)

代码实现

  • C++

struct Node{
  int val;
  struct Node* next;
}
struct Node* Merge(struct Node* a, struct Node* b);
void Split(struct Node* head, struct Node** front, struct Node** back);
void MergeSort(struct Node** head) {
  struct Node* phead = *head;
  struct Node* a;
  struct Node* b;
  if(phead == NULL | phead->next == NULL)
    return;
  Split(head, &a, &b);
  MergeSort(&a);
  MergeSort(&b);
  *head = Merge(a, b);
}

struct Node* Merge(struct Node* a, struct Node* b) {
  struct Node* result = NULL;
  if(a == NULL)
    return b;
  else if (b == NULL)
    return a;
  if(a->val <= b->val) {
    result = a;
    result->next = Merge(a->next, b);
  } else {
    result = b;
    result->next = Merge(a, b->next);
  }
  return result;
}

void Split(struct Node* head, struct Node** front, struct Node** back) {
  struct Node* fast;
  struct Node* slow;
  if(head == NULL | head->next == NULL) {
    *front = head;
    *back = NULL;
  } else {
    slow = head;
    fast = head->next;
    while(fast != NULL) {
      fast = fast->next;
      if(fast != NULL) {
        slow = slow->next;
        fast = fast->next;
      }
    }
    *front = head;
    *back = slow->next;
    slow->next = NULL;
  }
}

最后更新于