【算法题】二叉树的前序遍历(递归和非递归算法分析)

          问题:对二叉树的前序遍历(递归和非递归算法)

递归算法输出根节点的值
         对左子树进行左遍历
         对右子树进行遍历

  代码如下:
void PreorderTraversal(node *root)
{
  if(root)
   printf("%d\n",root->value);
else
return ;
PreorderTraversal(root->left);
PreorderTraversal(root->right);
}

这个算法的执行时间是多少呢?因为每个节点被检查了一次,所以它是O(n)级的。

        非递归算法:要完成该算法,需要深入分析一下递归算法的本质,再用循环算法来模拟它的动作。递归算法使用了堆栈这种数据结构,利用堆栈来完成数据处理。
堆栈的四个函数:

int Push(element **stack,void *data);
int Pop(element **stact,void **data);
int CreateStack(element **stack);
int deleteStack(element **stack);


首先来探究下递归算法的本质:
递归算法:a.输出根节点的值
          b.对左子树进行左遍历
          c.对右子树进行遍历


           第一次进入递归函数的时候,先输出根节点的值,然后递归地调用这个函数对左子树进行遍历。在发出这个递归调用的时候,调用者的程序状态就会被压入堆栈保存起来,这样在递归调用返回时,调用者就能从自己离开的地方开始继续执行。
         对左遍历算法来说,调用者将继续对右子树进行左遍历。为了能在遍历完左子树之后开始对右子树的遍历,递归调用隐含地把右子树的地址保存在堆栈上。在输出一个节点之后但在前进到它的左节点之前,该节点的右节点将被压入一个你不知道的堆栈里保存起来。当没有子节点可供处理时,就会从递归调用中返回一层,从堆栈上弹出一个右节点,然后以它为起点继续进行左遍历。
         总结:这个算法先输出当前节点的值,然后再把它的右节点压入堆栈,然后前进到它的左节点;当没有子节点可供处理时,算法将从堆栈上弹出一个新的当前节点。这个过程将一直重复到遍历完所有的节点为止,堆栈里也不再有任何数据。
 
 注:必须保证左节点总是先于右节点被弹出来,所以得先压入右节点,再压入左节点。


  非递归算法如下:
    创建堆栈
     把根节点压入堆栈
    当堆栈不为空,循环
     弹出一个节点
     如果这个节点不是NULL
       输出它的值
       把这个节点的右节点压入堆栈
       把这个节点的左节点压入堆栈


 代码如下:
 
 void PreorderTraversal(node *root)
{
element *theStack;
void *data;
node *curNode;
CreateStack(&theStack);
Push(&theStack,root);
while(Pop(&theStack,&data))
{
curNode=(node *)data;
if(curNode)
{
printf("%d\n",curNode->value);
Push(&theStack,curNode->right);
Push(&theStack,curNode->left);
}
}
DeleteStack(&theStack);
}

这个算法的时间开销也是O(n)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值