数据结构——二叉树

本文介绍了二叉树的基本概念,包括斜二叉树、满二叉树和完全二叉树等特殊类型,并详细阐述了二叉树的五个重要性质。此外,还讲解了前序、中序和后序遍历的方法,以及如何在二叉树中查询特定值的路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 二叉树概念


二叉树(Binary Tree)是n(n>=0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者有一个根节点和两颗互不相交的,方便称为根节点的左子树和右子树的二叉树组成

一般的树都可以使用孩子兄弟表示法转换为二叉树表示

(二)特殊的二叉树

1.斜二叉树

或者

所有的结点都只有左子树的二叉树叫做左斜树
所有的结点都只有右子树的二叉树叫做右斜树
相当于链表,所以线性结构可以理解为是树的一种极其特殊的表现形式

2.满二叉树(完美二叉树)

所有分支结点都存在左子树和右子树。
所有叶子结点都在同一层

3.完全二叉树

 

对树按照上->下,左->右,编号为i的与满二叉树中为i的位置相同

(三)二叉树的几个重要性质

性质一:第i层最大结点数位2^(i-1)个,(i>=1)

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

性质三:叶结点n0与度为2的结点n2的个数关系n0=n2+1

设n1为度为1的非叶结点数
那么按照边来计算
n0+n1+n2-1    每个结点向上都有一条边指向双亲结点,除了根结点
n0*0+n1*1+n2*2    度为二,向下有2条边,度为1向下有一条边,度为0的叶子节点无下边。
两者边相等,所以得出:n0=n2+1

性质四:具有n个结点的完全二叉树的深度为[log2n]+1

性质五:对一棵有n个结点的完全二叉树,从第一层到最大层,对任一结点i(1=<i<=n)有:

1.非根节点的父节点序号是[i/2]
2.结点(序号i)的左孩子为2i,若2i>n没有左孩子
2.结点(序号i)的右孩子为2i+1,若2i+1>n没有右孩子

 

2 遍历方式

前序遍历:根结点 ---> 左子树 ---> 右子树

中序遍历:左子树---> 根结点 ---> 右子树

后序遍历:左子树 ---> 右子树 ---> 根结点

 

树的结构定义

package org.buptdavid.datastructure.tree;

/**
 * 树的节点
 * @author 
 *
 */
public class TreeNode<T> {
	T data;
	TreeNode<T> left;
	TreeNode<T> right;
	
	public TreeNode(T data){
		this.data = data;
	}

}

创建一个1-10的树,并查询具体一个value所经过的树路径

public class TreeSearchTest {
	
	private static TreeNode<Integer> root;
	
	@BeforeClass
	public static void beforeClass(){
		TreeNode<Integer> node1 = new TreeNode<Integer>(1);
		TreeNode<Integer> node2 = new TreeNode<Integer>(2);
		TreeNode<Integer> node3 = new TreeNode<Integer>(3);
		TreeNode<Integer> node4 = new TreeNode<Integer>(4);
		TreeNode<Integer> node5 = new TreeNode<Integer>(5);
		TreeNode<Integer> node6 = new TreeNode<Integer>(6);
		TreeNode<Integer> node7 = new TreeNode<Integer>(7);
		TreeNode<Integer> node8 = new TreeNode<Integer>(8);
		TreeNode<Integer> node9 = new TreeNode<Integer>(9);
		TreeNode<Integer> node10 = new TreeNode<Integer>(10);
		
		node1.left = node2;
		node1.right = node3;
		
		node2.left = node4;
		node2.right = node5;
		
		node3.left = node6;
		node3.right = node7;
		
		node4.left = node8;
		
		node7.right = node9;
		
		node9.left = node10;
		
		root = node1;
	}
	
	/**
	 * 前序遍历测试
	 */
	@Test
	public void preorderTraversalTest(){
		TreeSearch<Integer> treeSearch = new TreeSearch<Integer>();
		
		Integer value = 5;
		String expectedSearchPath = "1->2->4->8->5";
		treeSearch.preorderTraversal(root, value);
		Assert.assertTrue(expectedSearchPath.equals(treeSearch.searchPath.toString()));
		
		treeSearch = new TreeSearch<Integer>();
		
		value = 6;
		expectedSearchPath = "1->2->4->8->5->3->6";
		treeSearch.preorderTraversal(root, value);
		Assert.assertTrue(expectedSearchPath.equals(treeSearch.searchPath.toString()));
	}
	
	/**
	 * 中序遍历测试
	 */
	@Test
	public void inorderTraversalTest(){
		TreeSearch<Integer> treeSearch = new TreeSearch<Integer>();
		
		Integer value = 5;
		String expectedSearchPath = "8->4->2->5";
		treeSearch.inorderTraversal(root, value);
		Assert.assertTrue(expectedSearchPath.equals(treeSearch.searchPath.toString()));
		
		treeSearch = new TreeSearch<Integer>();
		
		value = 6;
		expectedSearchPath = "8->4->2->5->1->6";
		treeSearch.inorderTraversal(root, value);
		Assert.assertTrue(expectedSearchPath.equals(treeSearch.searchPath.toString()));
	}

	/**
	 * 后序遍历测试
	 */
	@Test
	public void postorderTraversalTest(){
		TreeSearch<Integer> treeSearch = new TreeSearch<Integer>();
		
		Integer value = 5;
		String expectedSearchPath = "8->4->5";
		treeSearch.postorderTraversal(root, value);
		Assert.assertTrue(expectedSearchPath.equals(treeSearch.searchPath.toString()));
		
		treeSearch = new TreeSearch<Integer>();
		
		value = 6;
		expectedSearchPath = "8->4->5->2->6";
		treeSearch.postorderTraversal(root, value);
		Assert.assertTrue(expectedSearchPath.equals(treeSearch.searchPath.toString()));
	}
}

具体的路径算法,其实就是一个递归过程

public class TreeSearch<T> {
	StringBuffer searchPath = new StringBuffer();
	private boolean isSearched = false;
	
	/**
	 * 前序遍历root查询item
	 * @param item
	 * @return
	 */
	public void preorderTraversal(TreeNode<T> root, T data){
		if(root == null){
			return;
		}
		
		if(!isSearched){
			if(!searchPath.toString().equals("")){
				searchPath.append("->");
			}
			searchPath.append(root.data);
			if(root.data.equals(data))
				isSearched = true;
		}
		
		if(!isSearched)
		    preorderTraversal(root.left, data);
		if(!isSearched)
		    preorderTraversal(root.right, data);
	}
	
	/**
	 * 中序遍历root查询item
	 * @param root
	 * @param item
	 * @return
	 */
	public void inorderTraversal(TreeNode<T> root, T data){
		if(root == null){
			return;
		}
		
		if(!isSearched)
		    inorderTraversal(root.left, data);
		
		if(!isSearched){
			if(!searchPath.toString().equals("")){
				searchPath.append("->");
			}
			searchPath.append(root.data);
			if(root.data.equals(data))
				isSearched = true;
		}
		
		if(!isSearched)
		    inorderTraversal(root.right, data);
	}
	
	/**
	 * 后续遍历root查询item
	 * @param item
	 * @return
	 */
	public void postorderTraversal(TreeNode<T> root, T data){
		if(root == null){
			return;
		}
		
		if(!isSearched)
		    postorderTraversal(root.left, data);
		
		if(!isSearched)
		    postorderTraversal(root.right, data);
		
		if(!isSearched){
			if(!searchPath.toString().equals("")){
				searchPath.append("->");
			}
			searchPath.append(root.data);
			if(root.data.equals(data))
				isSearched = true;
		}
	}
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值