数据结构之回溯算法

借鉴:1、http://blog.csdn.net/baple/article/details/7181404

        2、http://www.cnblogs.com/steven_oyj/archive/2010/05/22/1741376.html  回溯之模板

        3、《大话数据结构》  P240页,深度优先遍历的概念(类似于树的前序遍历)

        4、这里有个对比,非递归比递归法更能体现出回溯的过程!

回溯题目解题一般步骤:1、找到题解的空间   2、找到约束条件  3、找到扩展的规则(下一步怎么走)

回溯之非递归算法:

package database;

public class NQuee2 {

    public static void NQuee2(int arr[],int n){                         
        int k=1 ;
        arr[1]=0;                                                         // 首先对进行初始化!(确定第一步先放在哪)
        while(k>0){
            arr[k]=arr[k]+1;
            while(arr[k]<=n && !Verify(arr,k))
                arr[k] = arr[k]+1;
            if(arr[k]<=n){                                           //这里能够看出什么时候回溯!
                if(k==n)
                    ResultPrint(arr,n);
                else{
                    k=k+1;
                    arr[k]=0;
                }
            }else k=k-1;                                                              
        }
    }
    
    public static boolean Verify(int arr[],int i){                              //仅仅判断能不能放置这个皇后
        for(int k =1;k != i;k++)                                                //与前i-1行进行比较
            if(Math.abs(k-i)==Math.abs(arr[i]-arr[k]) || arr[i] == arr[k])      //具体比较的方法;
                return false;
            return true;        
    }
    public static void ResultPrint(int arr[],int n){
        for(int a =1 ;a!=n+1 ;a++)
            System.out.print(a+","+arr[a]+";");
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int n = 4;
        int arr[] = new int[n+1];                                          //为什么是n+1? 这里要用n+1个空间,因为多一个空间是为了判断解是否超越了解空间!(a[k]>n的情况)

                                                                                     //如果超过了就回溯,如果没超过而且满足条件就继续往下
        NQuee2(arr,n);
    }

}


回溯之递归算法:

package database;

public class NQuee {

    public static boolean Verify(int arr[],int i){                                      //仅仅判断这个位置(int arr[],int i)能不能放置这个皇后
        for(int k =1;k != i;k++)                                                              //与前i-1行进行比较
            if(Math.abs(k-i)==Math.abs(arr[i]-arr[k]) || arr[i] == arr[k])      //具体比较的方法;
                return false;
            return true;        
    }
    public static void NQuee(int arr[] , int i , int n){
        for(int j = 1;j!=n+1;j++){                               //这里是尝试着往 第i行添加皇后     
            arr[i] = j;                                                   //尝试着往(i,arr[i])添加皇后      
                                                                            //这里注意:arr[i],而i是从1开始的,那么说arr[]要开辟n+1个空间   
        if(Verify(arr, i)){                                             //利用递归开始进行回溯算法
            if(i == n)                                                   //考虑是如何进行回溯的?见PPT
                ResultPrint(arr,n);                
            else
                NQuee(arr, i+1, n);
        }
        }
    }
    
    public static void ResultPrint(int arr[],int n){
        for(int a =1 ;a!=n+1 ;a++)
            System.out.print(a+","+arr[a]+";");
    }
    
    public static void main(String[] args) {
        int n = 4;
        int arr[] = new int[n+1];                                          //为什么是n+1? 这里要用n+1个空间,因为多一个空间是为了判断解是否超越了解空间!(a[k]>n的情况)

                                                                                     //如果超过了就回溯,如果没超过而且满足条件就继续往下

                                                                                     //数组初始化为0
        NQuee(arr,1,n);
        
    }

}

后记:回溯法之模板

1、非递归

int a[n],i;

初始化数组a[ ];

i=1;

While (i>0(有路可走)) and (未达到目标) //还未回溯到头

 { if (i=n) 搜索到一个解,输出;  //搜索到叶结点

   else                     //正在处理第i个元素

      {a[i]第一个可能的值;

       while (a[i]不满足约束条件且在搜索空间内)  

           a[i]下一个可能的值;

       if (a[i]在搜索空间内)      

            {标识占用的资源; i=i+1;}    //扩展下一个结点

       else  {清理所占的状态空间;i=i-1;}  //回溯

     }

}

递归框架:

int a[n];

try(int i)

 {   if (i>n) 输出结果;
 else

          for(j=下界 ; j<=上界; j++) //枚举i所有可能的路径
       { if ( check(j)=1)        //满足限界函数和约束条件

               { a[i]=j;

                  ……            //其它操作

                  try(i+ 1);}

             回溯前的清理工作(如:a[i]置空值);                     //有的要重头开始排序!

           }

 }

posted @ 2016-02-20 22:17  wangb021  阅读(1198)  评论(0编辑  收藏  举报