合併排序基本思想:
將待排序元素分成大小大致相同(可以不等長)的兩個子集和,分別對兩個子集合進行排序,最終將排好序的子集合合併成所要求的排好序的集合。
遞迴版:
void mergesort(int a,int left,int right)
}void mergepass(int x,int y,int s,int n)
if(i+sm)
for(int q=j;q<=r;q++) //i>m說明i已經複製到d中了,所以要把剩下的j複製到b中,並且此時c中元素是有序的,所以可以直接複製
d[l++]=c[q];
else
for(int p=i;p<=m;p++)
d[l++]=c[p];
}分析一下時間複雜度:
縱向:1->2->4->8....n 共logn次
橫向:包括比較和迴圈複製,最多都不超過n
所以時間複雜度也為o(nlogn)
但在現實中給定陣列中,肯定存在已排好序的子陣列段,如果將其利用起來,就避免了無意義的比較。
例如:a=;
自然排好序的子陣列段有.可以用一次對陣列a的線性掃瞄,找出這些已排好序的子陣列段,然後兩兩合併,構成更大已排好序的陣列。
->->
核心**:
void getbpoint(int a,int b,int n,int &m) //線性掃瞄a,記錄下已排好序的子陣列段下標
{int j=0;
b[j++]=0;
for(int i=0;i
void mergesort(int a,int n)
{int *b=new int[n];
int s=1;
while(s
時間複雜度分析:
由於利用了自然排好序的子陣列段,所以在自然合併排序中,合併的次數要少很多,即使是在某一具體例項中,而不是所謂的平均情況下。
儘管理論上分析時間複雜度也為o(nlogn),但是實際中,一定會存在自然排好序片段,這樣的話時間就會大大降低了。
極端的例子,如果n元素陣列已經排好序了,該演算法並不需要合併,而合併排序演算法還需要進行logn合併,
所以自然合併排序演算法需要o(n)(時間僅僅花在掃瞄上了),合併排序演算法需要o(nlogn)時間
自然合併排序完整**:
自然合併排序
自然合併排序演算法是對合併排序演算法的一種改進。設 a 0 n 1 是無序陣列,用一次對陣列a的掃瞄可以找出其中 自然排好序的子陣列,然後將相鄰的排好序的子陣列段兩 兩合併,繼續合併相鄰排好序的子陣列段,直至將整個數 組排好序。code include include using namespace...
自然合併排序
我們知道歸併排序是將乙個無序的陣列兩兩劃分,最終劃分成每個組內有序的子元素,組後再將若干個組內有序的元素合併成乙個完整有序的陣列。這個思路可以使用遞迴和非遞迴演算法來實現,我在此主要講自然合併排序 自然合併排序當然也是合併排序,所謂的自然只不過就是指 所劃分的子陣列不在是兩兩劃分,而是每乙個子陣列都...
分治 合併排序 自然合併排序(C )
演算法步驟 引用自 菜鳥教程 申請空間,使其大小為兩個已經排序序列之和,該空間用來存放合併後的序列 設定兩個指標,最初位置分別為兩個已經排序序列的起始位置 比較兩個指標所指向的元素,選擇相對小的元素放入到合併空間,並移動指標到下一位置 重複步驟 3 直到某一指標達到序列尾 將另一串行剩下的所有元素直...