自然合併排序演算法

2021-09-28 20:24:49 字數 1195 閱讀 1870

合併排序基本思想:

將待排序元素分成大小大致相同(可以不等長)的兩個子集和,分別對兩個子集合進行排序,最終將排好序的子集合合併成所要求的排好序的集合。

遞迴版:

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 直到某一指標達到序列尾 將另一串行剩下的所有元素直...