• 递归的理解1


    递归的大体总结:自己调用自己。大家都知道的道理。但是递归维数比较多的时候还是比较难以理解。我这里用了维数这个概念,其实就是一个函数里面包含了几个自己,一维就是一个函数里面只调用了一个自己二维两个以此类推。

    一维情况。只是简单的线性关系。也就是对于任何有线性关系的结构都可以使用递归。这个线性结构是指数据之间的关系。比如从当前的可以获取下一个就可以,例如链表中,有当前的可以得到下一个。或者十进制转化二进制时候参数传递。其实就是通过当前的参数可以得到下一个要处理函数的参数。可能说的时候不能清除表达意思,下面通过例子来说明

    比较经典的例子一个链表的遍历

    伪代码

    struct Node

    {

           int content;

           Node *next;

    }

    和基本的数据结构一样最后一个节点的next为NULL,链表有一个头结点header不存放数据。

    void ListVist(Node *n)

    {

           if (n == NULL)

                  return;

           else

           {

                  cout<<n->content;

                  ListVist(n->next);

           }

    }

    逆序打印

    void ListVisit2(Node *n)

    {

           if (n == NULL)

                  return;

           else

           {

                  ListVisit2(n->next);

                  cout<<n->content;

           }

    }

    结合前面说的链表的线性关系,由每一个当前节点可以得到后一个节点。这是他们的线性关系。然后就是对每个节点进行操作。

    这两个例子个人觉得比较经典,可以看出来单一的递归就是只是简单的线性的处理数据。当递归语句是最后一句的时候,就是直接线性的执行到最后一个元素,但是如果是后面还有后续的就是入栈然后从后往前执行。其实递归语句放最后也是一个入栈出栈过程但是语句已经执行完了。

    在放一个例子提高下理解吧阶乘 f(n) = n*(n-1)*(n-2)………1

    这个可以看出来有线性关系(嗯,其实有线性关系都可以递归)

    伪代码

    Int f(int n)

    {

           If (n == 1)

                  Return;   //出口

    Else

           Return n*f(n-1);

    }

    或许应该这样说,对于每一个元素只要有相同的操作就可以递归,对于阶乘就是对每个元素乘以以前所有元素的所有乘积(正向逆向无所谓) 上面的可以这样写 m为一全局变量

    void f(int n)

    {

           If (n== 1)

                  Return;

          Else

                  m = m*n;

                  f(n-1);

    }

    同时在添加一个 十进制转二进制 原子操作 对于每一个数 取他的余数

    正向将每一个余数放入vector<int> s

    Void convert(int n)      //参数为十进制数

    {

           If (n == 0)

                  Return;

          Else

         {

                  N = n%2;

                  s.insert(n);

                  convert(n);

    }

    }

    嗯,后两个修改的比较满意了,虽然多用了变量,但是这里只是为了理解递归,例子只是为了最容易理解。

    这里在放一个我当初理解起来很费劲的一个例子虽然是一维,但是掺杂循环。解决的问题倒也普通。组合。

    好了,只有单一一个递归其实还是比较容易理解的。

    第二个开始用一个比较熟悉的东西开始,快速排序 只写递归调用那部分的,

    int partition(int m, int n)

    {

           int i = m-1;

           int j = m;

           int temp;

           for (; j < n; j++)

           {

                  if (content[j] < content[n])

                  {

                         i++;

                         temp = content[j];

                         content[j] = content[i];

                         content[i] = temp;

                  }

           }

           temp = content[++i];

           content[i] = content[n];

           content[n] = temp;

           return i+1;

    }

     

    void quiciSort(int m, int n)

    {

           if (m <= n)

                  return;

           else

           {

                  int x = partition(m,n);

                  quickSort(m, x-1);

                  quickSort(x, n);

           }

    }

    只看quickSort函数, 递归说到底只是一个遍历,一维是线性,二位是树,仅此而已。程序中能够对于每个节点需要这种处理,都可以使用。 这点还不能表达我的意思。

    其实看这个  可以自己做个试验

    void test(int n);

    {

           if (n == 1)

                  return;

           else

           {

                  cout<<n<<" ";

                  test(n-1);

                  test(n-1);

           }

    }

    应该有似曾相识的感觉吧。如果把n改为树的节点这个就是树的线序遍历。其实两个递归放一起就是这个效果。按树的方式对于每个节点进行操作。其实跟一个一样。这个例子对比下上面那个快速排序然后就会明白,按树的方式每次递减一下数组的大小,每次把一个数字放到它应该呆的位置。仅此而已。

    然后类似于一个递归时候里面的逆序,其实两个递归调用的时候同样可以这样。

    其实另外一个对比的例子是对于每个原子节点进行后续遍历的。归并排序就是很典型的一个。对于最后的节点先进行访问,然后在一次网上访问。明天添加归并排序的。然后突然想到一个自己定义为一维的求组合的一个程序,这个理解还是有问题。

  • 相关阅读:
    gitment Error:validation failed错误解决办法
    Hexo博客yilia主题添加Gitment评论系统
    用DateTime的ParseExact方法解析特殊的日期时间
    C#中的日期处理函数
    SQL,Linq,Lambda之间的转换练习
    Windows Azure Platform 系列文章目录
    Linq查询表达式
    EF框架的三种工作方式
    jQuery UI 实现图片循环显示,常用于网站首页banner广告切换
    jQuery UI Datepicker
  • 原文地址:https://www.cnblogs.com/hatreds/p/2317004.html
Copyright © 2020-2023  润新知