递归的理解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改为树的节点这个就是树的线序遍历。其实两个递归放一起就是这个效果。按树的方式对于每个节点进行操作。其实跟一个一样。这个例子对比下上面那个快速排序然后就会明白,按树的方式每次递减一下数组的大小,每次把一个数字放到它应该呆的位置。仅此而已。

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

 

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

posted on 2012-01-09 13:25  hatreds  阅读(1028)  评论(0编辑  收藏  举报