跟著《演算法導論》學習——插入排序與歸併排序
阿新 • • 發佈:2019-01-02
讀前宣告:本人所寫帖子主要為了記錄本人學習的一個過程,無他想法,由於內容比較膚淺,如有雷同,非常正常!!!
本文內容:
本文主要是參考《演算法導論》這本書,完成部分演算法編寫,可能程式設計習慣或者風格比較差,還請多多批評。
1、插入排序(Insertion Sort)
插入排序是對少量元素進行排序的有效演算法,其機理與很多人打牌時,整理手中牌時的做法差不多。開始摸牌時,我們的左手是空的,牌面朝下放在桌上,接著,一次從桌上摸起一張牌,並將它插入到左手一把牌中的正確位置上。為了找到這張牌的正確位置,要將它與手中已有的每一張牌從右到左的比較。
其程式碼如下:
2、歸併排序(Merge sort)void InsertionSort(int a[],int n) { for(int j=1;j<n;j++) { int key = a[j]; int i = j-1; while (i>=0&&a[i]>key) { a[i+1] = a[i]; i--; } a[i+1] = key; }
歸併排序是分治法(Divide-and-Conquer)的一個應用。分治法的的策略如下:將原問題劃分為n個規模較小而結構與原問題相似的子問題;遞迴地解決這些子問題,然後再合併其結果,就得到原問題的解。分治模式在每一層遞迴都有三個步驟:
分解(Divide):將原問題分解成一系列子問題;
解決(Conquer):遞迴地求解各子問題,若子問題足夠小,則直接求解;
合併(Combine):將子問題的結果合併成原問題的解
歸併排序完全按照上述模式,直觀的操作如下:
分解:將n個元素分成各含n/2個元素的子序列;
解決:用合併排序法對兩個子序列遞迴地排序;
合併:合併兩個已排序的子序列以得到排序結果。
在對子序列排序時,其長度為1時遞迴結束,單個元素被視為已排序的。
合併排序的關鍵步驟在於合併步驟中的合併兩個已排序子序列。為做排序,引入一個輔助過程Merge,其過程是將兩個子序列經過比較,合併成一個大的排好序的陣列。
Merge子函式如下:
void Merge(int a[],int b[],int left,int middle,int right) { for (int i=left;i<=right;i++) { b[i] = a[i]; } int s1 = left; int s2 = middle+1; int t = left; while (s1<=middle&&s2<=right) { if (b[s1]<=b[s2]) { a[t++] = b[s1++]; } else { a[t++] = b[s2++]; } } if (s1==middle+1) { while (s2<=right) { a[t++] = b[s2++]; } } if (s2==right+1) { while (s1<=middle) { a[t++] = b[s1++]; } } }
歸併排序演算法過程:
void MergeSort(int a[],int b[],int left,int right)
{
if(left>=right) return;
int middle = (left+right)/2;
MergeSort(a,b,left,middle);
MergeSort(a,b,middle+1,right);
Merge(a,b,left,middle,right);
}