数据结构与算法(Java描述)-18、树,二叉树以及二叉树的遍历,翻转二叉树

一、树的概念

树是由n(n≥0)个结点构成的满足以下条件的结点集合:
(1)当n>0时,有一个特殊的结点称为根结点,根结点没有前驱结点;

(2)当n>1时,除根结点外的其他结点被分成m(m>0)个互不相交的集合T1,T2,…, Tm,其中每一个集合Ti(1≤i≤m)本身又是一棵结构和树结构类同的子树。


结点:结点由数据元素和构造数据元素之间关系的指针组成。 

结点的度:结点所拥有的子树的个数称为该结点的度。 

叶结点:度为0的结点称为叶结点,叶结点也称作终端结点。 

分支结点:度不为0的结点称为分支结点,分支结点也称  作非终端结点。 

孩子结点:树中一个结点的子树的根结点称作这个结点的孩子结点。

双亲结点:若树中某结点有孩子结点,则这个结点就称作它的孩子结点的双亲结点。 

兄弟结点:具有相同的双亲结点的结点称为兄弟结点。 

树的度:树中所有结点的度的最大值称为该树的度。 

结点的层次:从根结点到树中某结点所经路径上的分支数。

树的深度:树中所有结点的层次的最大值称为该树的深度。

无序树:树中任意一个结点的各孩子结点的排列没有严格次序的树称为无序树。

有序树:树中任意一个结点的各孩子结点的排列有严格次序的树称为有序树。

森林:m(m≥0)棵树的集合称为森林。

二、树的存储结构

1、双亲表示法

双亲表示法就是用指针表示出每个结点的双亲结点。
对于使用仿真指针的双亲表示法来说,每个结点应有两个域,一个是数据元素域,另一个是指示其双亲结点在数组中下标序号的仿真指针域。
树及其使用仿真指针的双亲表示法

2、孩子表示法

孩子表示法就是用指针表示出每个结点的孩子结点。

常规指针的孩子表示法:


3、双亲孩子表示法:

双亲孩子表示法就是用指针既表示出每个结点的双亲结点,也表示出每个结点的孩子结点。


4、孩子兄弟表示法

孩子兄弟表示法就是用指针既表示出每个结点的孩子结点,也表示出每个结点的兄弟结点。


三、二叉树

1、二叉树的定义

二叉树是n(n≥0)个结点构成的、每个结点最多只有两个子树的有序树。

满二叉树:在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子结点都在同一层上。

完全二叉树:如果一棵具有n个结点的二叉树的逻辑结构与满二叉树的前n个结点的逻辑结构相同。

两颗不同的二叉树:


满二叉树和完全二叉树:


四、二叉树的性质

性质1  若规定根结点的层次为0,则一棵非空二叉树的第i层上最多有2i(i≥0)个结点。

性质2  若规定空二叉树树的深度为-1(即根结点的深度为0),则深度为k的二叉树的最大结点数是2k+1-1(k≥-1)个。

性质3  具有n个结点的完全二叉树的深度k为不超过log2(n+1)-1的最大整数。

性质4  对于一棵非空的二叉树,如果叶结点个数为n0,度为2的结点数为n2,则有n0= n2+1。

性质5  对于具有n个结点的完全二叉树,如果按照从上至下和从左至右的顺序对所有结点从0开始顺序编号,则对于序号为i的结点,有:

 (1)如果i>0,则序号为i结点的双亲结点的序号为 (i-1)/2(“/”表示整除);如果i=0,则序号为i结点为根结点,无双亲结点。

 (2)如果2×i+1<n,则序号为i结点的左孩子结点的序号为2×i+1;如果2×i+1≥n,则序号为i结点无左孩子结点。

 (3)如果2×i+2<n,则序号为i结点的右孩子结点的序号为2×i+2;如果2×i+2≥n,则序号为i结点无右孩子结点。

五、二叉树的存储结构

1、二叉树的顺序存储结构

非完全二叉树的顺序存储结构如下图


2、二叉树的链式存储结构

二叉树的链式存储结构是用指针建立二叉树中结点之间的关系。

二叉链存储结构的每个结点包含三个域 。


3、二叉树的仿真指针存储结构

二叉树的仿真指针存储结构是用数组存储二叉树中的结点


六、设计二叉树节点类,以及二叉树的遍历、节点搜索

二叉树节点类:

public class BinaryTreeNode {

	private Object data;           //数据域
	private BinaryTreeNode leftChilder;//左孩子
	private BinaryTreeNode rightChilder;//右孩子
	
	public BinaryTreeNode() {}
	
	public BinaryTreeNode(Object data,BinaryTreeNode leftChilder,BinaryTreeNode rightChilder) {
		this.data=data;
		this.leftChilder=leftChilder;
		this.rightChilder=rightChilder;
	}
	
	public Object getData() {
		return data;
	}
	public void setData(Object data) {
		this.data = data;
	}

	public void setLeftChilder(BinaryTreeNode leftChilder) {
		this.leftChilder = leftChilder;
	}
	public BinaryTreeNode getLeftChilder() {
		return leftChilder;
	}

	public BinaryTreeNode getRightChilder() {
		return rightChilder;
	}
	public void setRightChilder(BinaryTreeNode rightChilder) {
		this.rightChilder = rightChilder;
	}
	
	
}

以下图中的二叉树为例,实现前序遍历、中序遍历、后序遍历以及层次遍历,以及翻转二叉树的实现


递归实现

import java.util.LinkedList;
import java.util.Queue;
public class BinaryTree {
	//初始化二叉树
	public  BinaryTreeNode  initTree() {
		/**
		 *                 A
		 *            B         C
		 *        D          E     F
		 *          G
		 *    前序遍历:ABDGCEF
		 *    中序遍历:DGBAECF
		 *    后序遍历:GDBEFCA
		 *    层次遍历:ABCDEFG
		 */
		BinaryTreeNode G=new BinaryTreeNode("G", null, null);
		BinaryTreeNode D=new BinaryTreeNode("D", null, G);
		BinaryTreeNode E=new BinaryTreeNode("E", null, null);
		BinaryTreeNode F=new BinaryTreeNode("F", null, null);
		BinaryTreeNode B=new BinaryTreeNode("B", D, null);
		BinaryTreeNode C=new BinaryTreeNode("C", E, F);
		BinaryTreeNode A=new BinaryTreeNode("A", B, C);
		
		return A;
	}
	
	//打印二叉树的内容
	public  void printTree(BinaryTreeNode root) {
		System.out.print(root.getData());
	}
	
	//递归 二叉树前序遍历
	public  void preOrdere(BinaryTreeNode root) {
		if(root!=null) {
			printTree(root);
			if(root.getLeftChilder()!=null) {
				preOrdere(root.getLeftChilder());
			}
			if(root.getRightChilder()!=null) {
				preOrdere(root.getRightChilder());
			}
		}
	}
	
	//递归 二叉树中序遍历
	public  void inOrder(BinaryTreeNode root) {
		if(root!=null) {
			if(root.getLeftChilder()!=null) {
				inOrder(root.getLeftChilder());
			}
			printTree(root);
			if(root.getRightChilder()!=null) {
				inOrder(root.getRightChilder());
			}
		}
	}
	
	//递归 二叉树后序遍历
	public void postOrder(BinaryTreeNode root) {
		if(root!=null) {
			if(root.getLeftChilder()!=null) {
				postOrder(root.getLeftChilder());
			}
			if(root.getRightChilder()!=null) {
				postOrder(root.getRightChilder());
			}
			printTree(root);
		}
		
	}
	
	//层次遍历
	public  void levelOrder(BinaryTreeNode root) {
		if(root==null)
			return;
		Queue<BinaryTreeNode> queue=new LinkedList<>();
		queue.add(root);
		BinaryTreeNode temp;
		while(!queue.isEmpty()) {
			temp=queue.remove();
			printTree(temp);
			if(temp.getLeftChilder()!=null) {
				queue.add(temp.getLeftChilder());
			}
			
			if(temp.getRightChilder()!=null) {
				queue.add(temp.getRightChilder());
			}
		}
	}
	
	//在二叉树中查找指定元素
	public  BinaryTreeNode search(BinaryTreeNode root,Object obj) {
		if(root!=null) {
			BinaryTreeNode node=null;
			if(root.getData().equals(obj)) {
				node=root;
			}
			if(root.getLeftChilder()!=null) {
				search(root.getLeftChilder(), obj);
			}
			
			if(root.getRightChilder()!=null) {
				search(root.getRightChilder(), obj);
			}
			return node;
		}else {
			return null;
		}
	}

	//翻转二叉树(递归实现)
	public void reverse(BinaryTreeNode root){
		BinaryTreeNode tempBinaryTreeNode;
		tempBinaryTreeNode = root.getLeftChilder();
		root.setLeftChilder(root.getRightChilder());
		root.setRightChilder(tempBinaryTreeNode);

		if (root.getLeftChilder() != null) {
			reverse(root.getLeftChilder());
		}

		if (root.getRightChilder() != null) {
			reverse(root.getRightChilder());
		}
	}

	//打印二叉树
	public static void printBinaryTree(BinaryTreeNode root, int level)
	{
		if(root!=null)
		{
			printBinaryTree(root.getRightChilder(),level+1);

			if(level!=0)
			{
				//输出6*(level-1)个空格
				for(int i=0;i<6*(level-1);i++)
				{
					System.out.print(" ");
				}
				System.out.print("-----");
			}
			System.out.println(root.getData());

			printBinaryTree(root.getLeftChilder(),level+1);
		}
	}

	public static void main(String[] args) {
		BinaryTree tree=new BinaryTree();
		BinaryTreeNode root=tree.initTree();
		
		System.out.println("打印二叉树:");
		tree.printBinaryTree(root,0);
		
		System.out.println("前序遍历结果:");
		tree.preOrdere(root);
		System.out.println();
		
		System.out.println("中序遍历结果:");
		tree.inOrder(root);
		System.out.println();
		
		System.out.println("后序遍历结果:");
		tree.postOrder(root);
		System.out.println();
		
		System.out.println("层次遍历结果:");
		tree.levelOrder(root);
		System.out.println();
		
		System.out.println("在二叉树中查找元素A");
		BinaryTreeNode result=tree.search(root, "A");
		if(result!=null) {
			System.out.println("查找到的元素为:"+result.getData());
		}else {
			System.out.println("没有找到该元素!");
		}

		System.out.println("二叉树翻转结果:");
		tree.reverse(root);
		tree.printBinaryTree(root,0);

	}
}

运行结果:


非递归实现:

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

//非递归实现二叉树的遍历(利用Stack的特性)
public class BinaryTreeStack {
	//初始化二叉树
	public  BinaryTreeNode  initTree() {
		/**
		 *                 A
		 *            B         C
		 *        D          E     F
		 *          G
		 *    前序遍历:ABDGCEF
		 *    中序遍历:DGBAECF
		 *    后序遍历:GDBEFCA
		 *    层次遍历:ABCDEFG
		 */
		BinaryTreeNode G=new BinaryTreeNode("G", null, null);
		BinaryTreeNode D=new BinaryTreeNode("D", null, G);
		BinaryTreeNode E=new BinaryTreeNode("E", null, null);
		BinaryTreeNode F=new BinaryTreeNode("F", null, null);
		BinaryTreeNode B=new BinaryTreeNode("B", D, null);
		BinaryTreeNode C=new BinaryTreeNode("C", E, F);
		BinaryTreeNode A=new BinaryTreeNode("A", B, C);
		
		return A;
	}
	
	//打印二叉树的内容
	public void printTree(BinaryTreeNode root) {
		System.out.print(root.getData());
	}
	
	//前序遍历
	public void preOrder(BinaryTreeNode root) {
		Stack<BinaryTreeNode> stack=new Stack<>();
		BinaryTreeNode node=root;
		while(node!=null||stack.size()>0) {
			if(node!=null) {
				printTree(node);
				stack.push(node);
				node=node.getLeftChilder();
			}else {
				node=stack.pop();
				node=node.getRightChilder();
			}
		}
	}
	
	//中序遍历
	public void inOrder(BinaryTreeNode root) {
		Stack<BinaryTreeNode> stack=new Stack<>();
		BinaryTreeNode node=root;
		while(node!=null||stack.size()>0) {
			if(node!=null) {
				stack.push(node);
				node=node.getLeftChilder();
			}else {
				node=stack.pop();
				printTree(node);
				node=node.getRightChilder();
			}
		}
	}
	
	//后序遍历
	public void postOrder(BinaryTreeNode root) {
		Stack<BinaryTreeNode> stack=new Stack<>();
		Stack<BinaryTreeNode> stackTemp=new Stack<>();
		BinaryTreeNode node=root;
		while(node!=null||stack.size()>0) {
			if(node!=null) {
				stackTemp.push(node);
				stack.push(node);
				node=node.getRightChilder();
			}else {
				node=stack.pop();
				node=node.getLeftChilder();
			}
		}
		
		while(stackTemp.size()>0) {
			printTree(stackTemp.pop());
		}
	}
	
	//层次遍历
	public void levelOrder(BinaryTreeNode root) {
		if(root==null)
			return ;
		Queue<BinaryTreeNode> queue=new LinkedList<>();
		BinaryTreeNode temp;
		queue.add(root);
		while(!queue.isEmpty()) {
			temp=queue.remove();
			printTree(temp);
			if(temp.getLeftChilder()!=null) {
				queue.add(temp.getLeftChilder());
			}
			if(temp.getRightChilder()!=null) {
				queue.add(temp.getRightChilder());
			}
		}
	}
	
	//在二叉树中查找元素
	public BinaryTreeNode search(BinaryTreeNode root,Object obj) {
		if(root!=null) {
			BinaryTreeNode node=null;
			if(root.getData().equals(obj)) {
				return root;
			}
			
			if(root.getLeftChilder()!=null) {
				search(root.getLeftChilder(), obj);
			}
			
			if(root.getRightChilder()!=null) {
				search(root.getRightChilder(), obj);
			}
			return node;
		}else {
			return null;
		}
	}
	
	public static void main(String[] args) {
		BinaryTree tree=new BinaryTree();
		BinaryTreeNode root=tree.initTree();
		System.out.println("前序遍历结果:");
		tree.preOrdere(root);
		System.out.println();
		
		System.out.println("中序遍历结果:");
		tree.inOrder(root);
		System.out.println();
		
		System.out.println("后序遍历结果:");
		tree.postOrder(root);
		System.out.println();
		
		System.out.println("层次遍历结果:");
		tree.levelOrder(root);
		System.out.println();
		
		System.out.println("在二叉树中查找元素A");
		BinaryTreeNode result=tree.search(root, "A");
		if(result!=null) {
			System.out.println("查找到的元素为:"+result.getData());
		}else {
			System.out.println("没有找到该元素!");
		}
	}
}

运行结果:






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值