java資料結構讀書筆記--引論
1 遞迴簡論
需求:求出f(x)=2f(x-1)+x²的值。滿足f(0)=0
public class Recursion {
// 需求: 求出f(x)=2f(x-1)+x²的值。滿足f(0)=0
public static void main(String[] args) {
int f = f(1);
System.out.println(f);
}
public static int f(int x){
// 1 當x=1的時候f(1)=1 f(0)=0 f(2)=2f(1)+4=6
if (x==0)
return x;
return 2*f(x-1)+x*x;
}
}
像上面的情況來說。我們知道f(0)=0;如果不知道這個情況,那麼程式將不會計算出來。這種情況稱之為基準情況,也就是說不需要經過遞迴而直接就可以計算出來。這就是基準情況。
接著我們再來看一個情況:如下程式碼所示。
public static int bad(int n){
if(n==0)
return 0;
return bad(n/3+1)+n-1;
}
Exception in thread “main” java.lang.StackOverflowError
at com.gosaint.firstChapter.Introduction.Recursion.bad(Recursion.java:25)
at com.gosaint.firstChapter.Introduction.Recursion.bad(Recursion.java:25)
at com.gosaint.firstChapter.Introduction.Recursion.bad(Recursion.java:25)
程式出現了棧溢位。這是因為沒有基準情況的。當n=1,此時bad(1)。但是bad(1)的值不知道,因此無法繼續遞迴下去。也就是說,遞迴必須要滿足的條件:
a 必須存在基準情況
b 能夠持續不斷的進行單方向的迴圈
需求:計算 一個數N中的二進位制中1的個數:
計算說明:
1 對於一個數,首先將其轉換為二進位制,對於其中1或者0的個數分別可以如下的計算:
n&(n-1):其中計算1的個數
n|(n+1):其中計算出0的個數
詳細的解釋下:如9的二進位制是:1001。其中的1的個數為2。9&8的結果是1000。消除了右邊的1。繼續迴圈消除。從而得到1的個數。
2 對於一個奇數而言,其中二進位制中1的個數為n/2的數中二進位制的個數加1
遞迴的方式計算一個數中二進位制中1的個數
public static int binarySystem(int N){
if(N%2!=0){
return binarySystem(N/2)+1;
}else {
// 如果N為偶數,二進位制中1的個數計算如下:
int n;
for ( n=0;N>0;n++){
N&=(N-1);
}
return n;
}
}
直接進行計算,不適用遞迴的方式
/**
* 由於n&(n-1)的這種方式可以直接計算,因此可以不用使用遞迴的方式操作
* @param N
* @return
*/
public static int binarySystem02(int N) {
int n;
for (n = 0; N > 0; n++) {
N &= (N - 1);
}
return n;
}