二叉树的前序遍历-中序遍历-后序遍历

本文详细介绍了二叉树的基本概念及其四种遍历方法:层次、前序、中序和后序遍历,并通过示例解释了每种遍历方式的特点及实现过程。

1、遍历是对树的一种最基本的运算,所谓遍历二叉树,就是按一定的规则和顺序走遍二叉树的所有结点,使每一个结点都被访问一次,而且只被访问一次。由于二叉树是非线性结构,因此,树的遍历实质上是将二叉树的各个结点转换成为一个线性序列来表示。二叉树的遍历分为:层次遍历、前序遍历、中序遍历、后序遍历。

二叉树的深度为k,则该二叉树最多有2^k - 1个结点。

层次遍历:这个太简单,,从左到右,从上到下

前序遍历:根节点、左子树、右子树

中序遍历:左子树、根节点、右子树

后序遍历:左子树、右子树、根节点

先来看一个简单示例:


该二叉树的深度为:4。

层次遍历结果:1  2  3  4  5  6  7  8

前序遍历结果:1  2  4  5  7  8  3  6

中序遍历结果:4  2  7  5  8  1  3  6

后序遍历结果:4  7  8  5  2  6  3  1

遍历过程:以中序遍历为例,首先访问左子树(左边叶子节点 )4,即将 1 2 4 依次压栈,直到左子树为空,将4输出(出栈)。然后输出根节点2(出栈),再访问右节点5,5的左子树不为空,压栈;然后访问7,7直接输出,再将5出栈,再访问右节点8, 8的左子树为空直接输出。这样进行依次的输出顺序就是:4 2 7 5 8。

注意:层次遍历需要用队列来实现

2、代码测试

注意:程序主要是对于二叉树结点的存储结构定义和二叉树的创建,最开始自己把BitTree*理解不了。然后翻了下typedef定义的知识,才明白其实就等于 struct BitNode*,一个结构体指针而已,只不过是类型别名。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//***************仅仅做测试,对比struct 和 typedef struct**************
struct node{
	int data;
	struct node *lchild;
	struct node *rchild;
}mynode,*mylistnode;//这里定义的是struct node 对象和 struct node* 对象

void testNode(){

	mynode.data = 10;
	mylistnode = (struct node*)malloc(sizeof(struct node) * 5);
	mylistnode[0].data = 100;
	mylistnode[1].data = 1000;
	printf("test:%d %d %d \n", mynode.data, mylistnode[0].data, mylistnode[1].data);//10 100 1000
}
//******************************************************************


typedef char ElemType;
typedef struct BitNode{
	ElemType data;
	struct BitNode* lchild;//左结点
	struct BitNode* rchild;//右结点
}BitNode, *BitTree;
//这里定义的是类型别名,*修饰类型,而不是对象,即定义了类型别名,等同于struct BitNode*
//等同于typedef BitNode*  BitTree;

void createTree(BitTree &T){
	ElemType indata;
	scanf("%c", &indata);
	if (indata == '#'){
		T = NULL;
	}else{
		T = (BitTree)malloc(sizeof(BitNode));
		if (NULL == T){
			printf("locate memery error.\n");
			return;
		}
		T->data = indata;
		createTree(T->lchild);
		createTree(T->rchild);
	}
}

//先续遍历二叉树
void preOrderTraverse(BitTree T){
	if (T){
		printf("%c ",T->data);
		preOrderTraverse(T->lchild);
		preOrderTraverse(T->rchild);
	}
}
//中序遍历
void midOrderTraverse(BitTree T){
	if (T){
		midOrderTraverse(T->lchild);
		printf("%c ", T->data);
		midOrderTraverse(T->rchild);
	}
}
//后序遍历
void postOrderTraverse(BitTree T){
	if (T){
		postOrderTraverse(T->lchild);
		postOrderTraverse(T->rchild);
		printf("%c ", T->data);
	}
}
/******
				A
           B            C
		D           E      F
	  G  H            I  

	  输入格式为: ABDG##H###CE#I##F##   总数量为2^k - 1个节点  15个
******/
int main(){

	testNode();
	BitTree one;
	printf("按先序序列输入结点序列,输入的是扩展二叉树。'#'代表其子节点空\n");
	createTree(one);
	printf("\n前序遍历:\n");
	preOrderTraverse(one);
	printf("\n中序遍历:\n");
	midOrderTraverse(one);
	printf("\n后序遍历:\n");
	postOrderTraverse(one);
	printf("\n");
	return 0;
}


测试2:


补充:求取二叉树的深度

//求取二叉树的深度:根节点开始为第一层
int getDeep(BitTree T){
	int left, right;
	int h = 0;
	if (T){
		left = getDeep(T->lchild);
		right = getDeep(T->rchild);
		h = left > right ? left : right;
		h = h + 1;
	}
	return h;
}




通过二叉树前序遍历和中序遍历结果求后序遍历结果,可利用前序遍历和中序遍历的特点,结合递归的方法来实现。 前序遍历的顺序是先访问根节点,然后递归遍历左子树,最后递归遍历右子树;中序遍历的顺序是先递归遍历左子树,然后访问根节点,最后递归遍历右子树。因此,前序遍历的第一个元素就是二叉树的根节点,在中序遍历中找到该根节点的位置,其左边的元素就是左子树的中序遍历结果,右边的元素就是右子树的中序遍历结果。根据左子树和右子树的节点数量,又可以从前序遍历中划分出左子树和右子树的前序遍历结果。然后对左子树和右子树分别递归地进行上述操作,直到子树为空。 以下是实现该功能的 Java 代码示例: ```java class Solution { public void postOrder(int[] pre, int[] mid, int preStart, int preEnd, int midStart, int midEnd) { if (preStart > preEnd || midStart > midEnd) { return; } // 前序遍历的第一个元素是根节点 int rootVal = pre[preStart]; // 在中序遍历中找到根节点的位置 int rootIndexInMid = midStart; while (mid[rootIndexInMid] != rootVal) { rootIndexInMid++; } // 计算左子树的节点数量 int leftSubtreeSize = rootIndexInMid - midStart; // 递归遍历左子树 postOrder(pre, mid, preStart + 1, preStart + leftSubtreeSize, midStart, rootIndexInMid - 1); // 递归遍历右子树 postOrder(pre, mid, preStart + leftSubtreeSize + 1, preEnd, rootIndexInMid + 1, midEnd); // 输出根节点 System.out.print(rootVal + " "); } public static void main(String[] args) { Solution solution = new Solution(); int[] pre = {1, 2, 4, 5, 3, 6, 7}; int[] mid = {4, 2, 5, 1, 6, 3, 7}; solution.postOrder(pre, mid, 0, pre.length - 1, 0, mid.length - 1); } } ``` 上述代码中,`postOrder` 方法接收前序遍历数组 `pre`、中序遍历数组 `mid`,以及前序遍历和中序遍历的起始和结束索引。在方法内部,首先找到根节点,然后在中序遍历中确定根节点的位置,计算左子树的节点数量,接着递归地对左子树和右子树进行处理,最后输出根节点的值,从而实现后序遍历的结果输出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值