網(wǎng)站建設(shè)排期什么是網(wǎng)站推廣?
一.遞歸
1.什么是遞歸
遞歸是一種編程技術(shù),它通過在函數(shù)內(nèi)部反復(fù)調(diào)用自身來解決問題。當(dāng)一個(gè)程序調(diào)用自己時(shí),這就稱為遞歸調(diào)用。遞歸可以有助于簡化某些算法的實(shí)現(xiàn)和理解。在遞歸過程中,每個(gè)調(diào)用都會將一些數(shù)據(jù)保存在棧上,直到遞歸結(jié)束后才能被處理并彈出棧。
遞歸通常有兩個(gè)部分:基本情況和遞歸情況?;厩闆r是在函數(shù)執(zhí)行之前判斷是否需要遞歸,如果不需要,則直接返回結(jié)果。遞歸情況是函數(shù)需要遞歸時(shí),它會調(diào)用自身,但是傳入的參數(shù)通常會有所不同,以便最終能夠達(dá)到基本情況而結(jié)束遞歸。
雖然遞歸可以使代碼更加簡潔,但是需要注意的是,在一些情況下,它可能會導(dǎo)致性能問題或者棧溢出等問題。因此,在編寫遞歸代碼時(shí),需要仔細(xì)考慮算法的邊界條件和遞歸深度等因素。
2.遞歸函數(shù)
遞歸函數(shù)是一種函數(shù),它在其定義中調(diào)用自身。通常情況下,遞歸函數(shù)包含兩個(gè)部分:基本情況和遞歸情況。
基本情況是指在遞歸函數(shù)中需要判斷是否需要終止遞歸的條件。當(dāng)滿足這個(gè)條件時(shí),遞歸就會停止。
遞歸情況是指在遞歸函數(shù)中需要調(diào)用自身的情況。在每次調(diào)用時(shí),函數(shù)的參數(shù)都應(yīng)該有所不同,以便最終能夠達(dá)到基本情況而停止遞歸。
遞歸函數(shù)通常用于處理樹形結(jié)構(gòu)、圖形結(jié)構(gòu)或其他類型的嵌套結(jié)構(gòu)數(shù)據(jù)。例如,在二叉樹中查找某一個(gè)值,就可以使用遞歸函數(shù)來實(shí)現(xiàn)。
3.說明
雖然遞歸算法比較簡單,但是它是一種編程的思想,在解決部分問題時(shí),它非常適用。并且他一般作為一種工具,搭配其他思想一起使用。它是C語言數(shù)據(jù)結(jié)構(gòu)與算法中最簡單的算法,這里舉幾個(gè)例子來學(xué)會使用它。
二.斐波那契數(shù)列
1.問題描述
斐波那契數(shù)列是一個(gè)經(jīng)典的數(shù)學(xué)問題,由0和1開始,之后的每一項(xiàng)都是其前面兩項(xiàng)的和。也就是說,斐波那契數(shù)列的前幾個(gè)數(shù)是:0、1、1、2、3、5、8、13、21、34……依次類推。
斐波那契數(shù)列在自然界中有很多應(yīng)用,比如植物的葉子排列、蜂窩的構(gòu)造等等。除此之外,在計(jì)算機(jī)科學(xué)領(lǐng)域內(nèi),斐波那契數(shù)列也有著廣泛的應(yīng)用,例如在排序算法、密碼學(xué)等領(lǐng)域。
斐波那契數(shù)列的通項(xiàng)公式是:F(n) = F(n-1) + F(n-2),其中F(0)=0,F(1)=1。根據(jù)這個(gè)公式可以使用遞歸函數(shù)或循環(huán)語句來實(shí)現(xiàn)求斐波那契數(shù)列的第n項(xiàng)。
2.思路
像這種可以求出通項(xiàng)公式的數(shù)列是我們平時(shí)典型的遞歸函數(shù)運(yùn)用,通項(xiàng)公式可以定義為函數(shù),它的第一個(gè)值一般是我們的遞歸函數(shù)出口。所謂遞歸函數(shù)的出口就是結(jié)束遞歸的標(biāo)志。
現(xiàn)在理清思路后,我們來用代碼完成求斐波拉契數(shù)列的第n項(xiàng):
3.C語言代碼
#include <stdio.h>int fibonacci(int n) {if (n == 0)return 0;else if (n == 1)return 1;elsereturn fibonacci(n - 1) + fibonacci(n - 2);
}int main() {int num, i;printf("Enter the number of terms: ");scanf("%d", &num);printf("Fibonacci series terms are:\n");for (i = 0; i < num; i++) {printf("%d ", fibonacci(i));}printf("\n");return 0;
}
三.漢諾塔
1.問題描述
該問題的主要材料包括三根高度相同的柱子和一些大小及顏色不同的圓盤,三根柱子分別為起始柱A,輔助柱B及目標(biāo)柱C。
**操作規(guī)則:**每次只能移動一個(gè)盤子,并且在移動過程中三根桿上都始終保持大盤在下,小盤在上,操作過程中盤子可以置于任意桿上。
2.分析
漢諾塔是一種經(jīng)典的遞歸問題,它涉及到將一組不同大小的圓盤從一個(gè)柱子移動到另一個(gè)柱子。以下是漢諾塔的具體過程:
- 將所有圓盤從起始柱子上除最下面一個(gè)圓盤之外的其他圓盤全部移動到中間柱子。
- 將最下面的圓盤從起始柱子上移動到目標(biāo)柱子上。
- 將中間柱子上除了最下面的圓盤之外的其他圓盤全部移動到目標(biāo)柱子上。
在完成這三個(gè)步驟時(shí),需要遵守以下規(guī)則:
- 一次只能移動一個(gè)圓盤。
- 大圓盤不能放在小圓盤上面。
通過遞歸調(diào)用上述步驟,可以將所有的圓盤從起始柱子移動到目標(biāo)柱子。由于每次遞歸都會將一個(gè)圓盤從起始柱子移動到目標(biāo)柱子,因此每個(gè)圓盤最多只會被移動一次,所以總共需要移動2^n - 1 次(n 表示圓盤的數(shù)量)。
3.C語言代碼
#include <stdio.h>void hanoi(int n, char A, char B, char C) {if (n == 1) {printf("Move disk 1 from %c to %c\n", A, C);} else {hanoi(n-1, A, C, B);printf("Move disk %d from %c to %c\n", n, A, C);hanoi(n-1, B, A, C);}
}int main() {int n = 3; // 將3個(gè)盤子從A移動到Chanoi(n, 'A', 'B', 'C');return 0;
}
四.子集問題
1.問題描述
子集問題(Subset):給定一個(gè)含有n個(gè)元素的集合S,求出S的所有子集。可以使用遞歸實(shí)現(xiàn)。
2.思路分析
子集問題是一個(gè)基本的組合問題,它涉及到從一個(gè)給定的集合中選擇一些元素組成新的集合。這個(gè)問題在計(jì)算機(jī)科學(xué)和數(shù)學(xué)中非常常見,解決子集問題可以幫助我們更好地理解組合問題和算法設(shè)計(jì)。
下面是一個(gè)簡單的思路分析:
-
首先,我們需要確定如何表示集合。在大多數(shù)編程語言中,集合通常是用數(shù)組或列表來表示的。
-
接著,我們需要考慮如何生成所有可能的子集。一種常見的方法是使用遞歸算法。
-
對于遞歸算法,我們需要考慮以下幾點(diǎn):
a. 基本情況:當(dāng)集合為空時(shí),只有一個(gè)空集。
b. 遞歸情況:對于非空集合,我們可以選擇將第一個(gè)元素包含在子集中或者不包含在子集中,然后對剩余的元素進(jìn)行遞歸處理。
-
在遞歸過程中,我們需要維護(hù)一個(gè)當(dāng)前子集的列表,并在每次遞歸結(jié)束后將其添加到結(jié)果集合中。
-
最后,我們可以返回結(jié)果集合,其中包含了原始集合的所有可能子集。
需要注意的是,由于子集問題的解空間非常大,因此在實(shí)際應(yīng)用中,需要根據(jù)具體的場景進(jìn)行優(yōu)化,以減少時(shí)間和空間復(fù)雜度。
3.C語言代碼
下面是一個(gè)使用C語言遞歸實(shí)現(xiàn)子集問題的示例代碼:
#include <stdio.h>void subset(int set[], int subset[], int n, int k, int start, int curr){if (curr == k) {printf("{");for (int i = 0; i < k; i++) {printf("%d ", subset[i]);}printf("}\n");return;}for (int i = start; i < n; i++){subset[curr] = set[i];subset(set, subset, n, k, i+1, curr+1);}
}int main() {int set[] = {1, 2, 3};int n = sizeof(set)/sizeof(set[0]);int subset[n];for (int i = 0; i <= n; i++) {subset(set, subset, n, i, 0, 0);}return 0;
}
該代碼中,subset
函數(shù)使用了遞歸實(shí)現(xiàn)。其中,set
表示原始集合,subset
表示當(dāng)前子集,n
表示原始集合的大小,k
表示當(dāng)前子集的大小,start
表示遍歷起始位置,curr
表示當(dāng)前子集中元素的個(gè)數(shù)。
在函數(shù)中,首先判斷當(dāng)前子集是否已達(dá)到目標(biāo)大小 k
,如果已經(jīng)達(dá)到則輸出該子集,并返回上一層遞歸。否則,從遍歷起始位置開始循環(huán)原始集合,將元素依次加入當(dāng)前子集,并對剩余元素進(jìn)行遞歸處理。
在 main
函數(shù)中,我們遍歷所有可能的子集大小,并調(diào)用 subset
函數(shù)進(jìn)行求解。最終結(jié)果會依次輸出到標(biāo)準(zhǔn)輸出。
五.歸并排序
1.問題描述與分析
歸并排序(Merge Sort)是一種基于分治思想的高效排序算法,通過將待排序數(shù)組遞歸地拆分為兩個(gè)子數(shù)組,對每個(gè)子數(shù)組進(jìn)行排序,然后將兩個(gè)有序的子數(shù)組合并成一個(gè)有序的數(shù)組,最終得到排序完成的整個(gè)數(shù)組。
具體而言,歸并排序的過程可以分為三個(gè)步驟:
- 分割:將待排序數(shù)組從中間位置劃分為左右兩個(gè)子數(shù)組,遞歸地對左右兩個(gè)子數(shù)組進(jìn)行分割,直到每個(gè)子數(shù)組只包含一個(gè)元素。
- 歸并:將兩個(gè)有序的子數(shù)組合并成一個(gè)有序的數(shù)組,直到所有子數(shù)組都被合并為一個(gè)完整的有序數(shù)組。
- 返回:返回排序完成的數(shù)組。
2.C語言代碼
下面是用 C 語言遞歸實(shí)現(xiàn)歸并排序的代碼:
#include <stdio.h>
#include <stdlib.h>void merge(int *arr, int l, int m, int r) {int i, j, k;int n1 = m - l + 1;int n2 = r - m;int L[n1], R[n2];for (i = 0; i < n1; i++)L[i] = arr[l + i];for (j = 0; j < n2; j++)R[j] = arr[m + 1 + j];i = 0;j = 0;k = l;while (i < n1 && j < n2) {if (L[i] <= R[j]) {arr[k] = L[i];i++;} else {arr[k] = R[j];j++;}k++;}while (i < n1) {arr[k] = L[i];i++;k++;}while (j < n2) {arr[k] = R[j];j++;k++;}
}void mergeSort(int *arr, int l, int r) {if (l < r) {int m = l + (r - l) / 2;mergeSort(arr, l, m);mergeSort(arr, m + 1, r);merge(arr, l, m, r);}
}int main() {int arr[] = {38, 27, 43, 3, 9, 82, 10};int n = sizeof(arr) / sizeof(arr[0]);mergeSort(arr, 0, n - 1);for (int i = 0; i < n; i++)printf("%d ", arr[i]);return 0;
}
在上面的代碼中,merge
函數(shù)用于將兩個(gè)有序子數(shù)組合并為一個(gè)有序數(shù)組,mergeSort
函數(shù)用于遞歸地分割和排序子數(shù)組。
六.說明
新星計(jì)劃:數(shù)據(jù)結(jié)構(gòu)與算法,@西安第一深情,創(chuàng)作打卡1!