乱扯递归与非递归

  最近在学数据结构的树,学了二叉树之后,老师一直在说要实现对二叉树的递归和非递归两种形式的先序,中序和后序遍历,六个程序。会不会遍历暂先不谈,对于递归和非递归我也是一头雾水。

  今天空闲时间想编写对二叉树的建立与遍历,但是发现毫无头绪,所以我先了解了对于程序的递归和非递归两种形式

 递归:程序调用自身的编程技巧称为递归( recursion)。递归做为一种算法程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。

 这是百度对递归的定义,对于像我这种小白来说,看了和没看一个样,其实递归简单的来说,就是函数不断的调用他自己本身来实现程序的不断运行。我们常见的汉诺塔问题,斐波那契组合问题,都是不断的用递归来实现程序的运行

  非递归用通俗的语言来说,就是我们常见的循环程序。While、do..while、for等等通过这些语句来实现程序的不断运行。

 先拿一个程序来距离两种程序的区别:

 

递归算法:

#include

#include

void main()

{

int Fibonacci(int n);

int n, i, c = 0;

 

printf("请输入n的值:");

scanf("%d", &n);

for (i = 1; i <= n; i++)

{

c = Fibonacci(i);

printf("%12ld", c);

if (i % 4 == 0) //用于换行 4个一行;

printf("\n");

}

system("pause");

}

 

int Fibonacci(int n)//函数部分;

{

long int f;

 

if (n == 1 || n == 2)

{

f = 1;

}

else

if (n >= 3)

f = Fibonacci(n - 1) + Fibonacci(n - 2);

return f;

}

 

非递归算法:

 

#include

void main()

{

int i,n;

int f[]= {1,1};

printf("请输入n的值:");

scanf("%d",&n);

for(i=2; i<=n; i++)

f[i] = f[i-2] + f[i-1];

for(i=0; i<=n; i++)

{

if(i%5==0) printf("\n");

printf("%12d",f[i]);

 

}

printf("\n");

}

 

可以看出,递归算法就是用一个函数来实现某一个小的项目,然后这个小项目可以堆加起来变成最终想要求的大项目,函数通过不断的调用本身,并且递归算法还需要有一个临界条件,就是什么时候能够退出这个调用。非递归算法在我看来就是技术含量相对低的一些语句和算法,通过c语言中常见的循环语句来实现程序的运行。

 

 

再看我现在遇到的问题就是用递归和非递归两种方式来实现二叉树的遍历,由于我现在确实对于二叉树的创建和遍历还是一头雾水所以代码全都是网上找来的,但是这两个代码十分利于我来了解递归和非递归两种方式的区别。

这是二叉树的先序递归遍历代码:

  void pre_traverse(BTree pTree)

{

if(pTree)

{

printf("%c ",pTree->data);

if(pTree->pLchild)

pre_traverse(pTree->pLchild);

if(pTree->pRchild)

pre_traverse(pTree->pRchild);

}

}

 

可以看出这里函数在不断的调用函数自己本身来实现对二叉树的遍历。

 

二叉树的先序非递归遍历代码:

 void pre_traverse(BTree pTree)

{

PSTACK stack = create_stack();  //创建一个空栈

BTree node_pop;                 //用来保存出栈节点

BTree pCur = pTree;             //定义用来指向当前访问的节点的指针

 

//直到当前节点pCur为NULL且栈空时,循环结束

while(pCur || !is_empty(stack))

{

//从根节点开始,输出当前节点,并将其入栈,

//同时置其左孩子为当前节点,直至其没有左孩子,及当前节点为NULL

printf("%c ", pCur->data);

push_stack(stack,pCur);

pCur = pCur->pLchild;

//如果当前节点pCur为NULL且栈不空,则将栈顶节点出栈,

//同时置其右孩子为当前节点,循环判断,直至pCur不为空

while(!pCur && !is_empty(stack))

{

pCur = getTop(stack);

pop_stack(stack,&node_pop);

pCur = pCur->pRchild;

}

}

}

很明显可以看出函数主要是通过循环来实现不断的遍历二叉树。

 

 对于二叉树的遍历等我弄懂之后肯定还会有详细的解释所以在这里就不过多的解释遍历的问题了,我直接也还不是很懂。

 那么,递归和非递归到底哪个好哪个不好,为什么会有这两种方式呢?其实并没有哪个好哪个不好,各有各自的优点和缺点。递归的优点在于递归的代码十分清晰,可读性十分强,对于任何人来说都是十分利于理解某一个程序。十分利于代码之后的维护。但是对于递归来说也有很大的缺点,递归需要开辟很多的栈帧空间,所以在空间的消耗上要比非递归多很多。

因此非递归的优缺点也就十分的明显,非递归的效率十分的高。

 

 

这里有几个我在看递归和非递归时十分有用的博客地址如果我说的不够清楚的话大家可以找以下几个链接:

http://blog.csdn.net/luojinping/article/details/6900768

https://www.cnblogs.com/bakari/p/5349383.html

http://blog.csdn.net/ns_code/article/details/12977901/

这几个大佬讲的都十分的清楚。

 

 

  

你可能感兴趣的:(数据结构)