二叉树的遍历,深度求解以及竖向打印详析

二叉树是每个节点最多有两个子树的有序树。二叉树常被用于实现二叉查找树二叉堆。值得注意的是,二叉树不是树的特殊情形。在图论中,二叉树是一个连通的无环图,并且每一个顶点的度不大于2。有根二叉树还要满足根结点的度不大于2。有了根结点后,每个顶点定义了唯一的根结点,和最多2个子结点。然而,没有足够的信息来区分左结点和右结点。二叉树详细请看本文:二叉树

所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问。访问结点所做的操作依赖于具体的应用问 题。 遍历是二叉树上最重要的运算之一,是二叉树上进行其它运算之基础。

代码如下:

#include<iostream>
#include<cstdlib>
using namespace std;
typedef char ElemType;
typedef struct Node
{
	ElemType data;
	struct Node* LChild;
	struct Node* RChild;
}BiTNode,*BiTree;
int LeafCount;
int Depth;

void Visit(ElemType T)//用于遍历的输出
{
	cout<<T;
}

//1.建立二叉树
void CreateBiTree(BiTree *bt)
{
	char ch;
	ch = getchar();
	if(ch=='.') *bt=NULL;
	else
	{
		*bt=(BiTree)malloc(sizeof(BiTNode)); //生成一个新结点
		(*bt)->data=ch;
		CreateBiTree(&((*bt)->LChild)); //生成左子树
		CreateBiTree(&((*bt)->RChild)); //生成右子树
	}
}

//2.二叉树遍历

void  PreOrder(BiTree root)
/*先序遍历二叉树, root为指向二叉树(或某一子树)根结点的指针*/
{
	if (root!=NULL)
	{
		Visit(root ->data);  /*访问根结点*/
		PreOrder(root ->LChild);  /*先序遍历左子树*/
		PreOrder(root ->RChild);  /*先序遍历右子树*/
	}
	else
		cout<<".";
}
void  InOrder(BiTree root)
/*中序遍历二叉树, root为指向二叉树(或某一子树)根结点的指针*/
{
	if (root!=NULL)
	{
		InOrder(root ->LChild);   /*中序遍历左子树*/
		Visit(root ->data);        /*访问根结点*/
		InOrder(root ->RChild);   /*中序遍历右子树*/
	}
	else
		cout<<".";
}
void  PostOrder(BiTree root)
/* 后序遍历二叉树,root为指向二叉树(或某一子树)根结点的指针*/
{
	if(root!=NULL)
	{
		PostOrder(root ->LChild); /*后序遍历左子树*/
		PostOrder(root ->RChild); /*后序遍历右子树*/
		Visit(root ->data);       /*访问根结点*/
	}
	else
		cout<<".";
}

//3.输出二叉树上的“叶子”节点(三种方法,只写了先序,中后请参考前面的2.二叉树遍历)

void  leafPreOrder(BiTree root)
/*先序遍历二叉树, root为指向二叉树根结点的指针*/
{
	if (root!=NULL)
	{
		if (root ->LChild==NULL && root ->RChild==NULL)
			Visit(root->data);  /*输出叶子结点*/
		PreOrder(root ->LChild);  /*先序遍历左子树*/
		PreOrder(root ->RChild);  /*先序遍历右子树*/
	}
}

//4.统计叶子节点数目(两个方法)

/* LeafCount保存叶子结点的数目的全局变量,调用之前初始化值为0 */
void leaf_a(BiTree root)//统计叶子节点数目法1
{
	if(root!=NULL)
	{
		leaf_a(root->LChild);
		leaf_a(root->RChild);
		if (root ->LChild==NULL && root ->RChild==NULL)
			LeafCount++;
	}
}

int leaf_b(BiTree root)//统计叶子节点数目法2
{
	int LeafCount2;
	if(root==NULL)
		LeafCount2 =0;
	else
		if((root->LChild==NULL)&&(root->RChild==NULL))
			LeafCount2 =1;
		else
			LeafCount2 =leaf_b(root->LChild)+leaf_b(root->RChild);
		/* 叶子数为左右子树的叶子数目之和 */
		return LeafCount2;
}

//6.后序遍历求二叉树的高度递归算法

int PostTreeDepth(BiTree bt)
{
	int hl,hr,max;
	if(bt!=NULL)
	{
		hl=PostTreeDepth(bt->LChild);  /* 求左子树的深度 */
		hr=PostTreeDepth(bt->RChild);  /* 求右子树的深度 */
		max=hl>hr?hl:hr;              /* 得到左、右子树深度较大者*/
		return(max+1);               /* 返回树的深度 */
	}
	else return(0);             /* 如果是空树,则返回0 */
}

//6.前序遍历求二叉树的高度递归算法

void PreTreeDepth(BiTree bt, int h)
/* 前序遍历求二叉树bt高度的递归算法,h为bt指向结点所在层次,初值为1*/
/*depth为当前求得的最大层次,为全局变量,调用前初值为0 */
{
	if(bt!=NULL)
	{
		if(h>Depth)
			Depth = h;     /*如果该结点层次值大于depth,更新depth的值*/
		PreTreeDepth(bt->LChild, h+1);  /* 遍历左子树 */
		PreTreeDepth(bt->RChild, h+1);  /* 遍历右子树 */
	}
}

//7.“竖向”打印二叉树

void PrintTree(BiTree bt,int nLayer)  /* 按竖向树状打印的二叉树 */
{
	if(bt == NULL) return;
	PrintTree(bt->RChild,nLayer+1);
	for(int i=0;i<nLayer;i++)
		printf("  ");
	printf("%c\n",bt->data);
	PrintTree(bt->LChild,nLayer+1);
}

int main()
{
	LeafCount =0;Depth=0;
	BiTree T=NULL;
	cout<<"请以先序输出的形式输入二叉树构造二叉链表:"<<endl;
	CreateBiTree(&T);
	cout<<"先序遍历二叉树为:"<<endl;
	PreOrder(T);
	cout<<endl<<"中序遍历二叉树为:"<<endl;
	InOrder(T);
	cout<<endl<<"后序遍历二叉树为:"<<endl;
	PostOrder(T);
	cout<<endl<<"先序输出二叉树叶子节点为:"<<endl;
	leafPreOrder(T);
		cout<<endl<<"叶子节点数目为:"<<endl;
	leaf_a(T);
	cout<<endl<<"方法一显示共有"<<LeafCount<<"个叶子节点"<<endl;

	cout<<endl<<"方法二显示共有"<<leaf_b(T)<<"个叶子节点"<<endl;

	cout<<endl<<"后序遍历求二叉树的高度为"<<PostTreeDepth(T)<<endl;
	PreTreeDepth(T,1);
	cout<<endl<<"前序遍历求二叉树的高度为"<<Depth<<endl;

	cout<<endl<<"竖状打印二叉树为:"<<endl;
	PrintTree(T,1);
	return 0;
}

附带二叉树遍历的非递归算法:

/* 中后非递归遍历二叉树,作为遍历方法的参考*/

//8.中序遍历二叉树非递归算法(三个)

/*算法a*/
void inorder(BiTree root);
{
	int top=0; p=bt;
L1: if (p!=NULL)       /* 遍历左子树 */
	{
		top=top+2;
		if(top>m) return;       /*栈满溢出处理*/
		s[top-1]=p;            /* 本层参数进栈 */
		s[top]=L2;             /* 返回地址进栈 */
		p=p->LChild;           /* 给下层参数赋值 */
		goto L1;               /* 转向开始 */
L2:  Visit(p->data);     /* 访问根 */
     top=top+2;
     if(top>m) return;       /*栈满溢出处理*/;
     s[top-1]=p;            /* 遍历右子树 */
     s[top]=L3;
     p=p->RChild;
     goto L1;
	}
L3: if(top!=0)
	{
		addr=s[top];
		p=s[top-1];            /* 取出返回地址 */
		top=top-2;             /* 退出本层参数 */
		goto addr;
	}
}

/*算法b*/
void inorder(BiTree root)   /* 中序遍历二叉树,root为二叉树的根结点 */
{
	int top=0;
	BiTree p;
	BiTree s[Stack_Size];
	int m;
	m = Stack_Size-1;
	p = root;
	do
	{
		while(p!=NULL)
		{
			if (top>m) return;
			top=top+1;
			s[top]=p;
			p=p->LChild;
		};  /* 遍历左子树 */
		if(top!=0)
		{
			p=s[top];
			top=top-1;
			Visit(p->data);  /* 访问根结点 */
			p=p->RChild;  /* 遍历右子树 */
		}
	}
	while(p!=NULL || top!=0);
}

/*算法c*/
void  InOrder(BiTree root) /* 中序遍历二叉树的非递归算法 */
{
	SeqStack S;
	BiTree p;
	InitStack (&S);
	p=root;
	while(p!=NULL || !IsEmpty(&S))
	{
		if (p!=NULL)  /* 根指针进栈,遍历左子树 */
		{
			Push(&S,p);
			p=p->LChild;
		}
		else
		{  /*根指针退栈,访问根结点,遍历右子树*/
			Pop(&S,&p);
			Visit(p->data);
			p=p->RChild;
		}
	}
}

//9.后序遍历二叉树的非递归算法

void PostOrder(BiTree root)
{
	BiTNode *p,*q;
	BiTNode **s;
	int top=0;
	q=NULL;
	p=root;
	s=(BiTNode**)malloc(sizeof(BiTNode*)*NUM);
	/* NUM为预定义的常数 */
	while(p!=NULL || top!=0)
	{
		while(p!=NULL)
		{
			top++;
			s[top]=p;
			p=p->LChild;
		}  /*遍历左子树*/
		if(top>0)
		{
			p=s[top];
			if((p->RChild==NULL) ||(p->RChild==q))	/* 无右孩子,或右孩子已遍历过 */
			{
				visit(p->data);        /* 访问根结点*/
				q=p;            	/* 保存到q,为下一次已处理结点前驱 */
				top--;
				p=NULL;
			}
			else
				p=p->RChild;
		}
	}
	free(s);
}
时间: 2025-01-21 21:24:47

二叉树的遍历,深度求解以及竖向打印详析的相关文章

二叉树的模板 先序建立 二叉树的遍历 深度

关于二叉树,基本操作都是在递归的基础上完成的,二叉树的层次遍历是队列实现.具体解释看代码 #include<iostream> #include<stack> #include<queue> #include<stdio.h> #include<stdlib.h> using namespace std; //二叉树结点 typedef struct BiTNode { //数据 char data; //左右孩子指针 struct BiTNod

Java实现二叉树地遍历、求深度和叶子结点的个数

一.分析 二叉树是n个结点所构成的集合,它或为空树,或为非空树.对于非空树,它有且仅有一个根结点,且除根结点以外的其余结点分为两个互不相交的子集,分别称为左子树和右子树,它们本身又都是二叉树. 显而易见,二叉树具有递归的性质,因此表示二叉树的结点至少要包含3个域:数据域.左指针.右指针.在Java中,我们可以将二叉树的结点视为一个类,其中含有左子树地址.右子树地址和数据三个属性,每个结点即使类的实例化对象.因为二叉树的递归性质,所以我们可以通过递归来实现二叉树地求深度.求叶子结点的个数.先序.中

数据结构第三部分:树与树的表示、二叉树及其遍历、二叉搜索树、平衡二叉树、堆、哈夫曼树、集合及其运算

参考:浙大数据结构(陈越.何钦铭)课件 1.树与树的表示 什么是树? 客观世界中许多事物存在层次关系 人类社会家谱 社会组织结构 图书信息管理 分层次组织在管理上具有更高的效率! 数据管理的基本操作之一:查找(根据某个给定关键字K,从集合R 中找出关键字与K 相同的记录).一个自然的问题就是,如何实现有效率的查找? 静态查找:集合中记录是固定的,没有插入和删除操作,只有查找 动态查找:集合中记录是动态变化的,除查找,还可能发生插入和删除 静态查找——方法一:顺序查找(时间复杂度O(n)) int

Python与数据结构[3] -&gt; 树/Tree[0] -&gt; 二叉树及遍历二叉树的 Python 实现

二叉树 / Binary Tree 二叉树是树结构的一种,但二叉树的每一个节点都最多只能有两个子节点. Binary Tree: 00 |_____ | | 00 00 |__ |__ | | | | 00 00 00 00 对于二叉树的遍历,主要有以下三种基本遍历方式: 先序遍历:先显示节点值,再显示左子树和右子树 中序遍历:先显示左子树,再显示节点值和右子树 后序遍历:先显示左子树和右子树,再显示节点值 下面将用代码构建一个二叉树,并实现三种遍历方式, 完整代码 1 class TreeNo

树、二叉树、遍历二叉树的总结

首先介绍树: 如上图所示就是一棵树,先介绍树的几个关键名词: 节点:A.B.C.D等都叫节点 节点的度:节点有几个分支,就叫节点的度,比如节点B有2个分支,那B的度为2 终端节点(叶子):没有分支的节点,如E.F.G.H 非终端节点:有分支的节点,如A.B.D.C 节点的层次:自上而下排列层次,A为1层,B为2层,D为3层 树的度:哪个节点的度最大,这个最大的度就是树的度,如图树的度为2 树的深度:简而言之,就是树有几层,如图的树的深度为4 我们接触最多的树是二叉树 二叉树:在计算机科学中,二叉

java生成二叉树和遍历

在java中实现二叉树和链表的方法都是在类中定义该类的对象引用 比如 class Tree { int data; Tree left; Tree right; } 这样的话当我们new一个Tree对象的时候,该对象就拥有了left和right两个对象,这样就起到了连接的 作用,在链表中就是连接了下一个,在树中就相当于边,这样就起到一个接一个的效果.总之,就是吧对象连接起来了. 下面是完整代码 package code; public class TwoTree { public static

Java数据结构-二叉树及其遍历

二叉树的定义:n(n>=0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根结点和两棵互相不相交的.分别称为根结点的左子树和右子树的二叉树组成. 二叉树的特点: 0<=度<=2: 左右子树是有顺序的,不能颠倒: 不论有几棵子树,也要区分它是左子树还是右子树. 二叉树的五种基本形态: 空二叉树: 只有一个根结点: 根结点只有左子树: 根结点只有右子树: 根结点既有左子树又有右子树. 举例3个结点的二叉树的形态有: 下面说一些特殊的二叉树. 斜树:所有的结点都只有左子树的二叉

求二叉树的最小深度

思路:用递归的方法求解. 输入:二叉树的根节点: 输出:二叉树的最小深度. 最小深度的定义:从根节点到叶子节点的最短路径上的节点数. 算法如下: 将二叉树分为这么几种情况: 传入的根节点为空,返回NULL: 传入根节点不为空,左子树为空,右子树为空,返回最小深度1: 传入根节点不为空,左子树为空,右子树不为空,返回右子树的最小深度+1: 传入根节点不为空,左子树不为空,右子树为空,返回左子树的最小深度+1: 传入根节点不为空,左右子树都不为空,则返回左右子树中最小深度的较小值+1. 代码如下:

【转】算法之二叉树各种遍历

http://blog.csdn.net/sjf0115/article/details/8645991 树形结构是一类重要的非线性数据结构,其中以树和二叉树最为常用. 二叉树是每个结点最多有两个子树的有序树.通常子树的根被称作“左子树”(left subtree)和“右子树”(right subtree).二叉树常被用作二叉查找树和二叉堆或是二叉排序树.二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒.二叉树的第i层至多有2的 i -1次方个结点: