二叉树的三种遍历算法(递归和不递归)

二叉树

二又树(Binary Tree)是n(n=0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根结点和两棵互不相交的、分别称为根结点的左子树和右子树的二叉树组成。

二叉树特点

  1. 每个结点最多有两棵子树,所以二又树中不存在度大于2的结点。注意不是只有两棵子树,而是最多有。没有子树或者有一棵子树都是可以的。
  2. 左子树和右子树是有顺序的,次序不能任意颠倒。
  3. 即使树中某结点只有一棵子树,也要区分它是左子树还是右子树。

二叉树遍历

二又树的遍历(traversing binary tree)是指从根结点出发,按照某种次序依次访问二叉树中所有结点,使得每个结点被访问一次且仅被访问一次。

  • 中心思想:访问和次序。

二叉树遍历方法

  1. 前序遍历
  2. 中序遍历
  3. 后序遍历
  4. 层序遍历

前序遍历

规则是若二又树为空,则空操作返回,否则先访问根结点,然后前序遍历左子树,再前序遍历右子树。如下图所示,遍历的顺序为:ABDGHCEIF。

图1

前序遍历算法

/*前序遍历算法——递归版*/
void PreOrderTraverse(BiTree T)
{
	if(T==NULL)
	   return;
	printf("%c",T->data);/*显示节点数据*/
	PreorderTraverse(T->lchild);/*再先序遍历左子树*/
	PreorderTraverse(t->rchild);/*最后遍历右子树*/
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

/*前序遍历算法——非递归版*/

#include<bits/stdc++.h>
using namespace std;
struct node
{
    node left;
    node right;
    int value;
};
void preorder(node head)//先序遍历
{
    if(head!=null)//头节点不为空时才执行下列操作
    {
        stack < node >q;
        q.push(head);//将头节点放入栈中去
        while (!q.empty())
        {
            head=q.top();
            q.pop();
            cout<<head.value<<" ";//打印头节点
            if(head.right!=null)//如果右孩子不为空,先放右孩子.
                q.push(head.right);
            if(head.left!=null)//如果左孩子不为空,后放左孩子,这样才能保证打印顺序为:头节点-->左孩子-->右孩子
                q.push(head.left);
        }
    }
}

中序遍历

规则是若树为空,则空操作返回,否则从根结点开始(注意并不是先访问根结点),中序遍历根结点的左子树,然后是访问根结点,最后中序遍历右子树。如下图所示,遍历的顺序为:GDHBAEICF。

在这里插入图片描述

中序遍历算法

/*中序遍历算法——递归版*/
void InOrderTraverse(BiTree T)
{
	if(T==NULL)
	   return;
	PreorderTraverse(T->lchild);/*中序遍历左子树*/
	printf("%c",T->data);/*显显示结点数据,可以更改为其他对结点操作*/
	PreorderTraverse(t->rchild);/*最后中序遍历右子树*/
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

/*中序遍历算法——非递归版*/
#include<bits/stdc++.h>
using namespace std;
struct node
{
    node left;
    node right;
    int value;
};
 
void inorder(node head)//中序遍历
{
    if(head!=null)//头节点不为空时才执行下列操作
    {
        stack < node >q;
        while (!q.empty()||head!=null)//这两个条件只要满足一个,就执行下面过程
        {
            if(head!=null)
            //如果当前节点不为空,就把当前节点放入栈中去,然后让head指向当前节点的左节点,没有打印过程
            {
                q.push(head);
                head=head.left;
            }
            else if(head==null)
            //如果当前节点为空,那么就弹出栈顶的元素,打印。然后让head指向栈顶节点的右节点
            {
                head=q.top();
                q.pop();
                cout<<head.value<<" ";
                head=head.right;
            }
        }
    }
 
}

后序遍历

规则是若树为空,则空操作返回,否则从左到右先叶子后结点的方式遍历访问左右子树,最后是访问根结点。如下图所示,遍历的顺序为:GHDBIEFCA。

在这里插入图片描述

后序遍历算法

/*后序遍历算法——递归版*/
void PostOrderTraverse(BiTree T)
{
	if(T==NULL)
	   return;
	PreorderTraverse(T->lchild);/*先遍历左子树*/
	PreorderTraverse(t->rchild);/*后遍历右子树*/
	printf("%c",T->data);/*显显示结点数据,可以更改为其他对结点操作*/
}

在这里插入图片描述

/*后序遍历算法——非递归版*/
#include<bits/stdc++.h>
using namespace std;
struct node
{
    node left;
    node right;
    int value;
};
void postorder(node head)//后序遍历,利用栈能够使一段序列逆序的性质
{
    if(head!=null)//和上面一样
    {
       stack < node >q;
       stack < node >p;//辅助栈,让q栈中的弹出的节点逆序
       q.push(head);
       while (!q.empty())
       {
           head=q.top();
           //弹出栈顶节点,但是先不着急打印,而是把该节点放入p栈中去,来实现原先打印顺序的逆序
           p.push(head);
           q.pop();
           if(head.left!=null)//如果该节点的左孩子不为空,先放左孩子
               q.push(head.right);
           if(head.right!=null)//如果该节点的右孩子不为空,先放右孩子
               q.push(head.left);
       }  
       while (!p.empty())//打印辅助栈中的节点
           cout<<p.value<<" ";
    }
 
}

总结

  1. 应该说,三种有序表的查找本质上是分隔点的选择不同,各有优劣,实际开发时可根据数据的特点综合考虑再做出选择。
  2. 未知的数据首先考虑二分查找
  3. 均匀的数据适合插值查找
  4. 如果要查找的记录在右侧,则左侧的数据都不用再判断了,不断反复进行下去,对处于当中的大部分数据,斐波那契查找工作效率要高一些。

参考文献

[1] 程杰. 大话数据结构[M]. 清华大学出版社, 2011.
[2] 啊哈磊. 啊哈! 算法[M]. 人民邮电出版社, 2014.
[3] 齐鲁工业大学–栾琪_二叉树的3种遍历方法 6种实现_2018_5_19
[4] z_ryan_详解二叉树的非递归遍历_2018_6_29

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值