二叉树的介绍以及二叉树的遍历

二叉树结构一直以来都是数据结构课程中的重点和难点。不论是找工作的笔试面试,还是考研的专业课,二叉树所占的比例都是很大的,而在原始的二叉树的基础上,有不断演化出了很多其他基于二叉树的结构,例如哈夫曼树、红黑树,还有线索二叉树、B+树等等

首先来介绍一下树的基本概念

树的定义
树是一种数据结构,它是由n(n>=1)个有限结点组成一个具有层次关系的集合。
树具有的特点有:

(1)每个结点有零个或多个子结点

(2)没有父节点的结点称为根节点

(3)每一个非根结点有且只有一个父节点

(4)除了根结点外,每个子结点可以分为多个不相交的子树。

树的一些专业术语

名字含义
结点的度结点拥有的子树的数目
叶子结点度为0的结点
分支结点度不为0的结点
树的度树中结点的最大的度
层次根结点的层次为1,其余结点的层次等于该结点的双亲结点的层次加1
树的高度树中结点的最大层次
森林0个或多个不相交的树组成。对森林加上一个根,森林即成为树;删去根,树即成为森林

了解完树之后,来了解一下二叉树
二叉树

定义:二叉树是每个结点最多有两个子树的树结构在这里插入图片描述

可以有五种形态:可以为空,可以有根(没有左右子树),有根(有左子树),有根(右子树),有根(同时有左右子树)。

二叉树的一些性质和常见公式

性质1:二叉树第i层上的结点数目最多为2i-1(i>=1)

性质2:深度为k的二叉树至多有2k-1个结点(k>=1)

性质3:包含n个结点的二叉树的高度至少为(log2n)+1

性质4:在任意一棵二叉树中,若终端结点的个数为n0,度为2的结点数为n2,则n0=n2+1

所以我们根据性质4可知
在任意一棵二叉树中,这些节点的数量,之间存在如下关系
1.n2 = n0 - 1:即度为2的节点总比度为0的节点少1个,也就是说,在任意二叉树中,同时具有左右孩子的节点,总比叶子结点的数量少一个
2.从上面的公式我们能够推导出来:n总 = n0 + n1 + n2 = 2n0 + n1 - 1 = n1 + 2n2 + 1,且n1 = n总 - n0 - n2 = n总 - 2n0 + 1 = n总 - 2n2 - 1
所以,只要我们知道一个二叉树中总的节点个数以及度为0或者度为2的节点数量,就能够推导出其他度的节点的数量

常见的几种二叉树的类型

满二叉树、完全二叉树和二叉查找树

1、满二叉树

定义:高度为h,并且由2h-1个结点组成的二叉树,称为满二叉树
也就是说除了最后一层,每个结点都有左右子节点
在这里插入图片描述

完全二叉树

定义:一棵二叉树中,只有最下面两层结点的度可以小于2,并且最下层的叶结点集中在靠左的若干位置上,这样的二叉树称为完全二叉树。

特点:叶子结点只能出现在最下层和次下层,且最下层的叶子结点集中在树的左部。显然,一棵满二叉树必定是一棵完全二叉树,而完全二叉树未必是满二叉树。
在这里插入图片描述

二叉查找树

定义:二叉查找树又被称为二叉搜索树。设x为二叉查找树中的一个结点,x结点包含关键字key,结点x的key值计为key[x]。如果y是x的左子树中的一个结点,则key[y]<=key[x];如果y是x的右子树的一个结点,则key[y]>=key[x]
在这里插入图片描述
接下来我们来讲一下二叉树的遍历

广度优先遍历

对一棵二叉树进行广度优先遍历,就是对一棵二叉树中所有的节点,按照层次从上到下、每一层中节点从左到右的顺序,将二叉树中的所有节点进行遍历的操作
广度优先遍历方式只有一种,那就是程序遍历,而二叉树的程序遍历操作,需要依赖于队列结构
所以接下来的代码是依赖队列来实现的遍历

/**
 * 广度优先breadth-first traversal(BFS)
 * 
 * @author 80769
 *
 */
public class Bfs {
	public void bfs(Node root) {
	public void print(TreeNode node) {
		LinkedList<TreeNode> list = new LinkedList<TreeNode>();
		// 首先将整个二叉树的根节点入队列
		list.offer(node);
		while (!list.isEmpty()) {// 如果队列中不再具有节点,说明整个二叉树遍历完成
			// 首先将队列头节点出队列
			TreeNode node1 = list.pop();
			if (node1 != null) {
				System.out.print(node1.data);
				// 如果队列头结点左孩子不是空,则将左孩子入队列
				if (node1.left != null) {
					list.offer(node1.left);
				}
				// 如果队列头节点右孩子不是空,则将右孩子入队列
				if (node.right != null) {
					list.offer(node1.right);
				}
			}

		}
	}

}

深度优先遍历

深度优先遍历是二叉树遍历方式中比较重点的一种遍历方式,可以分为先序遍历、中序遍历和后序遍历3种遍历序列

(1)先序:也就是根左右

/**
 * 先序PreorderTraversal 用递归的方式
 * 
 * @author xhh
 *
 */
public class PreTraversal {
	public void preTraversal(Node root) {
		// 首先输出根节点
		System.out.println(root.data);
		// 如果左孩子不为空,则先序遍历左子树
		if (root.leftNode != null) {
			preTraversal(root.leftNode);
		}
		// 如果右孩子不为空,则先序遍历右子树
		if (root.rightNode != null) {
			preTraversal(root.rightNode);
		}
	}
}

(2) 中序(左根右)

/**
 * 中序InorderTraversal 用递归的方式
 * 
 * @author xhh
 *
 */
public class InTraversal {
	public void inTraversal(Node root) {
		// 如果左孩子不为空,则中序遍历左子树
		if (root.leftNode != null) {
			inTraversal(root.leftNode);
		}
		// 访问根节点
		System.out.println(root.data);
		// 如果右孩子不为空,则中序遍历右子树
		if (root.rightNode != null) {
			inTraversal(root.rightNode);
		}
	}
}

(3)后序(左右根)

/**
 * 后序PostorderTraversal 用递归的方式
 * 
 * @author xhh
 *
 */
public class PostTraversal {
	public void postTraversal(Node root) {
		// 如果左孩子不为空,则中序遍历左子树
		if (root.leftNode != null) {
			postTraversal(root.leftNode);
		}
		// 如果右孩子不为空,则中序遍历右子树
		if (root.rightNode != null) {
			postTraversal(root.rightNode);
		}
		// 访问根节点
		System.out.println(root.data);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值