1. 分治與遞迴
編寫自然歸併合併排序演算法
演算法描述:對於初始給定的陣列
,通常存在多個長度大於
1的已自然排好序的子陣列段.例如
,若陣列
a中元素為
,則自然排好序的子陣列段有
,,,.
用一次對陣列
a的線性掃瞄就足以找出所有這些排好序的子陣列段
.然後將相鄰的排好序的子陣列段兩兩合併
,構成更大的排好序的子陣列段
(,).
繼續合併相鄰排好序的子陣列段
,直至整個陣列已排好序。
2.需求分析
本演示程式用vc++6.0編寫,完成模板的生成,完成陣列的合併排序,最後輸出結果。
① 輸入的形式和輸入值的範圍:在主函式初始給定陣列,此陣列存在多個長度大於1的已自然排好序的子陣列段
.。② 輸出的形式:通過劃分自然排序,線性掃瞄,.然後將相鄰的排好序的子陣列段兩兩合併
,構成更大的排好序的子陣列段,繼續合併相鄰排好序的子陣列段,直至整個陣列已排好序。最後輸出已排好序的陣列。
③ 程式所能達到的功能:完成陣列的合併排序
④ 測試資料:
輸出3.概要設計
1)為了實現上述程式功能,需要
定義模板和函式來實現陣列的線性掃瞄,合併相鄰排好序的子陣列段:
①template
void mergesort(type a,int left,int right)
②template
void merge(type a,type b,int left,int mid,int right)
③template
void copy(type a,type b,int left,int right)
1)本程式包含4個函式:
① 主函式main()
② 線性掃瞄函式mergesort(type a,int left,int right)
③ 排序合併函式merge(type a,type b,int left,int mid,int right)
④ 複製函式copy(type a,type b,int left,int right)
各函式間關係如下
:main() mergesort(type a,int left,int right) merge(type a,type b,int copy(type a,type b,int left,int right) left,int mid,int right)
4.詳細設計
為了實現上述程式功能,需要定義模板和函式來實現陣列的線性掃瞄,合併相鄰排好序的子陣列段
:① template
void mergesort(type a,int left,int right)
type *b=new type;
if(left至少有兩個元素
int i=(left+right)/2;//取中點
mergesort(a,left,i);
mergesort(a,i+1,right);
merge(a,b,left,i,right);//合併到陣列
bcopy(a,b,left,right);//複製回陣列
a② template
void merge(type a,type b,int left,int mid,int right)
int i=left;
int j=mid+1;
int k=left;
while(i<=mid&&j<=right) //i的範圍
[left
,mid],j
的範圍[mid+1,right]
if(a[i]else b[k++]=a[j++];
if(i>mid)
else
③ template
void copy(type a,type b,int left,int right)
int i;
for(i=left;i<=right;i++)
a[i]=b[i];
具體**:
#include
using namespace std;
template
void mergesort(type a,int left,int right)
type *b=new type;
if(left至少有兩個元素
int i=(left+right)/2;//取中點
mergesort(a,left,i);
mergesort(a,i+1,right);
merge(a,b,left,i,right);//合併到陣列
bcopy(a,b,left,right);//複製回陣列
atemplate
void merge(type a,type b,int left,int mid,int right)
int i=left;
int j=mid+1;
int k=left;
while(i<=mid&&j<=right) //i的範圍
[left
,mid],j
的範圍[mid+1,right]
if(a[i]else b[k++]=a[j++];
if(i>mid)
else
template
void copy(type a,type b,int left,int right)
int i;
for(i=left;i<=right;i++)
a[i]=b[i];
void main()
int i;
int c[8]=;
mergesort(c,0,7);
cout<5.除錯分析
#include
using namespace std;
template
void mergesort(type a,int left,int right)
type *b=new type;
if(left至少有兩個元素
int i=(left+right)/2;//取中點
mergesort(a,left,i);
mergesort(a,i+1,right);
merge(a,b,left,i,right);//合併到陣列
bcopy(a,b,left,right);//複製回陣列
atemplate
void merge(type a,type b,int left,int mid,int right)
int i=left;
int j=mid+1;
int k=left;
while(i<=mid&&j<=right) //i的範圍
[left
,mid],j
的範圍[mid+1,right]
if(a[i]else b[k++]=a[j++];
} //時間複雜度
t(n)=o(1),
空間複雜度
s(n)=o(1)
if(i>mid)
else
} //時間複雜度
t(n)=o(1),
空間複雜度
s(n)=o(1)
template
void copy(type a,type b,int left,int right)
int i;
for(i=left;i<=right;i++)
a[i]=b[i];
} //時間複雜度
t(n)=o(1),
空間複雜度
s(n)=o(1)
void main()
int i;
int c[8]=;
mergesort(c,0,7);
cout<
t(n)=o(1),
空間複雜度
s(n)=o(1)
6.使用說明
程式名為
1.exe,執行環境為
vc++6.0
。程式執行後顯示
7.測試結果
1) 建立程式:
輸出:
演算法思想之分治遞迴策略
摘自 鄒恒明 演算法之道 採取分治策略解決問題有三個步驟 1 將問題分解為若干個小的子問題。每個子問題和大問題同型,但規模更小。2 遞迴解決這些問題。3 將子問題的解答合併,並獲得大問題的解答。第二步中 遞迴解決這些子問題 指的是按照同樣的分治策略進行求解,即通過將這些子問題分解到更小的孫子問題來進...
棋盤覆蓋之分治加遞迴
在乙個n n n 2k 個方格組成的棋盤中,恰有乙個方格與其他方格不同,稱該方格為一特殊方格,且稱該棋盤為一特殊棋盤。在棋盤覆蓋問題中,要用圖示的4種不同形態的l型骨牌覆蓋給定的特殊棋盤上除特殊方格以外的所有方格,且任何2個l型骨牌不得重疊覆蓋。當初自己聽了老師說的好久還是不太懂,自己就慢慢琢磨,下...
ACM 歸併排序與快速排序(遞迴與分治)
歸併排序的內容可在紫書p226裡面檢視,紫書裡的 寫得十分簡潔,高效,重點要理解好循壞條件的控制。快排可參考以下的部落格 歸併排序時間複雜度 o nlogn 快排時間複雜度 平均o nlogn 最慢o n 2 歸併排序穩定但佔空間比較大,快排佔空間較小但不穩定。以下為 實現 includeusing...