資料結構-遞迴和分治
阿新 • • 發佈:2021-10-28
斐波那契數
斐波那契數---遞迴實現
斐波那契數---迭代實現
遞迴實現逆序輸出
二分查詢(分治)
漢諾塔問題
八皇后問題(遞歸回溯實現)
目錄
遞迴和分治
斐波那契數
斐波那契數---遞迴實現
/* 斐波那契數列 1 1 2 3 5 8 ... 從第三個數開始每一個數都是前兩個數之和 使用遞迴實現列印前40個斐波那契數 */ # include<stdio.h> # include<stdlib.h> // 列印第i個斐波那契數 int fbnq(int n) { if(n <= 2) return 1; else return fbnq(n - 1) + fbnq(n - 2); } int main() { for(int i = 1 ; i <= 40 ; i ++) printf("%d ",fbnq(i)); system("pause"); return 0; }
斐波那契數---迭代實現
/* 斐波那契數列 1 1 2 3 5 8 ... 從第三個數開始每一個數都是前兩個數之和 使用迭代實現列印前40個斐波那契數(注意這個是使用陣列實現的) */ # include<stdio.h> # include<stdlib.h> int fbnqarr[1000]; int main() { fbnqarr[0] = 1; fbnqarr[1] = 1; int fbnqn = 0; for(int i = 2 ; i < 40 ; i ++) { fbnqarr[i] = fbnqarr[i - 1] + fbnqarr[i - 2]; } for(int i = 0 ; i < 40 ; i ++) printf("%d ",fbnqarr[i]); system("pause"); return 0; }
遞迴實現逆序輸出
/* 使用遞迴實現輸入一個任意長度的字串,'#'表示結束輸入 結束輸入之後將剛才的字串逆序輸出 */ # include<stdio.h> # include<stdlib.h> void nx_print() { char e; scanf("%c",&e); if(e != '#') nx_print(); printf("%c",e); } int main() { printf("請輸入字串!\n"); nx_print(); printf("\n"); system("pause"); return 0; }
二分查詢(分治)
/*binary search
二分查詢
輸入一個數列長度n,表示將輸入一個長度為n的有序數列,接下來輸入有序數列
輸入想要查詢的數字
輸出查詢的數字的位置
*/
# include<stdio.h>
# include<stdlib.h>
const int MAXSIZE = 110;
// 1 2 3 4 4 6
// 二分查詢函式 傳入想要查詢的數字,順序數列,結果位置的指標,陣列的長度
void find(int x,int* arr,int *pos1,int *pos2,int n)
{
int l = 0 , r = n - 1;
while(l < r)
{
int mid = ( l + r ) / 2; // 注意每次mid都要更新,所以mid要寫在while內
if(arr[mid] >= x) r = mid;
else l = mid + 1;
}
if (x != arr[l]) *pos1 = -1, *pos2 = -1;
else // 說明找到了左邊第一個為x的數,但是這裡還是有一種情況 1 2 3 4 4 5剛才只是找到了左邊的4,右邊的4的定位在使用一個二分(只是將check條件更改一下即可)
{
*pos1 = l;
l = 0 , r = n - 1;
while (l < r)
{
int mid = (l + r + 1) / 2;
if( arr[mid] <= x) l = mid;
else r = mid - 1;
}
*pos2 = l;
}
}
int main()
{
int n,e,findn;
int arr[MAXSIZE];
printf("輸入有序序列長度:\n");
scanf("%d",&n);
printf("依次輸入有序序列:\n");
for(int i = 0 ; i < n ; i ++)
{
scanf("%d",&e);
arr[i] = e;
}
printf("輸入想要查詢的數:\n");
scanf("%d",&findn);
int pos1 = -1 ,pos2 = -1;
find(findn,arr,&pos1,&pos2,n);
printf("想要查詢的數在有序序列中的順序依次為:");
printf("%d %d\n",pos1 + 1,pos2 + 1);
system("pause");
return 0;
}
漢諾塔問題
漢諾塔核心:
1.將A柱上的n-1個移動到B柱上
2.將A柱上的第n個移動到C柱上
3.將B柱上的n-1個移動到C柱上(這裡就和1.2.開始遞迴就行)
/*
漢諾塔問題
有ABC三根柱子,A柱子上有個盤子
要把A柱子上的盤子移動到C柱子上,在移動過程中可以藉助B柱子,但是要求小的盤子在上大的盤子在下。
要求輸出入盤子的個數,輸出需要移動的次數。
核心:
漢諾塔分為以下核心三步:
1.將A柱上n-1個移動到B柱上
2.將A柱上第n個移動到C柱上
3.將B柱上n-1個移動到C柱上(可以發現和第一步就相同了.....就這樣遞迴下去就可)
*/
# include<stdio.h>
# include<stdlib.h>
int cnt;
// hanoimove函式 傳入盤子的個數n,返回移動的次數
void hanoimove(int n,char a,char b,char c) // 將a柱上的盤子(藉助b柱)移動到c柱上
{
if( n == 1)
{
// 移動A的最底下的一個盤子(這個整體中最大的盤子)通過B移動到C柱上
cnt ++;
printf("第%d次:將%c->%c上\n",cnt,a,c);
}
else
{
// 將A柱上N-1個盤子移動到B盤上
hanoimove(n-1,a,c,b);
cnt ++;
printf("第%d次:將%c->%c上\n",cnt,a,c);
// 將B柱上的n-1個盤子移動到C柱上
hanoimove(n-1,b,a,c);
}
}
int main()
{
int n;
printf("請輸入A柱上盤子的個數:\n");
scanf("%d",&n);
char a = 'A',b = 'B', c = 'C';
hanoimove(n,a,b,c);
printf("一共移動了%d次\n",cnt);
system("pause");
return 0;
}
八皇后問題(遞歸回溯實現)
/*
八皇后問題(英文:Eight queens),是由國際象棋棋手馬克斯·貝瑟爾於1848年提出的問題,是回溯演算法的典型案例。
問題表述為:在8×8格的國際象棋上擺放8個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行、同一列或同一
斜線上,問有多少種擺法
遞歸回溯方法:
思路:
0表示無,1表示這裡放置了一個皇后
需要寫一個isdanger函式用來判斷該位置是否合法,find函式尋找下一個合法位置
把第一行的第一個位置放上皇后,使用find函式去尋找下一個合法位置,合法就放上1,繼續find下一個合法位置,
八行都填滿了(這個就是遞迴結束的條件),這時就找到了一種擺法。然後繼續去往第一行第二個位置放皇后繼續上述步驟..
*/
# include<stdio.h>
# include<stdlib.h>
int chess[8][8];
int cnt;
// 判斷位置是否合法,傳入位置(i,j)合法返回1,不合法返回0
// 即判斷這一行的哪個列位置是合法的
int isdanger(int i , int j)
{
int f1 = 1, f2 = 1, f3 = 1, f4 = 1, f5 = 1;
// 判斷這一列是否還有其他的皇后
for(int row = 0; row < 8 ; row ++)
{
if(chess[row][j])
{
f1 = 0;
break;
}
}
// 判斷這個位置左上方是否有其他皇后
for(int row = i ,col = j ; row >= 0 && col >= 0 ; row --,col --)
{
if(chess[row][col])
{
f2 = 0;
break;
}
}
// 判斷這個位置右上方是否有其他皇后
for(int row = i,col = j ; row >= 0 && col < 8 ; row --,col ++)
{
if(chess[row][col])
{
f3 = 0;
break;
}
}
// 判斷這個位置左下方是否有其他皇后
for(int row = i ,col = j ; row < 8 && col >= 0; row ++,col --)
{
if(chess[row][col])
{
f4 = 0;
break;
}
}
// 判斷這個位置右下方是否有其他皇后
for(int row = i ,col = j; row < 8 && col < 8 ; row ++,col ++)
{
if(chess[row][col])
{
f5 = 0;
break;
}
}
return (f1 && f2 && f3 && f4 && f5);
}
// 實現八皇后位置的查詢與輸出
void eigthqueenfind(int row)
{
if( row == 8 ) // row加到8就說明0-7 × 0-7 都已經完成了八皇后擺放
{
printf("第%d種\n", ++ cnt);
// 結束條件
for(int i = 0 ; i < 8 ; i ++)
{
for(int j = 0; j < 8 ; j ++)
{
printf("%d ",chess[i][j]);
}
printf("\n");
}
printf("\n");
}
else
{
for(int j = 0 ; j < 8 ; j ++) // 每一列都可以考慮到(由於這裡是for迴圈然後遞迴,所以可以遞歸回溯)
{
// printf("判斷(%d,%d)\n",row,j);
if(isdanger(row,j))
{
// printf("判斷(%d,%d): 1\n",row,j);
chess[row][j] = 1; // 如果找到了這一行的某個列位置是合法的就把皇后擺放上去
eigthqueenfind(row + 1); // 這一行找到了就接著去尋找下一行
chess[row][j] = 0; // 找到了,或者沒有找到都要將這個合法位置(row,j)重新設定成0,去尋找下一個
}
}
}
}
int main()
{
eigthqueenfind(0);
system("pause");
return 0;
}
rds_blogs