ACM實習之分治與遞迴

2021-08-20 06:09:31 字數 4383 閱讀 2198

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...