recursive(遞迴)
簡潔易懂,但效率差,適合描述演算法
可分為以下3種:
direct recursion:直接呼叫自己
indirect recursion:先呼叫其它程序若干層後,最後又呼叫回自己
tail recursion:在最後一個命令又呼叫自己本身(由於尾端遞迴的返回位址是程式的結束指令,即時返回也不需進行處理)
若把此改掉,可以不需要儲存返回位址與程式狀態,而能夠提昇執行效率
遞迴函數=基本元素+建立其他新元素所需規則
遞迴演算法=遞迴關係+終止條件(需有一條路徑不再進行遞迴呼叫)
(若無法到達終止條件會造成無窮迴窮)
分析遞迴複雜度的工具:
遞迴樹:用樹狀結構表示遞迴的呼叫情況
遞迴關係式=用關係式表示呼叫遞迴的關係
當遞迴關係式可表示成為:
T(n)=aT(n/b)+cn^k,a與b=整數常數,c與k為正常數,a>=1,b>=2,在比較a,b^k大小關係,可以得到:
T(n)={
O(n^logb(a)),if a< b^k
O(n^k log n),if a=b^k
O(n^k),if a< b^k
removal of recursion 遞迴轉成非遞迴
1堆疊法:indirect recursion和direct recursion處理稍有不同
2folding(折疊法)
……………..
fibonacci(費氏數列) O(2^n)
遞回迴關係式:t(n){0,if n=0; 1,if n=1; t(n-1)+t(n-2)+c,otherwise
推導過程:t(n-1)+t(n-2)+c=t(t(n-2)+t(n-3)+c)+t(t(n-3)+t(n-4)+c)+c=…2^(n-1)*t(1)+(2^(n-1)-1)*c
所以t(n)=(2^n-1)*c > big O(2^n)
int fibonacci(int n){
if(n=0)return (0);
else if(n=1)return (1);
else return(fibonacci(n-1)+fibonacci(n-2));
}
int fibonacci(int n){
int fib_n,fib_n_1,fib_n_2;
if(n==0)return(0);
else if(n==1)return(1);
else{
fib_n_2=0;fib_n_1=1;
for(i=2;i<=n;i++){
fib_n=fib_n_1+fib_n_2; fib_n_1=fib_n_2; fib_n_2=fib_n;
}
return(fib_n);
}
}
hanoi(河內塔問題) O(2^n)
遞迴關係式:T(n){
2T(n-1)+c ,n>=2 where c屬於constant(遞迴關係)
c ,n=1 where c屬於constant(終止條件)
推導…
ps:搬動n個套環需2^n-1次
bin_search(二元搜尋),O(2底log n)
遞迴關係式:T(n)={
T(n/2)+c ,n>=2 where c屬於constant(遞迴關係)
c , n=1 where c屬於constant(終止條件)
最大/最小問題,O(n)
遞迴關係式:T(n)={
2T(n/2)+c ,n>=2 where c屬於constant(遞迴關係)
c , n=1 where c屬於constant(終止條件)
選擇問題 O(n^2)
矩陣乘法問題 O(n^3)
遞迴關係式,推導…
volker strassen O(n^2.81)
遞迴關係式,推導…
…
//找總數
int findsum(int n){ //1+2+…n
if(n==1)return(1); //終止條件
else return(findsum(n-1)+n); //遞迴條件
}
int findsum(int n){
int result,i;
for(i=n;i>1;i++){result+=i;}
return result;
}
//找最大,尚未測試
int findmax(int a[],int max,int i){ //find(a,1,陣列元素);
if(i==0){return max}
else{
if(max < a[i] )max=a[i];
findmax(a,max,i-1);
}
}
//找最大公因數
int findgcd(int x,int y){
return((y==0)?x:findgcd(y,x%y))
}
int findgcd(int x,y){
if(y==0)return(x);
else return(findgcd(y,x%y));
}
int findgcd(int x,y){
int remainder=x%y;
while(remainder!=0){
x=y;y=remainder;
remainder=x%y;
}
return(y);
}
找一字串的所有排列
void permutation(char list[],int i,int n){
int j,temp;
if(i==n){ printf("%s",list);}
else{
for(j=i;j<=n;j++){
swap(list[i],list[j],temp);
permutation(list,i+1,n);
swap(list[i],list[j],temp);
}
}
}
t(n)={c ,if n=1; n*t(n-1)+c*n ,if n>=2;
t(n)=n*t(n-1)+c*n=n*t((n-1)*t((n-1)-1)+c*(n-1))+c*n=(n*(n-1))*t(n-2)+c*(n+(n-1))=.....=O(n!)
ackermann
……