zoukankan      html  css  js  c++  java
  • 递归与回溯

    递归:是调用一个和调用者同名的方法,他并不是一个方法调用自身,而是方法的一个实例调用相同方法的另一个实例。

    递归分为:尾递归,非尾递归,间接递归以及过分递归;

    相比于迭代,递归的效率低,但是递归的解决方案简单,与源算法逻辑一致性强,使用迭代需要定义一个新的数据结构实现堆栈,迭代应当适用在实时系统。

    实例:斐波那契数列使用递归实现:

    0,1,1,2,3,5,8, 13, 21, 34, 55, 89 ......

    Fib(n) = n 当n < 2时;Fib(n) = Fib(n-2) + Fib(n-1) 其他情况;

    在Java中可以直接定义一个函数Fib然后使用迭代实现:

        public int Fib(int n) {
            if(n < 2) {
                return n;
            }else {
                return Fib(n-2) + Fib(n-1);
            }
        }

    这个方法简单易懂,但是效率极低,在计算第26个斐波那契数时,大约需要25万次的调用,计算第31个数时需要接近三百万个调用,代价很高。

    在计算相对较小的数时可以采用递归,

    在计算较大数据时可以采用迭代实现:

        public int iterativeFib(int n) {
            if(n < 2) {
                return n;
            }else { 
                int i = 2, temp, current = 1, last = 0;
                for(; i <= n;i++) {
                    temp = current;
                    current += last;
                    last = temp;
                }
                return current;
            }
        }

    回溯:从某点出发有很多的道路选择,但是不清楚那一条道路能有效地解决问题,尝试一条道路失败后,返回到岔路口再试另外的道路,我们必须确定所有的路都是可以尝试的,可以返回的。

    一个经典的回溯问题:

    八皇后问题:将八个皇后放在一个棋盘上,要求他们不能相互攻击,规则是一个皇后可以攻击同一行,同一列以及和他在同一条对角线上的任意皇后。

    解决问题的伪代码:

    putQueen(row)

      for 同一row的每个位置col

      if  col可用

        把下一个皇后放在col上

      if(row < 8)

        putQueen(row+1)

      else 成功;

      取走col上的皇后

    算法的java实现如下:

    package queen;
    import java.io.*;
    
    public class Queens {
        static final int squares = 8, norm  = squares - 1;
        static final boolean available = true;
        static int [] positionInRow = new int[squares];
        static boolean [] column = new boolean[squares];
        static boolean [] leftDiagonal = new boolean[squares*2 -1];
        static boolean [] rightDiagonal = new boolean[squares*2 -1];
        static int howMany = 0;
        
        public Queens() {
            //初始化
            for(int i = 0;i < squares; i++) {
                positionInRow[i] = -1;
                column[i] = available;
            }
            for(int i = 0; i < squares*2 -1;i++) {
                leftDiagonal[i] = rightDiagonal[i] = available;
            }
        }
        static void printBorad(PrintStream out) {
            System.out.println("第"+howMany+"种摆放方式:");
            //循环打印可行解决方案q表示可行位置
            for(int i=0;i<squares;i++){
                for(int j=0;j<squares;j++){
                    if(i == positionInRow[j]){
                        System.out.print("q ");
                    }else
                        System.out.print("* ");
                }
                System.out.println();
            } 
        }
        
        static void PutQueen(int row) {
            for(int col = 0; col < squares;col++) {
                if(column[col] == available &&
                    leftDiagonal[row+col] == available &&
                    rightDiagonal[row - col +norm] == available) {
                    //确认下一个可以放置的位置
                    
                    positionInRow[row] = col;
                    
                    //找到可放置位置后,确定不可行域
                    column[col] = !available;
                    leftDiagonal[row+col] = !available;
                    rightDiagonal[row-col+norm] = !available;
                    
                    //遍历所有的行
                    if(row < squares - 1) {
                        PutQueen(row+1);
                    }else {
                        printBorad(System.out);
                        ++howMany;
                    }
                    //重置可行域
                    column[col] = available;
                    leftDiagonal[row+col] = available;
                    rightDiagonal[row-col+norm] = available;
                }
            }
        }
        static public void main(String[] args) {
            Queens queens = new Queens();
            queens.PutQueen(0);
            System.out.println("There are " + howMany + " solutions for this problem!");
        }
    }    
  • 相关阅读:
    msgs no .h file
    我们为之奋斗过的C#之---简单的库存管理系统
    我们为之奋斗过的C#-----C#的一个简单理解
    套接字之sendto系统调用
    套接字之msghdr结构
    套接字之select系统调用
    套接字之close系统调用
    TCP之listen&backlog
    套接字之相关系统调用的调用流程
    套接字之shutdown系统调用
  • 原文地址:https://www.cnblogs.com/lc1475373861/p/10722627.html
Copyright © 2011-2022 走看看