合併排序的三種不同寫法,包括遞迴和非遞迴

2021-06-18 16:06:05 字數 1571 閱讀 5867

在學演算法設計課中,學到合併排序時,並把合併排序的三種不同的寫法都寫了一遍(兩種遞迴的形式其實大同小異,只是在一種寫法中整個演算法只分配了乙個臨時陣列而一種寫法中每次遞迴時都會分配臨時空間用於暫存資料)。

一、遞迴形式的一種寫法(每次遞迴操作中都分配新的空間)

void merge1(item * a, item * b, item * c, int lb, int lc)

if(i < lb)

while(i < lb)

a[k++] = b[i++];

else

while(j < lc)

a[k++] = c[j++];

}/* a為待排序陣列 n為陣列長度 */

void merge_sort1(item * a, int n)

}

typedef int item;

void merge2(item * p, item * q, int first, int mid, int last)

else

} if(f <= mid)else

while(j <= last)

q[k ++] = p[j ++];

int i;

for(i = 0; i < k; i++)//將已排序陣列複製到原陣列

p[first + i] = q[i];

}/* p為待排序陣列, q為臨時陣列 */

void merge_sort2(item *p, item *q, int n1, int n2)

}

三、非遞迴形式

原來的遞迴過程是將待排序集合一分為二,直至排序集合就剩下乙個元素位置,然後不斷的合併兩個排好序的陣列。而非遞迴思想為,將陣列中的相鄰元素兩兩配對,並將其排序,構成n/2組長度為2的排序好的子陣列段,然後再將他們排序成長度為4的子陣列段,如此繼續下去,直至整個陣列排好序。

typedef int item;

void merge3(item * p, int first, int mid, int last)

else

} if(f <= mid)else

while(j <= last)

q[k ++] = p[j ++];

int i;

for(i = 0; i < k; i++)//將已排序陣列複製到原陣列

p[first + i] = q[i];

}/* p為待排序陣列 n為陣列長度 */

void merge_sort3(item * p, int n)

merge3(p, i, i + m/2 - 1, n -1);//尾部殘餘處理

m *= 2;

} merge3(p, 0, m/2 - 1, n - 1);//最後一次對兩個有序陣列做合併排序

}

在三種演算法中,實際執行發現過多的new會花費很多時間,所以遞迴的第二種形式要明顯由於第一種。

堆排序(遞迴 迭代三種寫法)

具體的演算法流程可以參考 排序演算法 三 之堆排序 堆排序的基本思路 這裡重點討論下調整堆結構這個操作,這個結構是建立在大頂堆已經建立的基礎上的,有遞迴和迭代兩種方法。遞迴方法 public void heapify int arr,int n,int i 非遞迴方法 public void adj...

三種不同狀態機寫法

1 reg 3 0 cs,ns 2 always posedge clk or negedge rst n begin 3 if rst n begin 4 cs idle 5 cmd 3 b111 6 end 7 else begin 8 case cs 9 idle if wr req begi...

關於氣泡排序,三種寫法

最近寫乙個簡單的排序,就用冒泡就行,結果忘了。於是就重新思考寫了一下。隨手寫出乙個,竟然寫完後有點懵了,到底寫的對不對呢。為方便,用matlab進行驗證,並檢視了網上流行的寫法。都寫在下面,其中,自認為第二種為最容易理解。當然,3種寫法,交換次數完全相同,交換之後結果完全相同。程式如下 clc cl...