二叉树访问基本操作

重温数据结构。整理一些代码。
这一篇包括二叉树的先序建立三种顺序递归访问三种顺序非递归访问,力求精简。
二叉树的默认是如下形状:


#define OK true
#define ERROR false
#include<stdio.h>
#include<malloc.h>
#include<stack>	//由于二叉树的非递归访问等需要一个栈来记录节点顺序,这里使用stack简单好理解
using namespace std;

typedef struct BtNode{
	char data;	//二叉树的节点元素
	struct BtNode *lchild,*rchild;	//二叉节点
}BtNode;

BtNode *CTBT_pre(BtNode *T,int &n,char list[]);//先序递归建立二叉树

//递归方式先序,中序,后序访问二叉树
void preOrder(BtNode *T);
void inOrder(BtNode *T);
void laOrder(BtNode *T);
//非递归访问声明
void preOrder_st(BtNode *T);
void inOrder_st(BtNode *T);
void laOrder_st(BtNode *T);


void main()
{
	BtNode *Tree;
	Tree=NULL; //初始化指针

	//以下建立二叉树
	char list[20]="abc de  f   gh   ";//字符串是空表示节点到头。
	int n=0;	//利用字符串建立二叉树时需要辅助的参数
	Tree=CTBT_pre(Tree,n,list);//利用Tree来生成二叉树
	//返回Tree二叉树

	laOrder_st(Tree);
}
//结点的访问函数
bool visit(BtNode *p)
{
	if(p){
		printf("%c ",p->data);
		return OK;
	}
	else
		return ERROR;
}
//先序建立二叉树(递归)
BtNode *CTBT_pre(BtNode *T,int &n,char list[]){
	//按照先序递归生成二叉树
	if(list[n]==' '){
		n++;
		return NULL;//如果输入出现了空,表明到了叶子结点
	}
	else{
		if(!(T=(BtNode *)malloc(sizeof(BtNode)))) return false;//这里要验证内存是否分配成功;
		T->data=list[n++];
		T->lchild=CTBT_pre(T->lchild,n,list);
		T->rchild=CTBT_pre(T->rchild,n,list);
		return T;
	}
}
//三种方式的递归访问二叉树,简单直接暴力= =
void preOrder(BtNode *T)
{//前序访问
	if(T){	
		visit(T);
		preOrder(T->lchild);
		preOrder(T->rchild);
	}
}
void inOrder(BtNode *T)
{//中序访问
	if(T){	
		inOrder(T->lchild);
		visit(T);
		inOrder(T->rchild);
	}
}
void laOrder(BtNode *T)
{//后序访问
	if(T){	
		laOrder(T->lchild);
		laOrder(T->rchild);
		visit(T);
	}
}
//三种方式的非递归访问二叉树
void preOrder_st(BtNode *T)//非递归先序
{
	stack <BtNode*> Stack;
	if(!T) return;
	while(T || !Stack.empty())//注意理解这个进行循环的入口
	{
		while(T){
			Stack.push(T);//入栈后,我们下次用的不是他,而是他的右孩子。
			visit(T);
			T=T->lchild;
		}
		T=Stack.top();//左边走到头,下一个应该是双亲的右孩子,好,把他取出来。
		T=T->rchild;
		Stack.pop();
	}
}
void inOrder_st(BtNode *T)//非递归中序
{
	stack <BtNode*> Stack;
	if(!T) return;
	while(T || !Stack.empty())//某种意义上,先序和中序的思路是一致的,只是visit出现的位置。
	{
		while(T){
			Stack.push(T);
			T=T->lchild;
		}
		T=Stack.top();
		visit(T);
		Stack.pop();
		T=T->rchild;
	}
}
void laOrder_st(BtNode *T)//非递归后序遍历
{
	stack <BtNode*> Stack;
	bool tag[20];//后序遍历的麻烦在于,每当访问栈里的节点时需要分清楚是从左孩子还是右孩子回来
		//所以这里使用一个对应等长的标记,左孩子回来即true,右孩子回来的则是false
	if(!T) return;
	while(T || !Stack.empty())
	{
		while(T){
			Stack.push(T);
			tag[Stack.size()]=true;
			T=T->lchild;
		}
		while(tag[Stack.size()]==false && !Stack.empty()){
			visit(Stack.top());
			Stack.pop();
			//T=Stack.top();
		}

		if(!Stack.empty()){//来到这里的时候,左边已经访问完了
			tag[Stack.size()]=false;//所以下次回来,对于这个节点来说就是两边都访问了false
			T=Stack.top()->rchild;
		}
	}
}





转载于:https://my.oschina.net/o0Kira0o/blog/206437

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值