Java數據結構與算法(第六章遞歸)

遞歸是一種方法(函數)調用本身的編程技術。java

三角數字redis

        數字序列 一、三、六、十、1五、2一、。。。。
算法

        這個數列中的第n項是由第n-1項加n獲得了。
編程

        這個序列中數字被稱爲三角數字,由於他們能夠被形象化地表示成對象的一個三角形排列,如圖:
函數

    使用循環查找第n項post

        第n項的值,好比說第4項(其值爲10)。你會如何設計?
ui

int triangle(int n){
    int tatal = 0;
    while(n>0){
        total = total +n;
        --n;
    }
    return total;
}

這個方法循環了n次,total值在第一次循環中加n,在第二次循環中加n-1,如此循環一直到加1,當n減少到0時退出循環。spa

package com.digui;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Triangle {

    static int theNumber;
    
    public static void main(String[] args) throws IOException {
        System.out.print("Enter a number: ");
        System.out.flush();
        theNumber = getInt();
        int theAnswer = triangle(theNumber);
        System.out.println("Trinagle = "+theAnswer);
    }
    
    public static int triangle(int n)throws IOException{
        if(n==1){
            return 1;
        }else{
            return (n+triangle(n-1));
        }
    }
    
    public static String getString() throws IOException{
        InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(isr);
        return br.readLine();
    }
    
    public static int getInt() throws IOException{
        String s = getString();
        return Integer.parseInt(s);
    }
}

//輸入輸出:
Enter a number: 2
Trinagle = 3

Enter a number: 1000
Trinagle = 500500

遞歸方法的特徵設計

        全部遞歸方法都具有的關鍵特徵:
code

  •         調用自身

  • 當它調用自身的時候,它這樣作事爲了解決更小的問題。

  • 存在某個足夠簡單的問題的層次,在這一層算法不須要調用本身就能夠直接解答,且返回結果。

    在遞歸算法每次調用自身的過程當中,參數變小(也許是被多個參數秒速的範圍變小),這反映了問題變小或變簡單的事實。當參數或者範圍達到必定的最小值時,將會觸發一個條件,此時方法不須要調用自身而能夠返回。

遞歸方法有效率嗎?

        調用一個方法會有必定的額外開銷。控制必須從這個調用的位置轉移到這個方法的開始處。除此以外,傳給這個方法的參數以及這個方法返回的地址都要被壓入到一個內部的棧裏,爲的是這個方法能夠訪問參數值和知道返回到哪裏。

        就triangle()這個方法來說,由於有上述開銷二形成的結果,可能while循環方法執行的速度比遞歸的方法快。

        若是因爲遞歸方法的存在,形成了太大規模的方法調用的話,可能會考慮消除遞歸,。

        另一個低效率反映在系統內存空間存儲全部的中間參數以及返回值,若是有大量的數據須要存儲,這就會引發棧溢出的問題。

        人們經常採用遞歸,是由於它從概念上簡化了問題,而不是由於它本質上更有效率。

數學概括法

        遞歸程序設計中數學概括法。數學概括法是一種經過自身的語彙定義某事物本身的方法。(語彙也被用於描述證實原理的相關方法。)使用概括法,能夠用數學的方式定義三角數字:

        tri(n) = 1                if n=1

        tri(n)=n+tri(n-1)    if n>1

        用自身來定義某事可能看起來是在轉圈子,可是事實上它是徹底正確的(假設有一個基值狀況)。

階    乘

        階乘在概念上和三角數字相似的,只是用乘法取代了加法而已,獲得第n個三角數字是經過n加上n-1個三角數字的和,而n的階乘則是經過n乘以n-1的階乘來獲得的。

int factorial(int n){
    if(n==0){
        return 1;
    }else{
        return (n*factorial(n-1));
    }
}


變 字 位

        這是遞歸應用的另外一種狀況。

package com.digui.anagram;
import java.io.IOException;
import redis.digui.Triangle;
public class AnagramApp {
    static int size;
    static int count;
    static char[] arrChar = new char[100];
    
    public static void main(String[] args) throws IOException {
        System.out.print("Enter a word:");
        String intput = Triangle.getString();
        size = intput.length();
        count = 0;
        for (int i = 0; i < size; i++) {
            arrChar[i] = intput.charAt(i);
        }
        doAnagram(size);
    }
    
    public static void doAnagram(int newsize){
        if(newsize==1)
            return;
        for (int i = 0; i < newsize; i++) {
            doAnagram(newsize-1);
        if(newsize==2)
            displayWord();
            rotate(newsize);
        }
    }
    
    private static void displayWord() {
        if(count<99)
            System.out.print(" ");
        if(count<9)
            System.out.print(" ");
        System.out.print(++count+" ");
        for (int i = 0; i < size; i++) {
            System.out.print(arrChar[i]);
        }
        System.out.print(" ");
        System.out.flush();
        if(count%6==0){
            System.out.println("");
        }
    }
    
    public static void rotate(int newsize){
        int j;
        int postion = size-newsize;
        char temp = arrChar[postion];
        for (j = postion+1; j < size; j++) {
            arrChar[j-1] = arrChar[j];
        }
        arrChar[j-1] = temp;
    }
}

輸入輸出:
Enter a word:cats
  1 cats   2 cast   3 ctsa   4 ctas   5 csat   6 csta 
  7 atsc   8 atcs   9 asct  10 astc  11 acts  12 acst 
 13 tsca  14 tsac  15 tcas  16 tcsa  17 tasc  18 tacs 
 19 scat  20 scta  21 satc  22 sact  23 stca  24 stac


遞歸的二分查找

    遞歸取代循環

      

private int recFind(long key,int lowerBound, int upperBound){
    int curIn;
    curIn = (lowerBound + uperBound)/2;
    if(a[curIn]==key)
        return curIn;
    else if(lowerBound>upperBound)
        return nElems;
    else{
        if(a[curIn]<key)
            return recFind(key,curIn+1,uperBound);
        else
            return recFind(key,lowerBound,curIn-1);
    }
}

歸併排序

。。。。。。

。。。。。。


小        結

  • 一個遞歸的方法每次用不一樣的參數值反覆調用自身。

  • 某種參數值使遞歸的方法返回,而再也不調用自身。這種爲基值狀況。

  • 當遞歸方法返回時,遞歸過程經過逐漸完成各層方法實例的未執行部分,而從最內層返回到最外層的原始調用處。



待續。。。

197

相關文章
相關標籤/搜索