zoukankan      html  css  js  c++  java
  • 递归的狂想(菜鸟的胡思乱想)

    和很多学习刚学习算法的同学来说,递归是摆在我们面前的一道坎

    结合数据结构中的二叉树和图的遍历,逛了逛51cto和csdn还有一些大牛博客,总算能摸着一些头绪了。
     
    递归--传递和回归
    1:传递
    将规模为n的问题,传递为n-1或者n-2 更小也行
       这要求解决A问题依赖于解决小A问题
       也可以是,解决A问题=解决一个小菜问题+解决小A问题
    如遍历一颗二叉树,可以是遍历左子树+遍历右子树
    如遍历一幅图,打印一个节点,再从它的临节点开始遍历一副少一个结点的图
     
    不要以为递归只是执行一次,f(n)不能解决,f(n-1)当然也难以解决。当问题规模不断的缩小,直到n=1or n=2这样规模的问题基本就可以解决了 
    举例  f(n)=f(n-1)+f(n-2)     未知
    f(5)=f(4)+f(3)     未知
    f(4)=f(3)+f(2)已知
    f(3)=f(2)已知+f(1)已知
    (感谢 Ewarder 提供)
     
    2:回归
    当问题的规模中出现已知,如上图,就可以将 解 带回
     
    总结:引用一张觉得概括性很高的图片

    (来自Wiki—

    怎样解递归题目
    根据题目获取递归表达式(一般采用数学归纳法,即带值慢慢找规律)
     
    递归的表达式(表现形式:自己定义自己)
    这里用斐波那契的例子来说明
     
    f(n)=
    1. 1                       (n=1)   (回归用) 递归终止条件   即当执行f(1) 终止
    2. 2                        ( n=2)    (回归用) 递归终止条件  即当执行f(2)时 终止
    3. f(n-1)+f(n-1)     (n>2)   (传递用)
    可以看成是分段函数的编程(if语句就行了)
     
     
    递归的作用
    分解(依赖传递)Divide
     
     
    递归与分治  Recurison <->Divide&Conqur
    Ex.1 归并排序(递归)
    归并排序(递归)
     1 #include<stdio.h>
     2 
     3 
     4 
     5 void mergesort(int *num,int start,int end);// 声明一个递归函数--Divide  形参为(数组指针,数组头指针,数组尾指针)
     6 
     7 
     8 void merge(int *num,int start,int middle,int end);// 这个函数用来将两个排好序的数组进行合并---Conqur
     9 
    10 int main()
    11 {
    12     // 测试数组
    13     int num[10]= {12,54,12,67,86,45,97,32,14,65};
    14     int i;
    15     // 排序之前
    16     printf("Before sorting:\n");
    17     for (i=0; i<10; i++)
    18     {
    19         printf("%3d",num[i]);
    20     }
    21     printf("\n");
    22     // 进行合并排序
    23     mergesort(num,0,9);
    24     printf("After sorting:\n");
    25     // 排序之后
    26     for (i=0; i<10; i++)
    27     {
    28         printf("%3d",num[i]);
    29     }
    30     printf("\n");
    31     return 0;
    32 }
    33 
    34 
    35 
    36 //这个函数用来将问题细分
    37 
    38 void mergesort(int *num,int start,int end)
    39 {
    40     int middle;
    41     if(start<end)
    42     {
    43         middle=(start+end)/2;  //数组中间位置的那个数  (区间上的中点)
    44         // 归并的基本思想
    45         // 排左边
    46         mergesort(num,start,middle);
    47         // 排右边
    48         mergesort(num,middle+1,end);
    49         // 合并
    50         merge(num,start,middle,end);
    51     }
    52 }
    53 
    54 
    55 
    56 //这个函数用于将两个已排好序的子序列合并
    57 
    58 void merge(int *areadysort,int start,int middle,int end)
    59 {    int * temparry=new int[end-start+1];  //动态分配内存(注意不能用a[num]的形式
    60      int indexA=start;
    61      int indexB=middle+1;
    62      int I=0;
    63      while((indexA<=middle)&&(indexB<=end))   //扫描两个序列
    64      {
    65          if  (areadysort[indexA]<=areadysort[indexB])
    66             
    67              temparry[I++]=areadysort[indexA++];
    68              
    69         else 
    70             if(areadysort[indexB]<=areadysort[indexA])
    71              temparry[I++]=areadysort[indexB++]; 
    72             
    73      }
    74          while(indexA<=middle)//复制没有比较完子表中的元素
    75                      
    76             temparry[I++]=areadysort[indexA++];
    77          while(indexB<=end)
    78              temparry[I++]=areadysort[indexB++];
    79 
    80          I=0;
    81          int tmp = end-start;
    82          while(I<=tmp)
    83              areadysort[start++]=temparry[I++];  //aready
    84           printf("%5d\n",I);
    85   
    86          
    87      }

    Ex.2 全排列

    全排列
     1 #include <stdio.h>  
     2 
     3 int n = 0;  //全局计数器,全排列的个数
     4 
     5 void swap(int *a, int *b) 
     6 {     
     7     int m;     
     8     m = *a;     
     9     *a = *b;     
    10     *b = m; 
    11 }  
    12 void perm(int list[], int k, int m) //m是数组最大下标,k是当前递归的标记
    13 {     
    14     int i;     
    15     if(k > m)   //当计数器大于最大下标时,
    16     {          
    17         for(i = 0; i <= m; i++)             
    18         printf("%d ", list[i]); //输出的全排列是交换后的临时结果
    19         printf("\n");         
    20         n++;     
    21     }     
    22     else     
    23     {         
    24     for(i = k; i <= m; i++)         
    25         {             
    26             swap(&list[k], &list[i]); //把选好的元素放到最前面来
    27             perm(list, k + 1, m);
    28             swap(&list[k], &list[i]); //排列好之后,再换回来,等着下次交换
    29         }     
    30     } 
    31 } 
    32 int main() 
    33 {     
    34     int list[] = {1, 2, 3};     
    35     perm(list, 0, 2);     
    36     printf("total:%d\n", n);     
    37     return 0; 
    38 }

     Ex.3 快速排序

    快速排序
     1 #include<stdio.h>
     2 #include<iostream.h>
     3 
     4 int count = 0;
     5 
     6 void Swap(int *a,int *b)
     7 {
     8     printf("Swap begin\n");int t;
     9     t = *a;
    10     *a = *b;
    11     *b =t;
    12 }
    13 int Partition( int a[],int p,int r)
    14 {
    15     printf("Partition begin\n");
    16     int i = p; //一個指針指向數組頭部
    17     int j = r+1; //一個指針指向數組尾部  (+1是為了下面方便操作)
    18     int x = a[p];    //设置pivot
    19     while(true)
    20     {    
    21         while(a[++i]<x&&i<r);
    22         while(a[--j]>x); //(得益于+1)
    23             if(i>=j) break;
    24             Swap(&a[i],&a[j]);
    25     }
    26 a[p]=a[j];
    27 a[j]=x;//pivot落到最终位置;
    28 return j;
    29 }
    30 void QuickSort( int a[],int p,int r)
    31 { 
    32     printf("%d QickSort begin\n", count++);
    33     int q ;  //划分位置
    34     if(p<r)  //待排数组中 只剩下
    35     {    q = Partition(a,p,r);
    36         QuickSort(a,p,q-1);
    37         QuickSort(a,q+1,r);
    38     }
    39 }
    40 
    41 
    42 
    43 
    44 void main()
    45 {   int a[]={8,6,3,1,5,6,4,2,7};
    46 
    47 cout<<"The array before sort:"<<endl;
    48 for(int i=0;i<9;i++)
    49 printf("%2d",a[i]);
    50 printf(" OK \n");
    51 
    52 QuickSort(a,0,8);
    53 printf(" OK\n");
    54 
    55 cout<<"The array after sort:"<<endl;
    56 for(i=0;i<9;i++)
    57 printf("%2d",a[i]);
    58   printf("\n");
    59 }

    递归与动态规划 Recurison <->Dinamic Programming

     Ex.2 爬楼梯(DP)

    爬楼梯之动态规划
     1 #include<iostream.h>
     2 int table[6];   // 表格,儲存全部問題的答案。 
     3 bool solve[6];  // 紀錄問題是否已經計算完畢 
     4 
     5 int f(int n) 
     6 { 
     7     if (n == 0 || n == 1) 
     8         return 1; 
     9 
    10     if (solve[n]) 
    11         return table[n]; 
    12 
    13     table[n] = f(n-1) + f(n-2); // 將答案存入表格 
    14     solve[n] = true;            // 已經計算完畢 
    15 
    16     return table[n]; 
    17 } 
    18 
    19 void main()   //Stair_Climbing  5阶楼梯
    20 { 
    21     // initial 
    22     for (int i=0; i<=5; i++) 
    23         solve[i] = false; 
    24 
    25     // compute 
    26     cout << "爬完五階的踏法有" << f(5) << "種\n"; 
    27 
    28 
    29     int n;   //Stair_Climbing   5阶以下楼梯
    30 
    31     cout<<"请输入:一个五阶以下的楼梯\n";
    32     while (cin >> n && (n >= 0 && n <= 5)) 
    33     { 
    34         cout << "爬完" << n << "階的踏法"
    35             << "" << f(n) << "種\n";
    36         cout<<"请输入:一个五阶以下的楼梯\n";   //这句必须放在最后,即下一个循环之前
    37     } 
    38 }

     递归与回溯

    Ex1 n皇后迭代回溯

    迭代回溯
     1 #include <stdio.h>
     2 #include <iostream.h>
     3 #include <iomanip.h>
     4 #include <math.h>
     5 
     6 class Queen{
     7     friend int nQueen(int);
     8 private:
     9     bool Place(int k);
    10     void Backtrack(void);
    11     void display();
    12     int n, //皇后个数
    13         * x;  //当前解        
    14     long sum; //当前已找到的可行方案
    15 };
    16 
    17 bool Queen::Place(int k)
    18 {
    19   for (int j=1;j<k;j++)
    20     if ((abs(k-j)==abs(x[j]-x[k]))||(x[j]==x[k]))  //不满足隐约束
    21            return false;
    22     return true;
    23 } 
    24 
    25 void  Queen::Backtrack(void)
    26 {  
    27     x[1] = 0;
    28     int k = 1;
    29     while (k>0) {
    30         x[k]+=1;  //遍历所有孩子
    31         while((x[k]<=n)&&!(Place(k))) x[k]+=1; //对每个孩子进行尝试
    32         if (x[k]<=n)  //执行到这一行只有种可能,1。当前行没有可行解 2.找到一个活节点
    33             if (k==n){    //已经搜索到第n行(在第n行已经找到一个活节点)
    34                 sum++;
    35                 display();
    36                 cout<<"\n";
    37             }
    38             else{
    39                 k++;    //深度搜素
    40                 x[k]=0;  
    41             }
    42             else k--;  //回溯
    43     }
    44  }
    45 
    46 void Queen::display( ){
    47     //输出n个皇后在棋盘图形上的位置
    48     int i,j;
    49     int queenq[100][100];
    50     for ( i=1; i<=n; i++)
    51         for ( j=1; j<=n; j++)
    52             queenq[i][j] =0;  //初始化棋盘图形矩阵
    53     for ( i=1; i<=n; i++)
    54             if (x[i]) queenq[i][x[i]] =1;  //为棋盘图形矩阵赋值            
    55 
    56     for( i=1;i<=n;i++){  //输出棋盘图形
    57        cout << "(" <<" ";
    58        for ( j = 1; j<=n; j++)
    59            if(queenq[i][j]) cout << "Q" << "  ";
    60            else cout << "*" << "  ";
    61        cout << ")" << endl;
    62     }
    63 }
    64 
    65 
    66 int nQueen(int n)
    67 { Queen X;
    68   X.n = n;
    69   X.sum = 0;
    70   int *p = new int [n+1];
    71   for (int i = 0; i<=n; i++)
    72       p[i] = 0;
    73   X.x = p;
    74   X.Backtrack();
    75   delete [] p;
    76   return X.sum;
    77 }
    78 
    79 void main( )
    80 { 
    81   int n,sum;
    82   while(1){
    83        cout << "用迭代回溯法解n后问题"<<"\n"<<endl;
    84        cout << "请输入皇后的数目(不超过16个):  ";
    85        cin >> n;
    86        sum = nQueen(n); 
    87        cout << "一共有"<<sum<<"种情况"<<endl; 
    88        cout<<"\n"<<endl;
    89        }
    90 }

      n皇后递归回溯

    递归回溯
     1 #include <stdio.h>
     2 #include <iostream.h>
     3 #include <iomanip.h>
     4 #include <math.h>
     5 
     6 class Queen{
     7     friend int nQueen(int);
     8 private:
     9     bool Place(int k);
    10     void Backtrack(int t);
    11     void display();
    12     int n, //皇后个数
    13         * x;  //当前解        
    14     long sum; //当前已找到的可行方案
    15 };
    16 
    17 bool Queen::Place(int k)
    18 {
    19   for (int j=1;j<k;j++)
    20     if ((abs(k-j)==abs(x[j]-x[k]))||(x[j]==x[k]))  //不满足隐约束
    21            return false;
    22     return true;
    23 } 
    24 
    25 void  Queen::Backtrack(int t)   //搜索解空间中的第t层子树(先序遍历空间树)
    26 {  
    27     if (t>n) { 
    28         sum++;  //到达叶结点,搜索到一个解
    29         display();        
    30         cout<<'\n';
    31     }
    32     else
    33       for (int i=1;i<=n;i++) {
    34         x[t]=i;  //在第
    35         if (Place(t)) Backtrack(t+1);
    36       }
    37  }
    38 
    39 void Queen::display( ){
    40     //输出n个皇后在棋盘图形上的位置
    41     int i,j;
    42     int queenq[100][100];
    43     for ( i=1; i<=n; i++)
    44         for ( j=1; j<=n; j++)
    45             queenq[i][j] =0;  //初始化棋盘图形矩阵
    46     for ( i=1; i<=n; i++)
    47             if (x[i]) queenq[i][x[i]] =1;  //为棋盘图形矩阵赋值            
    48 
    49     for( i=1;i<=n;i++){  //输出棋盘图形
    50        cout << "(" <<" ";
    51        for ( j = 1; j<=n; j++)
    52            if(queenq[i][j]) cout << "Q" << "  ";
    53            else cout << "*" << "  ";
    54        cout << ")" << endl;
    55     }
    56 }
    57 
    58 
    59 int nQueen(int n)
    60 { Queen X;
    61   X.n = n;
    62   X.sum = 0;
    63   int *p = new int [n+1];
    64   for (int i = 0; i<=n; i++)
    65       p[i] = 0;
    66   X.x = p;
    67   X.Backtrack(1);
    68   delete [] p;
    69   return X.sum;
    70 }
    71 
    72 void main( )
    73 { 
    74   int n,sum;
    75   while(1){
    76        cout << "用递归回溯法解n后问题"<<"\n"<<endl;
    77        cout << "请输入皇后的数目(不超过16个):  ";
    78        cin >> n;
    79        sum = nQueen(n); 
    80        cout << "一共有"<<sum<<"种情况"<<endl; 
    81        cout<<"\n"<<endl;
    82        }
    83 }
  • 相关阅读:
    TestNG之Factory
    Selenium2怎么调用selenium1中方法
    JAVA如何随机生成一个汉字
    selenium如何随机选取省份和城市的下拉框的值
    Bootstrap之登陆页面范例
    Bootstrap之信息记录
    Bootstrap之表格、表单应用
    Bootstrap之响应式导航栏
    Bootstrap之网格类
    使用fastjson将对象和字符串进行转换
  • 原文地址:https://www.cnblogs.com/thywings/p/2812279.html
Copyright © 2011-2022 走看看