二叉树(Binary Tree)详解

二叉树本身就是递归定义的(wikipedia)

To actually define a binary tree in general, we must allow for the possibility that only one of the children may be empty. An artifact, which in some textbooks is called an extended binary tree is needed for that purpose. An extended binary tree is thus recursively defined as:

1.the empty set is an extended binary tree

2.if T1 and T2 are extended binary trees, then denote by T1 • T2 the extended binary tree obtained by adding a root r connected to the left to T1 and to the right to T2 by adding edges when these sub-trees are non-empty.

就是说考虑空集也是“扩展二叉树”,通过一个树节点节点将两个“扩展二叉树”分别作为左右子节点后,以该树节点为根节点构成一棵“扩展二叉树”。

二叉树类型:满二叉树、完全二叉树、完美二叉树、平衡二叉

性质:太多了!!!

存储二叉树节点的方法:

1.节点和引用,这个自不必说。

2.数组:二叉树以隐式广度优先搜索顺序存储在数组中,这种方法节省两个左右子节点引用的内存。

对于以0为索引开头的数组,数组索引值为i的节点,它的左右子节点的索引分别为2i+1,2i+2,而它的父节点数组索引[(i-1)/2]

对于以1为索引开头的数组,数组索引值为i的节点,它的左右子节点的索引分别为2i,2i+1,而它的父节点数组索引[i/2]

存储稠密并且更好的本地引用(数组索引速度快),然而这种存储方法耗费的空间复杂度为O(2^h-n)(深度h,节点数为n的树)

                                                         

直接上代码:

//二叉树的二叉链表树用根节点来表示
public class BinaryTree<T>{
	
	public BinaryNode<T> root;
	public BinaryTree()
	{
		this.root=null;
	}
	
	public BinaryTree(BinaryNode<T> root)
	{
		this.root=root;
	}
	
	/*
	 先根遍历和中根遍历两种次序可以唯一确定二叉树,perlist和inlist长度为n,序号为0~n-1
	 先根遍历序列prelist的perlist[0]为根节点,在中根遍历序列的inlist中寻找值为perlist[0]的节点,序号为i
	 在inlist中i左边0,i-1为左子树,i+1,n为右子树
	 左子树的先根遍历序列为prelist[1],...,prelist[i]
	 左子树的中根遍历序列为inlist[0],...inlist[i-1]
	 右子树的先根遍历序列为prelist[i+1],...prelist[n-1]
	 右子树的中根遍历序列inlist[i+1],...,inlist[n-1]
	 */
	public BinaryTree(T[] prelist,T[] inlist)
	{
		this.root=create(prelist,inlist,0,0,prelist.length);
	}
	
	public BinaryNode<T> create(T[] prelist,T[] inlist,int preStart,int inStart,int n )
	{
		if(n<=0)
			return null;
		T e=prelist[preStart];
		BinaryNode<T> p=new BinaryNode<T>(e);
		
		int i=0;
		while(i<n && !inlist[i+inStart].equals(e))
			i++;
		p.left=create(prelist,inlist,preStart+1,inStart,i);
		p.right=create(prelist,inlist,preStart+i+1,inStart+i+1,n-1-i);
		return p;
	}
	@Override
	public boolean isEmpty() {
		// TODO Auto-generated method stub
		return this.root==null;
	}

	@Override
	public int count() {
		// TODO Auto-generated method stub
		return count(this.root);
	}
	public int count(BinaryNode<T> p) 
	{
		if(p==null)
			return 0;
		return 1+count(p.left)+count(p.right);
	}
	@Override
	public int height() {
		// TODO Auto-generated method stub
		return height(this.root);
	}

	//递归调用height求当前节点的高度
	public int height(BinaryNode<T> p)
	{
		if(p==null)
			return 0;
		int lcount=height(p.left);
		int rcount=height(p.right);
		return (lcount>=rcount)?lcount+1:rcount+1;
	}
	@Override
	public void preOrder() {
		//先根次序遍历:访问根节点,遍历左子树,遍历右子树 TODO Auto-generated method stub
		System.out.print("先根次序遍历二叉树");
		preOrder(root);
		System.out.println();
	}

	public void preOrder(BinaryNode<T> p)
	{
		if(p!=null)
		{
			System.out.print(p.data.toString()+" ");
			preOrder(p.left);
			preOrder(p.right);
		}
	}
	
	/*用非递归先根遍历以node为根节点的(子)树
	*在二叉树先序遍历非递归算法中,先将根结点压栈,在栈不为空的时候执行循环:让栈顶元素p出栈,访问栈顶元素p,
	*如果p的右孩子不为空,则让其右孩子先进栈,如果p的左孩子不为空,则再让其左孩子进栈
	*(注意:进栈顺序一定是先右孩子,再左孩子)。
	*/
	public void preOrderNoRecursive(BinaryNode<T> node)
	{
		LinkedStack<BinaryNode<T>> stack=new LinkedStack<BinaryNode<T>>();
		BinaryNode<T> p=node;
		//停止while循环的条件是栈为空并且p指向null
		while(!stack.isEmpty() || p!=null)
		{
			while(p!=null)
			{
				System.out.print(p.data);
				stack.push(p);//入栈操作表示访问该节点
				p=p.left;
			}
			if(!stack.isEmpty())
			{
				p=stack.getTop();
				stack.pop();
				p=p.right;
			}
		}
	}
	
	public void preOrderNoRecursive2(BinaryNode<T> node)
	{
		LinkedStack<BinaryNode<T>> stack=new LinkedStack<BinaryNode<T>>();
		BinaryNode<T> p=node;
		while(!stack.isEmpty() || p!=null)
		{
			if(p!=null)
			{
				System.out.print(p.data);
				stack.push(p);
				p=p.left;
			}
			else
			{
				p=stack.getTop();
				stack.pop();
				p=p.right;
			}
		}
	}
	
	@Override
	public void inOrder() {
		//中根次序遍历:遍历左子树,访问根节点,遍历右子树 TODO Auto-generated method stub
		System.out.print("中根次序遍历二叉树");
		inOrder(root);
		System.out.println();
	}

	public void inOrder(BinaryNode<T> p)
	{
		if(p!=null)
		{
			preOrder(p.left);
			System.out.print(p.data.toString()+" ");
			preOrder(p.right);
		}
	}
	
	//用非递归中根遍历以node为根节点的(子)树
	public void inOrderNoRecursive(BinaryNode<T> node)
	{
		System.out.println("非递归中根遍历: ");
		LinkedStack<BinaryNode<T>> stack=new LinkedStack<BinaryNode<T>>();
		BinaryNode<T> p=node;
		while(!stack.isEmpty() || p!=null )
		{
			if(p!=null)
			{
				stack.push(p);
				p=p.left;
			}
			else
				{
				p=stack.pop();
				System.out.print(p.data+" ");
				p=p.right;
				}
		}
	}
	
	
	
	@Override
	public void postOrder() {
		// 后根次序遍历:遍历左子树,遍历右子树,访问根节点TODO Auto-generated method stub
		System.out.print("后根次序遍历二叉树");
		postOrder(root);
		System.out.println();
	}

	public void postOrder(BinaryNode<T> p) 
	{
		if(p!=null)
		{
			postOrder(p.left);
			postOrder(p.right);
			System.out.print(p.data.toString()+" ");
		}
	}
	
	//对于非递归后根遍历,使用顺序栈比
	public void postOrderNoRecursive(BinaryNode<T> node)
	{
		System.out.println("非递归后根遍历: ");
		SeqStack<BinaryNode<T>> stack=new SeqStack<BinaryNode<T>>();
		BinaryNode<T> p=node;
		int[] tag=new int[this.count()];
		//停止while循环的条件是栈为空并且p指向null
		while(!stack.isEmpty() || p!=null)
		{
			while(p!=null)
			{
				stack.push(p);
				tag[stack.getTopIndex()]=0;
				p=p.left;
			}
			while(!stack.isEmpty() && tag[stack.getTopIndex()]==1)
			{
				System.out.print(stack.pop());
			}
			if(!stack.isEmpty())
			{
				p=stack.getTop();
				tag[stack.getTopIndex()]=1;
				p=p.right;
			}
		}
	}
	
	public void postOrderNoRecursive2(BinaryNode<T> node)
	{
		if(node==null)
			return;
		LinkedStack<BinaryNode<T>> stack=new LinkedStack<BinaryNode<T>>();
		stack.push(node);
		BinaryNode<T> lastPop=node;
		while(!stack.isEmpty())
		{
			BinaryNode<T> top =stack.getTop();
			if(top.left!=null && top.left!=lastPop && top.right!=lastPop)
				stack.push(top.left);
			else if(top.right!=null && top.right!=lastPop && (top.left==lastPop || top.left==null))
			{
				stack.push(top.right);
			}
			else
			{
				stack.pop();
				lastPop=top;
				System.out.print(top.data);
			}
		}
	}
	
	public String toGenListString()
	{
		return "二叉树的广义表形式"+this.toGenListString(this.root);
	}
	
	public String toGenListString(BinaryNode<T> node)
	{
		if(node==null)
			return "^";
		String str=node.data.toString();
		if(node.left!=null || node.right!=null)
			str+="("+this.toGenListString(node.left)+","+this.toGenListString(node.right)+")";
		return str;
	}
	
	
	public void levelOrder(BinaryNode<T> node) {
		// TODO Auto-generated method stub
		LinkedQueue<BinaryNode<T>> q=new LinkedQueue<BinaryNode<T>>();
		BinaryNode<T> p=node;
		q.enqueue(p);
		while(!q.isEmpty())
		{
			p=q.dequeu();
			System.out.print(p.data.toString());
			if(p.left!=null)
				q.enqueue(p.left);
			if(p.right!=null)
				q.enqueue(p.right);
		}
	}

	@Override
	public void levelOrder()
	{
		levelOrder(this.root);
	}
	
	@Override
	public BinaryNode<T> search(T key) {
		// TODO Auto-generated method stub
		return search(this.root,key);
	}

	public BinaryNode<T> search(BinaryNode<T> p,T key)
	{
		if(p==null||key==null)
			return null;
		if(p.data.equals(key))
			return p;
		BinaryNode<T> find=search(p.left,key);
		if(find==null)
			find=search(p.right,key);
		return find;
	}
	
	@Override
	public BinaryNode<T> getParent(BinaryNode<T> node) {
		// TODO Auto-generated method stub
		return getParent(this.root,node);
	}

	//查找以p为根的子树中节点node的父节点
	public BinaryNode<T> getParent(BinaryNode<T> p,BinaryNode<T> node)
	{
		if(p==null)
			return null;
		if(p.left==node||p.right==node)
			return p;
		BinaryNode<T> find=getParent(p.left,node);
		if(find==null)
			find=getParent(p.right,node);
		return find;
	}
	
	@Override
	public void insertRoot(T x) {
		// TODO Auto-generated method stub
		BinaryNode<T> new_root=new BinaryNode<T>(x);
		new_root.left=this.root;	
	}

	//插入x作为节点p的左(右)子节点,如果p节点已经存在对应的左(右)节点,则原左(右)节点作为插入节点的左(右)子节点
	@Override
	public BinaryNode<T> insertChild(BinaryNode<T> p, T x, boolean leftChild) {
		// TODO Auto-generated method stub
		if(p==null || x==null)
			return null;
		BinaryNode<T> new_node=new BinaryNode<T>(x);
		if(leftChild)
		{
			if(p.left==null)
				p.left=new_node;
			else
			{
				new_node.left=p.left;
				p.left=new_node;
			}
		}
		else
		{
			if(p.right==null)
				p.right=new_node;
			else
			{
				new_node.right=p.right;
				p.right=new_node;
			}
		}
		return new_node;
	}

	//删除节点p的左(右)子节点,这里规定将以p的左(右)子节点为根节点的树全部删去
	@Override
	public void removeChild(BinaryNode<T> p, boolean leftChild) {
		// TODO Auto-generated method stub
		if(p!=null)
		{
			if(leftChild)
				p.left=null;
			else
				p.right=null;
		}
	}

	@Override
	public void removeAll() {
		// TODO Auto-generated method stub
		this.root=null;
	}
	
	public static void main(String[] args)
	{
		BinaryNode<String> n7=new BinaryNode<String>("H");
		BinaryNode<String> n6=new BinaryNode<String>("G");
		BinaryNode<String> n5=new BinaryNode<String>("F");
		BinaryNode<String> n4=new BinaryNode<String>("E");
		BinaryNode<String> n3=new BinaryNode<String>("D",n7,null);
		BinaryNode<String> n2=new BinaryNode<String>("C",n5,n6);
		BinaryNode<String> n1=new BinaryNode<String>("B",n3,n4);
		BinaryNode<String> n0=new BinaryNode<String>("A",n1,n2);
		
		BinaryTree<String> tree=new BinaryTree<String>(n0);
		System.out.println(tree.height());
		System.out.println(tree.count());
		tree.preOrder();
		tree.inOrder();
		tree.postOrder();
		tree.preOrderNoRecursive(n0);
		System.out.println();
		tree.preOrderNoRecursive2(n0);
		System.out.println();
		tree.postOrderNoRecursive(n0);
		System.out.println();
		tree.postOrderNoRecursive(n2);
		System.out.println();
		tree.postOrderNoRecursive2(n0);
		System.out.println();
		System.out.println(tree.toGenListString());
		System.out.println();
		tree.levelOrder();
	}
}

打印结果如下:

4
8
先根次序遍历二叉树A B D H E C F G 
中根次序遍历二叉树B D H E A C F G 
后根次序遍历二叉树H D E B F G C A 
ABDHECFG
ABDHECFG
非递归后根遍历: 
HDEBFGCA
非递归后根遍历: 
FGC
HDEBFGCA
二叉树的广义表形式A(B(D(H,^),E),C(F,G))

ABCDEFGH

猜你喜欢

转载自blog.csdn.net/To_be_to_thought/article/details/84668184
今日推荐