算法设计学习---递归
cuicuiv小白學(xué)算法—遞歸
遞歸:是指在函數(shù)的定義中又調(diào)用函數(shù)自身的方法。
使用遞歸求解的問題需要滿足一下三個條件:
提取遞歸模型的步驟
基于遞歸數(shù)據(jù)結(jié)構(gòu)的遞歸算法設(shè)計
例—二叉樹的遞歸算法設(shè)計
假設(shè)二叉樹采用二叉鏈存儲結(jié)構(gòu),設(shè)計一個遞歸算法釋放二叉樹bt中的所有結(jié)點。
設(shè)f(bt)的功能是釋放二叉樹bt的所有結(jié)點,則f(bt->lchild)的功能是釋放二叉樹bt的左子樹的所有結(jié)點,f(bt->rchild)的功能是釋放二叉樹bt的右子樹的所有結(jié)點。即f(bt)是“大問題”,f(bt->lchild)和f(bt->rchild)是兩個“小問題”
對應(yīng)的遞歸模型如下:
f(bt)=不做任何事情 ********************************** 當(dāng)bt=NULL時
f(bt)=f(bt->lchild);f(bt->rchild);釋放bt所指的結(jié)點 ***其他情況
*
對應(yīng)的遞歸算法:
void DestroyBtree(BTNode *&bt)
{ if(bt!=NULL)
{
DestroyBtree(bt->lchild);
DestroyBtree(bt->rchild);
ftee(bt);
}
}
基于歸納思想的遞歸算法設(shè)計
從本質(zhì)上來講,給出一個帶有參數(shù)n的問題,采用基于歸納思想設(shè)計遞歸算法是基于這樣一個事實。
如果知道求解帶有參數(shù)k(<n)的同樣問題,那么整個任務(wù)就轉(zhuǎn)化成如何把解法擴展到帶有參數(shù)k的情況。實際上就是以f(n)為“大問題”,以f(n-1)或者f(n/2)等為“小問題”,歸納出大小問題之間的遞推關(guān)系。
基于歸納思想的遞歸算法設(shè)計通常不像基于遞歸數(shù)據(jù)結(jié)構(gòu)的遞歸算法設(shè)計那樣直觀,需要通過對求解問題的深入分析提煉出求解過程中的相似性而不是數(shù)據(jù)結(jié)構(gòu)的相似性,這就增加了算法設(shè)計的難度。
簡單選擇排序和冒泡排序
【問題描述】 對于給定的含有n個元素的數(shù)組a,分別采用簡單選擇排序和冒泡排序方法按元素值遞增排序
簡單選擇排序和冒泡排序方法都是按a[0···n-1]分為有序區(qū)a[0····i-1]和無序區(qū)兩個部分,有序區(qū)中的所有元素都不大于無序區(qū)中的元素,初始時有序區(qū)為空(即i=0)。經(jīng)過n-1趟排序(i=1~n-2),每趟排序采用不同方式將無序區(qū)中的最小元素移動到無序區(qū)的開頭。
1.簡單選擇排序
簡單選擇排序采用簡單比較方式在無序區(qū)中選擇最小元素并放到開頭處。
設(shè)f(a,n,i)用于在無序區(qū)a[i···n-1](共n-i個元素)中選擇最小元素并放到a[i]處,是“大問題”,則f(a,n,i+1)用于在無序區(qū)a[i+1····n-1]中選擇最小元素放到a[i+1]處,是“小問題”。當(dāng)i=n-1時所有元素有序,算法結(jié)束。
對應(yīng)遞歸模型:
f(a,n,i) 不做任何事情,算法結(jié)束****************************當(dāng)i=n-1時
f(a,n,i) 通過簡單選擇比較挑選a[i···n-1]中最小的元素;***否則
a[k]放到a[i]出;f(a,n,i+1);
代碼如下:
#include<stdio.h> void swap(int &x,int &y) //交換x和y的值 {int tmp=x;x=y;y=tmp; }void disp(int a[],int n) //輸出a中的所有元素 {for(int i=0;i<n;i++)printf("%d",a[i]);printf("\n"); }void SelectSort(int a[],int n,int i) //遞歸的簡單選擇 {int j,k;if(i==n-1) return; //滿足遞歸出口else {k=i;//k記錄a [i ```n-1]中最小元素的下標(biāo)for(j=i+1;j<n;j++)//在a[i```n-1]中找最小元素a[k]{if(a[j]<a[k])k=j;if(k!=i)//若最小元素不是a[i]swap(a[i],a[k]);//a[i]和a[k]交換SelectSort(a,n,i+1);} } } void main() {int n=10;int a[]={2,5,1,7,10,6,9,4,3,8};printf("排序前:");disp(a,n);SelectSort(a,n,0);printf("排序后:");disp(a,n); }簡單選擇排序通過兩兩對比一一得出最小元素,通過遞歸實現(xiàn)全部排列,最后通過遞歸出口結(jié)束。
2.冒泡排序
冒泡排序采用交換方式將無序區(qū)中的最小元素放到開頭處。
設(shè)f(a,n,i)用于將無序區(qū) a[i···n-1] 中的最小元素交換到a[i]處,是”大問題“,則f(a,n,i+1)用于將無序區(qū)a[i+1···n-1]中的最小元素交換到a[i+1]處,是”小問題“。當(dāng)i=n-1時所有元素有序,算法結(jié)束。
對應(yīng)遞歸模型:
f(a,n,i) 不做任何事情,算法結(jié)束************************當(dāng)i=n-1時
f(a,n,i) 對a[i ···n-1]中的元素序列從a[n-1]開始進(jìn)行相鄰比較***否則
若相鄰兩元素反序則將兩者交換;
若沒有交換則返回,否則執(zhí)行f(a,n,i+1)
代碼如下:
#include<stdio.h> void swap(int &x,int &y) //交換x和y的值 {int tmp=x;x=y;y=tmp; }void disp(int a[],int n) //輸出a中的所有元素 {for(int i=0;i<n;i++)printf("%d",a[i]);printf("\n"); }void BubbleSort(int a[],int n,int i) //遞歸的冒泡排序 {int j;bool exchange;if(i==n-1) return; //滿足遞歸出口條件else{exchange=false;for(j=n-1;j>i;j--)if(a[j]<a[j-1]) // 當(dāng)相鄰元素方序時{swap(a[j],a[j-1]);exchange=true;} if(exchange==false) //未發(fā)生交換時直接返回return;elseBubbleSort(a,n,i+1);} } void main() {int n=10;int a[]={2,5,1,7,10,6,9,4,3,8};printf("排序前:");disp(a,n);SelectSort(a,n,0);printf("排序后:");disp(a,n); }**
總結(jié):
1. 面對問題求解選擇方法時,先判斷題目對象的條件,以其數(shù)據(jù)結(jié)構(gòu)以及數(shù)學(xué)模型為參考。
2. 用遞歸求解題目主要分為兩大類:
(1)基于遞歸數(shù)據(jù)結(jié)構(gòu)的遞歸算法設(shè)計 (2)基于歸納思想的遞歸算法設(shè)計
3.使用遞歸時,對“大問題”和“小問題”的判斷以及劃分以及遞歸出口條件極為重要。
總結(jié)
以上是生活随笔為你收集整理的算法设计学习---递归的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python调用周立功CAN接口卡接口库
- 下一篇: B+树索引及其使用