1 / 17

# 資料結構 第五章：遞迴 - PowerPoint PPT Presentation

I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.

## PowerPoint Slideshow about '資料結構 第五章：遞迴' - vui

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.

- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript

### 資料結構第五章：遞迴

ywdeng@mail.knu.edu.tw

http://w3.im.knu.edu.tw/~joseph/

• 遞迴函數的特徵：
• 直接或間接地呼叫自己
• 在數學上與遞迴定義有關
• 例如：費氏數列

• n! = n*(n-1)*(n-2)*…*2*1
• 遞迴定義：
• 1!=1
• f(n)=n*f(n-1), n>=2
• 13! = 1932053504，在32位元系統上用long所能算出的最大階乘數

long fact(int n) {

if (n == 1) return 1;

else return n * fact(n-1);

}

int fibon(int n) {

if (n == 0) return 0;

if (n == 1) return 1;

return fibon(n-1) + fibon(n-2);

}

0

1

2

3

4

5

6

7

8

9

• 輸入：
• n 筆已排序資料（從小排到大）
• 欲尋找之資料 target
• 輸出：
• target 於輸入資料中的位置（序號）
• 如果 target 不在輸入資料中，則傳回 -1

int bin_search(int data[], int left, int right, int target) {

int mid = (left + right) / 2;

if (left > right) return -1;

if (target == data[mid]) return mid;

if (target > data[mid]) {

return bin_search(data, mid+1, right, target);

} else {

return bin_search(data, left, mid-1, target);

}

}

Tower of Hanoi 宣告與用法

#define PEG_A "PEG_A"

#define PEG_B "PEG_B"

#define PEG_C "PEG_C"

int main(int argc, char* argv[])

{

hanoi_move(n, PEG_A, PEG_B, PEG_C);

}

Tower of Hanoi 主要邏輯

void hanoi_move(int n, char* from, char* to, char* via) {

if (n == 1) {

printf("Move ring 1 from %s to %s\n", from, to);

} else {

hanoi_move(n-1, from, via, to);

printf("Move ring %d from %s to %s\n", n, from, to);

hanoi_move(n-1, via, to, from);

}

}

Tower of Hanoi 執行結果

1: Move ring 1 from PEG_A to PEG_B

2: Move ring 2 from PEG_A to PEG_C

3: Move ring 1 from PEG_B to PEG_C

4: Move ring 3 from PEG_A to PEG_B

5: Move ring 1 from PEG_C to PEG_A

6: Move ring 2 from PEG_C to PEG_B

7: Move ring 1 from PEG_A to PEG_B

• 西洋棋盤上，皇后不可以在同一列（row）或同一行（column）或同一對角線（diagonal）上
• 在一個 8×8 的棋盤上如何放置 8 個皇后？
• 往回追蹤（Backtracking）又稱『回溯』
• 如果下一個皇后找不到位置可放，則回頭調整前一個皇后的位置

void place(int q)

{

int i;

i = 0;

while (i < MAXQUEEN) {

/* 試著將第 q 個皇后放在 (row, col) = (i, q) 的位置 */

if (!attack(i, q)) { /*皇后未受攻擊 */

queen[q] = i; /*儲存皇后所在的列位置 */

/*判斷是否找到一組解 */

if (q == (MAXQUEEN - 1))

output_solution(); /*列出此組解 */

else

place(q + 1); /*否則繼續擺下一個皇后 */

}

i++;

}

}

/* 測試在(row,col)上的皇后是否遭受先前放置的其他皇后攻擊 */

int attack(int row, int col)

{

int i, atk = FALSE;

int offset_row, offset_col;

i = 0;

while (!atk && i < col) {

offset_col = ABS(i - col);

offset_row = ABS(queen[i] - row);

/*判斷兩皇后是否在同一列,皇后是否在對角線上 */

/*若皇后同列或在對角線上則產生攻擊,atk ==TRUE */

atk = (queen[i] == row) || (offset_row == offset_col);

i++;

}

return atk;

}

• 組合數
• 在 m 個球之中取 n 個，有多少種方式？
• 遞迴解：

int comb(int m, int n) {

if (n == 0) return 1;

if (m == n) return 1;

return comb(m-1, n) + comb(m-1, n-1);

}