函數調用時的棧
程序中的「函數調用棧」是棧數據結構的一種應用
函數調用棧通常是從高地址向低地址增加的
棧底爲內存的高地址處
棧頂爲內存的低地址處
函數調用棧中存儲的數據爲活動記錄
程序中的棧
在不斷的壓棧過程當中形成棧空間耗盡而產生棧溢出
棧溢出常因爲函數遞歸過深或局部數組過大形成ios
遞歸是一種數學上分而自治的思想
遞歸將大型複雜問題轉化爲與原問題相同但規模較小的問題進行處理
遞歸須要有邊界條件
當邊界條件不知足時,遞歸繼續進行
當邊界條件知足時,遞歸中止
斐波拉切數列
斐波納契數列以以下被以遞推的方法定義:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*)算法
int fibolac(int n) { if((1 == n)||(2 == n)) { return 1; } else { return fibolac(n-1)+fibolac(n-2); } }
字符串長度
求取字符串長度可以使用遞歸的方式來求取數組
int string_len(const char* p) { if(p == NULL) { return -1; } else if(*p == '\0') { return 0; } else { return string_len(p+1) + 1; } }
全排列
假設集合是{a,b,c},那麼這個集合中元素的所有排列是{(a,b,c),(a,c,b),(b,a,c),(b,c,a),(c,a,b),(c,b,a)},顯然,給定n個元素共同擁有n!種不一樣的排列,假設給定集合是{a,b,c,d},可以用如下給出的簡單算法產生其所有排列,即集合(a,b,c,d)的所有排列有如下的排列組成
以a開頭後面跟着(b,c,d)的排列
以b開頭後面跟着(a,c,d)的排列
以c開頭後面跟着(a,b,d)的排列
以d開頭後面跟着(a,b,c)的排列數據結構
int permutation(char s[],int b,int e) { if((b>=0) && (b<=e)) { if(b == e) { printf("%s\n",s); } else { int i = 0; for(i = b; i<=e; i++) { if(isswap(s,b,i)) //去重的全排列就是從第一個數字起每一個數分別與它後面非重複出現的數字交換 { char c = s[b]; //交換位置 s[b] = s[i]; s[i] = c; permutation(s,b+1,e); c = s[b]; //交換位置 s[b] = s[i]; s[i] = c; } } } } }
漢諾塔問題
該遊戲是在一塊銅板裝置上,有三根杆(編號A、B、C),在A杆自下而上、由大到小按順序放置64個金盤。遊戲的目標:把A杆上的金盤所有移到C杆上,並仍保持原有順序疊好。操做規則:每次只能移動一個盤子,而且在移動過程當中三根杆上都始終保持大盤在下,小盤在上,操做過程當中盤子能夠置於A、B、C任一杆上。
ide
/* n:須要移動的盤子數量 a:起始位置 b:須要藉助的柱子 c:須要移動到的柱子 */ int hannoi(int n, char a, char b, char c) { if(1 == n) { printf("%c-->%c\n",a,c); } else { hannoi(n-1, a, c, b); printf("%c-->%c\n",a,c); hannoi(n-1, b, a, c); } return 0; }
八皇后問題
八皇后問題,是一個古老而著名的問題,是回溯算法的典型案例。該問題是國際西洋棋棋手馬克斯·貝瑟爾於1848年提出:在8×8格的國際象棋上擺放八個皇后,使其不能互相,即任意兩個皇后都不能處於同一行、同一列或同一斜線上,問有多少種擺法。函數
#define N 8 typedef struct _tag_Pos { int ios; int jos; } Pos; //位置檢查 static char board[N+2][N+2]; static Pos pos[] = { {-1, -1}, {-1, 0}, {-1, 1} }; //偏移位置 static int count = 0; //符合要求的個數 void display() { int i = 0; int j = 1; for(i=0; i<N+2; i++) { for(j=0; j<N+2; j++) { printf("%c", board[i][j]); } printf("\n"); } } void init_queen() { int i,j; for(i=0;i<N+2;i++) { board[0][i] = '#'; board[i][0] = '#'; board[N+1][i] = '#'; board[i][N+1] = '#'; } display(); } int check(int i,int j) { int ret = 1; int p = 0; for(p=0; p<3; p++) { int ni = i; int nj = j; while( ret && (board[ni][nj] != '#') ) { ni = ni + pos[p].ios; nj = nj + pos[p].jos; ret = ret && (board[ni][nj] != '*'); } } return ret; } int find(int i) //查找的第i行 { int j; if(i > N) { count++; printf("Solution: %d\n", count); display(); //顯示 getchar(); } else { for(j=1;j<=N;j++) { if(check(i,j)) { board[i][j] = '*'; find(i+1); board[i][j] = ' '; //???? } } } }
數字的分解問題code
輸出正整數和等於n的全部不增的正整數和式,如:
4=4
4=3+1
4=2+2
4=2+1+1
4=1+1+1+1blog
a:用於存放分解的數 n:須要分解的數的和 k:分解的深度 int integer_fac(int a[],int n,int k) { int j,p; for(j=n; j>=1; j--) { if(j <= a[k-1]) { a[k] = j; if(j == n) { printf("%d = %d",a[0],a[1]); for(p=2;p<=k;p++) { printf("+%d",a[p]); } printf("\n"); } else { integer_fac(a,n-j, k+1); } } } return 0; }