首先我们来谈谈归并算法的思想:把一个n长度的序列拆分为n个单独的子序列,然后两两合并变为n/2个,如此反复下去,直至重新得到一个长度n的序列
在这里面我们要说说,进行合并的时候是进行有序的合并,不然也就体现不出来归并排序的优势了。下图示归并排序的过程。
经过上面的介绍我们大概可以知道,在算法的实现过程中主要包含两个部分:拆分和合并
现在我们的思想就是两个函数拆分和合并,首先拆分,拆分到单独的子序列之后向反方向调用合并函数。这样我们就可以利用递归来实现这种功能。
说了这么多都是理论,现在我们先来学习一下下面这个题:
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
因为两个链表均排过序,所以,我们可以用两个“指针”分别指向两个链表的头部,如果其中一个比另一个小,移动小的那个链表的指针并把小结果放在返回链表中,反之也是这样;一直这样操作下去,直到有一个指针已经超过数组范围。这种方法的时间复杂度为O(m+n),m和n分为为两个链表的长度。下面贴出代码:
struct ListNode { //结点 int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { } }; ListNode* Merge(ListNode* pHead1, ListNode* pHead2) { if (pHead1 == NULL) return pHead2; if (pHead2 == NULL) return pHead1; ListNode *newListNode = NULL; //一个遍历存结果,一个用于返回 ListNode *head = NULL; if (pHead1->val <= pHead2->val){ //存头结点先进行一次判断 newListNode = head = pHead1; pHead1 = pHead1->next; } else{ newListNode = head = pHead2; pHead2 = pHead2->next; } while (pHead1 != NULL && pHead2!= NULL) //两个都不为空是一直遍历下去 { if (pHead1->val <= pHead2->val){ head ->next= pHead1; head = head->next; pHead1 = pHead1->next; } else{ head->next = pHead2; head = head->next; pHead2 = pHead2->next; } } if (pHead2 == NULL){ //有一个为空时,直接另外一个直至为空 head->next = pHead1; } if (pHead1 == NULL){ head->next = pHead2; } return newListNode; }
我想上面的合并两个有序链表对我们进行合并两个有序的数组也是大同小异的。下面我贴上测试的归并排序的代码;
#include<iostream> using namespace std; //合并有序数列函数 void merge(int *a, int b[], int first, int mid, int last){ int i = first, j = mid + 1, k = 0; while (i <= mid&&j <= last){ if (a[i] < a[j]) b[k++] = a[i++]; else b[k++] = a[j++]; } while (i <= mid) b[k++] = a[i++]; while (j <= last) b[k++] = a[j++]; for (int ix = 0; ix < k; ++ix){ a[first + ix] = b[ix]; } } //拆分函数 void mergesort(int *A, int b[], int first, int last){ int mid = (first + last) / 2; if (first<last){ mergesort(A, b, first, mid); //利用递归函数 mergesort(A, b, mid + 1, last); merge(A, b, first, mid, last); } } bool MergeSort(int *A, int n) //归并函数 { int *p = new int[n]; if (n == 0) return false; mergesort(A, p, 0, n - 1); delete[] p; return true; } int main(){ const int N = 9; int a[N] = { 2, 5, 3, 4, 6, 1, 7, 0, 2 }; for (int i = 0; i < N; ++i){ cout << a[i] << " "; } cout << endl; bool bValue = MergeSort(a, N); if(bValue) { for (int i = 0; i < N; ++i) cout << a[i] << " "; } return 0; }