归并排序
图示
算法描述
把待排序序列分为若干个有序的子序列,再把有序的子序列合并为整体有序序列
- 申请空间,使其大小为两个已经排好序的数组的长度之和
- 把两个有序的数组通过比较桉顺序放到申请的空间中
- 把在申请空间上存放的元素复制到原数组相应的位置上
参考代码
void merge(int *a, int beg, int mid, int end) { int *p = new int[end - beg + 1]; int i = beg, j = mid+1, k = 0; for (; i <= mid && j <= end;) { if (a[i] < a[j]) { p[k++] = a[i++]; } else { p[k++] = a[j++]; } } while (i <= mid) p[k++] = a[i++]; while (j <= end) p[k++] = a[j++]; for (i = 0; i < k; ++i) a[beg + i] = p[i]; delete []p; } void mergeSort(int *a, int beg, int end) { if (a == NULL || beg >= end) return; else if (beg + 1 == end) { if (a[beg] > a[end]) swap(a[beg], a[end]); } else { int mid = beg + (end - beg) / 2; mergeSort(a, beg, mid); mergeSort(a, mid + 1, end); merge(a, beg, mid, end); } }
测试
#include <iostream> using namespace std; void merge(int *a, int beg, int mid, int end) { int *p = new int[end - beg + 1]; int i = beg, j = mid+1, k = 0; for (; i <= mid && j <= end;) { if (a[i] < a[j]) { p[k++] = a[i++]; } else { p[k++] = a[j++]; } } while (i <= mid) p[k++] = a[i++]; while (j <= end) p[k++] = a[j++]; for (i = 0; i < k; ++i) a[beg + i] = p[i]; delete []p; } void mergeSort(int *a, int beg, int end) { if (a == NULL || beg >= end) return; else if (beg + 1 == end) { if (a[beg] > a[end]) swap(a[beg], a[end]); } else { int mid = beg + (end - beg) / 2; mergeSort(a, beg, mid); mergeSort(a, mid + 1, end); merge(a, beg, mid, end); } } void tranverse(int *a, int len) { for(int i = 0; i < len; ++i) { cout << a[i] << " "; } cout << endl; } int main() { int a[] = {3, 9, 0, 1, 3, 2, 2, 7}; int len = sizeof(a) / sizeof(int); tranverse(a, len); mergeSort(a, 0, len-1); tranverse(a, len); }
复杂度
- 空间复杂度:O(n)
- 时间复杂度: 最好 最坏 平均 统统O(nlogn)
稳定性
稳定
应用
数组中的逆序对。例如{7,5,6,4}的逆序对有(7,5)(7,6)(7,4)(5,4)(6,4)总共5个
思路
其实就是归并排序中,两个数字交换的次数 + 归并有序数组时后一个数组元素大于前一个数字元素的个数之和。
参考代码
数组
#include <iostream> using namespace std; int num = 0; void Merge(int *a, int left, int mid, int right) { int *tmp = new int[right - left + 1]; int i, j, k; for(i = left, j = mid+1, k = 0; i <= mid && j <= right;) { if(a[i] <= a[j]) tmp[k++] = a[i++]; else { tmp[k++] = a[j++]; num += (mid - i + 1); } } while(i <= mid) tmp[k++] = a[i++]; while(j <= right) tmp[k++] = a[j++]; for(i = 0; i < right - left + 1; ++i) a[left + i] = tmp[i]; delete []tmp; } void MergeSort(int *a, int left, int right) { if(left == right) return; if(left + 1 == right) { if(a[left] > a[right]) { int tmp = a[left]; a[left] = a[right]; a[right] = tmp; ++num; } } else { int mid = left + (right - left) / 2; MergeSort(a, left, mid); MergeSort(a, mid + 1, right); Merge(a, left, mid, right); } } int main() { int a[] = {8, 3, 3, 4, 1}; int size = sizeof(a) / sizeof(*a); MergeSort(a, 0, size - 1); for(int i = 0; i < size; ++i) { cout << a[i] << endl; } cout << "num:" << num << endl; }
链表
#include <iostream> using namespace std; struct ListNode { int val; ListNode *next; ListNode(int v) : val(v), next(NULL) {}; }; void Traverse(ListNode *root) { while (root != NULL) { cout << root->val << " "; root = root->next; } cout << endl; } ListNode *Merge(ListNode *pa, ListNode *pb) { if (pa == NULL) return pb; if (pb == NULL) return pa; ListNode *rev = NULL; if (pa->val < pb->val) { rev = pa; rev->next = Merge(pa->next, pb); } else { rev = pb; rev->next = Merge(pa, pb->next); } return rev; } void FrontBackSplit(ListNode *root, ListNode *&pa, ListNode *&pb) { ListNode *fast; ListNode *slow; if (root == NULL || root->next == NULL) { pa = root; pb = NULL; } fast = root->next; slow = root; while (fast != NULL) { fast = fast->next; if (fast != NULL) { fast = fast->next; slow = slow->next; } } pa = root; pb = slow->next; slow->next = NULL; } void Mergesort(ListNode *&root) { if (root == NULL || root->next == NULL) return; ListNode *pa; ListNode *pb; FrontBackSplit(root, pa, pb); Mergesort(pa); Mergesort(pb); root = Merge(pa, pb); } int main() { ListNode *root = new ListNode(0); ListNode *p1 = new ListNode(1); ListNode *p2 = new ListNode(0); ListNode *p3 = new ListNode(3); ListNode *p4 = new ListNode(4); ListNode *p5 = new ListNode(8); ListNode *p6 = new ListNode(6); ListNode *p7 = new ListNode(7); ListNode *p8 = new ListNode(2); ListNode *p9 = new ListNode(2); root->next = p1; p1->next = p2; p2->next = p3; p3->next = p4; p4->next = p5; p5->next = p6; p6->next = p7; p7->next = p8; p8->next = p9; Traverse(root); Mergesort(root); Traverse(root); }