日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

数据结构教程读书笔记_递归

發布時間:2023/12/13 综合教程 19 生活家
生活随笔 收集整理的這篇文章主要介紹了 数据结构教程读书笔记_递归 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

遞歸的定義

在定義一個過程或函數時,出現直接或者間接調用自己的成分,稱之為遞歸。

若直接調用自己,稱之為直接遞歸;若間接調用自己,稱之為間接遞歸。

如果一個遞歸函數中遞歸調用語句是最后一條執行語句,則稱這種遞歸調用為尾遞歸。

尾遞歸算法:可以用循環語句轉換為等價的非遞歸算法

其他遞歸算法:可以通過棧來轉換為等價的非遞歸算法

使用遞歸的場景

(1)定義是遞歸的

有許多數學公式、數列等的定義是遞歸的。例如,求n!和Fibonacci數列等。這些問題的求解過程可以將其遞歸定義直接轉化為對應的遞歸算法。

(2)數據結構是遞歸的

有些數據結構是遞歸的。 例如, 單鏈表就是一種遞歸數據結構, 其節點類型定義如下:

1 typedef struct LNode
2 { 
3     ElemType data;
4     struct LNode *next; //指向同類型節點的指針
5 } LinkList;

不帶頭節點單鏈表示意圖:

(3)問題的求解方法是遞歸的

遞歸模型

一個遞歸模型是由遞歸出口和遞歸體兩部分組成。

遞歸出口確定遞歸到何時結束;遞歸體確定遞歸求解時的遞推關系。

f(sn) =g(f(si), f(si+1), …, f(sn-1), cj, cj+1, …, cm)

其中g是一個非遞歸函數,c是常量。

把一個不能或不好直接求解的“大問題”轉化成一個或幾個“小問題”來解決; 再把這些“小問題”進一步分解成更小的“小問題” 來解決。 直到每個“小問題”都可以直接解決(此時分解到遞歸出口)。
但遞歸分解不是隨意的分解,遞歸分解要保證“大問題”與“小問題”相似,即求解過程與環境都相似。


f(s1) =m1
f(sn) =g(f(sn-1), cn-1)

求f(sn)的分解過程如下:

遇到遞歸出口發生“質變” , 即原遞歸問題便轉化成可以直接求解的問題。 求值過程:

這樣f(sn)便計算出來了,因此遞歸的執行過程由分解和求值兩部分構成。

求遞歸模型的步驟

(1)對原問題f(s)進行分析, 稱為“ 大問題” ,假設出合理的“ 小問題” f(s’)

(2)假設f(s’)是可解的, 在此基礎上確定f(s)的解, 即給出f(s)與f(s’)之間的關系,即遞歸體

(3)確定一個特定情況(如f(1)或f(0))的解,即遞歸出口


應用

1、采用遞歸算法求實數數組A[0..n-1]中的最小值

分析:

假設f(A,i-1)已求出, 則f(A,i)=MIN(f(A,i-1), A[i]), 其中MIN()為求兩個值較小值函數。

當i=0時,只有一個元素,有f(A,i)=A[0]。

遞歸模型:
f(A,i) =A[0] 當i=0時
f(A,i) = MIN(f(A,i-1), A[i]) 其他情況

代碼:

 1 float f(float A[], int i)
 2 { 
 3     float m;
 4     if (i == 0)
 5         return A[0];
 6     else
 7     { 
 8         m = f(A, i - 1);
 9         
10         if (m > A[i])
11             return A[i];
12         else
13             return m;
14     }
15 }

2、求單鏈表中數據節點個數

分析:

空單鏈表的數據節點個數為0,即f(L)=0 當L=NULL

對于非空單鏈表:

考慮一下我們的鏈表模型:

則可以得出下面的圖:

遞歸模型:

f(L) = 0 當L=NULL
f(L) =f(L->next) + 1 其他情況

代碼:

1 int count(Node *L)
2 { 
3     if (L == NULL)
4         return 0;
5     else
6         return count(L->next) + 1;
7 }

3、正向顯示所有節點值

分析:

假設f(L->next)已求解
f(L)等價于輸出L->data; f(L->next);

遞歸模型:

f(L) 不做任何事件 當L=NULL
f(L) 輸出L->data;f(L->next) 其他情況

代碼:

1 void traverse(Node *L)
2 { 
3     if (L == NULL) 
4         return;
5         
6     printf("%d ", L->data);
7     traverse(L->next);
8 }

4、反向顯示所有節點值

分析:

假設f(L->next)已求解
f(L)等價于f(L->next);輸出L->data;

遞歸模型:

f(L) 不做任何事件 當L=NULL
f(L) f(L->next);輸出L->data 其他情況

代碼:

1 void traverseR(Node *L)
2 { 
3     if (L == NULL) 
4         return;
5 
6     traverseR(L->next);
7     printf("%d ", L->data);
8 }

5、采用遞歸算法求解迷宮問題,并輸出從入口到出口的所有迷宮路徑

分析:

遞歸模型:

mgpath(xi,yi,xe,ye,path) 將(xi,yi)添加到path中;輸出path中的迷宮路徑; 若(xi,yi)=(xe,ye)
mgpath(xi,yi,xe,ye,path) 對于(xi,yi)四周的每一個相鄰方塊(i,j):
              (1)將(xi,yi)添加到path中;
              (2)置mg[xi][yi]=-1;
              (3)mgpath(i,j,xe,ye,path);
              (4)path回退一步并置mg[xi][yi]=0; (在一個“小問題” 執行完后回退是為了找所有解)
                                若(xi,yi)不為出口且可走

代碼:

 1 typedef struct
 2 { 
 3     int i; //當前方塊的行號
 4     int j; //當前方塊的列號
 5 } Box;
 6 
 7 typedef struct
 8 { 
 9     Box data[MaxSize];
10     int length; //路徑長度
11 } PathType; //定義路徑類型
12 
13 int mg[M+2][N+2] = //M=4, N=4
14 { 
15     {1, 1, 1, 1, 1, 1},
16     {1, 0, 0, 0, 1, 1},
17     {1, 0, 1, 0, 0, 1},
18     {1, 0, 0, 0, 1 ,1},
19     {1, 1, 0, 0, 0, 1},
20     {1, 1, 1, 1, 1, 1} 
21 };
22 
23 void mgpath(int xi,int yi,int xe,int ye,PathType path)
24 //求解路徑為:(xi,yi) ? (xe,ye)
25 { 
26     int di,k,i,j;
27     if (xi == xe && yi == ye)
28     { 
29         path.data[path.length].i = xi;
30         path.data[path.length].j = yi;
31         path.length++;
32         printf("迷宮路徑%d如下:
",++count);
33 
34         for (k = 0; k < path.length; k++)
35         { 
36             printf("	(%d, %d)", path.data[k].i, path.data[k].j);
37             
38             if ((k + 1) % 5 == 0) //每輸出每5個方塊后換一行
39                 printf("
");
40         }
41         printf("
");
42     }
43     else //(xi,yi)不是出口
44     { 
45         if (mg[xi][yi] == 0) //(xi,yi)是一個可走方塊
46         { 
47             di= 0;
48             while (di<4) //對于(xi,yi)四周的每一個相鄰方位di
49             { 
50                 switch(di) //找方位di對應的方塊(i,j)
51                 {
52                     case 0: 
53                         i = xi-1; j = yi; break;
54                     case 1: 
55                         i = xi; j = yi + 1; break;
56                     case 2:
57                         i = xi + 1; j = yi; break;
58                     case 3:
59                         i = xi; j = yi - 1; break;
60                 } 
61                 path.data[path.length].i = xi;
62                 path.data[path.length].j = yi;
63                 path.length++; //路徑長度增1
64                 mg[xi][yi]=-1; //避免來回重復找路徑
65 
66                 mgpath(i,j,xe,ye,path);
67 
68 path.length--; //回退一個方塊 69 mg[xi][yi]=0; //恢復(xi,yi)為可走 70 di++; 71 } //-while 72 } //- if (mg[xi][yi]==0) 73 } //-遞歸體 74 } 75 76 int main() 77 { 78 PathType path; 79 path.length=0; 80 81 mgpath(1, 1, 4, 4, path); 82 83 return 0; 84 }

初始:

結果:

本文圖片參考自:配套ppt課件

總結

以上是生活随笔為你收集整理的数据结构教程读书笔记_递归的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。