C语言非递归实现二叉树的三种遍历算法:前序、中序、后续

C语言非递归实现二叉树的三种遍历算法:前序、中序、后续

目录

遍历的基本概念-必读

二叉树由三个元素组成,分别是根节点D,左子树L,右子树R。理论上存在六种遍历方法,分别是:DLR(先序)、LDR(中序)、LRD(后序)、DRL、RDL、RLD。实际中只有前三种遍历算法,特点是:

  1. L在R之前
  2. 根据D的前、中、后三种位置分为三种

遍历可以借助递归调用实现,方法简单便捷,本文不再介绍。
本文利用栈实现遍历,栈的特点:先进后出。利用栈主要是将树的关联性存储在栈中,通过栈可以返回到正确的结点位置处,实现对树的整体遍历。

遍历示意图-必看

在这里插入图片描述图中虚线箭头所示是这三种遍历的递归执行过程,图中三角形、圆形、方形分别是先序、中序、后序在遍历过程中依次访问结点输出的信息。
先序:-*abc
中序:a*b-c
后序:ab*c-

先序遍历:先打印父结点,然后遍历左结点,再遍历右结点。
中序遍历:先打印最左的结点,然后打印父节点,再遍历右结点。
后序遍历:先打印最左结点,再打印兄弟右结点,最后打印父结点。

先序遍历

先序遍历:先打印父结点,然后遍历左结点,再遍历右结点。
思路:

  1. 获得栈顶结点,就打印数值,实际就是再打印父节点。然后先入栈右结点,再入栈左结点。

这样深度越低的右结点就越在栈底。我们保留了树的关联信息。
深度:树结构中的层数,根是第一层,深度为1,以此类推)

/BitTree:结点指针
void preOrderTraverse(BitTree Tree){
	stack<BitTree> st;
	st.push(Tree);
	BitTree p ;
	while(!st.empty()){
	   //弹出栈顶
		p = st.top();st.pop();
		cout << p->data;
		//先入栈右结点
		if(p->right){
			st.push(p->right);
		}
		//先入栈左结点
		if(p->left){
			st.push(p->left);
		}
	}
}

中序遍历

中序遍历:先打印最左的结点,然后打印父节点,再遍历右结点。
思路:

  1. 遍历到最左子树
  2. 某结点若左子树为空,则退栈,输出此节点的数值
  3. 某结点若右子树为空,表明当前层遍历完毕(当前层指的是父结点,左子树,右子树),则继续退栈
  4. 隐晦信息:能访问右子树则左子树和父节点一定已经访问结束。故第三步成立。
void InOrderTraverse(BitTree Tree){
	stack<BitTree> st;
	BitTree p = Tree,p1;
	while(p || !st.empty()){
		if (p){
			st.push(p);
			p = p->left;
		}
		else{
			p1 = st.top();st.pop();
			cout << p1->data;
			p = p1->right;
		}
	}
}

后序遍历

后序遍历:先打印最左结点,再打印兄弟右结点,最后打印父结点。
后序遍历可以只用一个栈实现,但需要一个参考量flag,flag指向最近访问的结点:
思路:

  1. 若是左右子树都未访问,才入栈左子树。
  2. 若是左子树已访问,右子树未访问,才进入入栈右子树。
  3. 不满足上述信息代表左右子树都已访问,则出栈打印当前结点信息。

隐晦信息

  1. 首先能访问到最左,同中序遍历。
  2. 左右都已访问,才访问父结点。
void InOrderTraverse(BitTree Tree){
	stack<BitTree> st;
	BitTree p;
	st.push(Tree);
	while(!st.empty()){
		p = st.top();
		if (p->left and p->left != flag and p->right != right){
			st.push(p->left)
		}else if(p->right and p->right != flag ){
			st.push(p->left)
		}else{
			p = st.top();st.pop();
		    cout << p.data;
		    flag = h;
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值