树和二叉树

一、树的基本概念

树是由一个集合以及在该集合上定义的一种关系构成的。集合中的关系称的结点,所定义的关系为父子关系最上层为根节点树是n(n>=o)个结点的有限集
在这里插入图片描述
a.一颗空树,b.有一个根节点的树,c.有许多子结点

结点的度:结点拥有子结点的数目
树的度:树内各节点最大的度数
在这里插入图片描述
树的深度:树中结点的最大层树
在这里插入图片描述
有序树:各节点从左到右有次序
在这里插入图片描述

二、二叉树

每个结点的度都不超过二的有序树,称为二叉树
在这里插入图片描述
满二叉树:高度为并且有个2^(k+1)-1结点的二叉树,每层的结点都达到最大数
在这里插入图片描述
完全二叉树:在一棵满二叉树中,在最下层最右侧起去点相邻的叶子结点得到的二叉树
在这里插入图片描述
满二叉树必为完全二叉树,反之不一定
二叉树的性质:
1.在二叉树的第i层上最多有2^(i-1) 个结点(根是第一层)
2.高度为h的二叉树最多有2^h -1个节点
3.对于任何一个二叉树,如果其终端节点数为n,度为2 的结点数为m,则n=m+1
4.如果一颗二叉树有n个结点的完全二叉树进行编号,则对任一结点(1<=i<=n)
5.若i=1,则i是二叉树的根、、
6.如果2i>n,则结点i无左孩子,否则其左孩子为2i
7.如果2i+1>n,则结点i无右孩子,否则其右孩子为2i+1

三、叉树的存储结构

1.顺序存储结构
对于满二叉树和完全二叉树来说,可以将其数据元素筑层放到一组连续的存储单元
在这里插入图片描述
如果不是满二叉树,则比较浪费空间
在这里插入图片描述
2.链式存储结构
若将其采用链式存储,则只需从树的根节点开始,将各个节点及其左右孩子使用链表存储即可。因此,图 1 对应的链式存储结构如图 2 所示:

二叉树链式存储结构示意图
在这里插入图片描述

二叉树遍历

遍历:按着某种次序访问树中所以二叉树,且每个节点恰好访问一次。人为的将非线性化线性化。
先序遍历DLR:根 左 右
中序遍历LDR:左子树 根 右子树
后序遍历LRD:左 右 根
在这里插入图片描述

Node.java

/**
 * 
 */
package com.liang.datastructure.btree;

/**
 * 二叉树链表节点
 * @author Administrator
 *
 */
public class Node {
	private Node leftChild;//左子树引用
	private Object data;
	private Node rightChild;
	
	
	public Node(Object data) {
		super();
		this.data = data;
	}

	public Node(Node leftChild, Object data, Node rightChild) {
		super();
		this.leftChild = leftChild;
		this.data = data;
		this.rightChild = rightChild;
	}
	public Node getLeftChild() {
		return leftChild;
	}
	public void setLeftChild(Node leftChild) {
		this.leftChild = leftChild;
	}
	public Object getData() {
		return data;
	}
	public void setData(Object data) {
		this.data = data;
	}
	public Node getRightChild() {
		return rightChild;
	}
	public void setRightChild(Node rightChild) {
		this.rightChild = rightChild;
	}

	@Override
	public String toString() {
		return "Node [leftChild=" + leftChild + ", data=" + data + ", rightChild=" + rightChild + "]";
	}
	
	
	
}

BinaryTree.java

package com.liang.datastructure.btree;
/**
 * 二叉树接口
 * 可以有不同的实现类,每个类可以使用不同的存储结构,比如顺序结构、链式结构
 * @author Administrator
 *
 */
public interface BinaryTree {
	/**
	 * 是否空树
	 * @return
	 */
	public boolean isEmpty();
	/**
	 * 树结点数量
	 * @return
	 */
	public int size();
	
	/**
	 * 获取二叉树的高度
	 * @return
	 */
	public int getHeight();
	/**
	 * 查询指定值的结点
	 * @param value
	 * @return
	 */
	public Node findKey(int value); // 查找
	/**
	 * 前序递归遍历
	 */
	public void preOrderTraverse(); 
	/**
	 * 中序遍历递归操作
	 */
	public void inOrderTraverse();  	
	/**
	 * 后序遍历递归操作
	 */
	public  void postOrderTraverse();
	/**
	 * 后序遍历递归操作
	 * @param node  树根结点
	 */
	public  void postOrderTraverse(Node node); 
	/**
	 * 中序遍历非递归操作
	 * 1)对于任意节点current,若该节点不为空则将该节点压栈,并将左子树节点置为current,重复此操作,直到current为空。 
	 * 2)若左子树为空,栈顶节点出栈,访问节点后将该节点的右子树置为current
	 * 3) 重复1、2步操作,直到current为空且栈内节点为空。 
	 */
	public void inOrderByStack();
	/**
	 *   前序遍历非递归操作
	 *   1)对于任意节点current,若该节点不为空则访问该节点后再将节点压栈,并将左子树节点置为current,重复此操作,直到current为空。 
	 *   2)若左子树为空,栈顶节点出栈,将该节点的右子树置为current 
	 *   3) 重复1、2步操作,直到current为空且栈内节点为空。
	 */
	public  void preOrderByStack(); 
	/**
	 * 后序遍历非递归操作
	 * 1)对于任意节点current,若该节点不为空则访问该节点后再将节点压栈,并将左子树节点置为current,重复此操作,直到current为空。 
	 * 2)若左子树为空,取栈顶节点的右子树,如果右子树为空或右子树刚访问过,则访问该节点,并将preNode置为该节点 
	 * 3) 重复1、2步操作,直到current为空且栈内节点为空。 
	 */
	public  void postOrderByStack(); 
	
	/**
	 * 按照层次遍历二叉树
	 */
	public void levelOrderByQueue();
}

LinkedBinaryTree.java

/**
 * 
 */
package com.liang.datastructure.btree;

import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;

/**

 * @author Administrator
 *链式实现类
 */
public class LinkedBinaryTree implements BinaryTree{
	private Node root;
	
	
	
	public LinkedBinaryTree() {
		super();
	}

	public LinkedBinaryTree(Node root) {
		super();
		this.root = root;
	}

	@Override
	public boolean isEmpty() {
		// TODO 自动生成的方法存根
		return root == null;
	}

	@Override
	public int size() {
		return this.size(root);
	}
	private int size(Node node) {
		if(node==null) {
			return 0;
		}else {
			//左子树节点数
			int l = this.size(node.getLeftChild());
			//右子树节点数
			int r=this.size(node.getRightChild());
			return l+r+1;
		}
	}

	@Override
	public int getHeight() {
		
		return getHeight(root);
	}
	private int getHeight(Node node) {
		if(node==null) {
			//System.out.println("-------------");
			return 0;
		}else {
			int l = this.getHeight(node.getLeftChild());
			//System.out.print("l值:"+l+"  ");
			int r=this.getHeight(node.getRightChild());
			//System.out.print("r值:"+r+"  ");
			return l>r ? l+1:r+1;
		}
		
	}
	@Override
	public Node findKey(int value) {
		return findKey(value,root);
	}
	public Node findKey(Object value,Node root) {
		if(root == null){//递归结束条件1:结点为空,可能是整个树的根节点,也可能是递归调用中叶子节点中左孩子和右孩子
			return null;
		}else if(root != null && root.getData() == value){//递归的结束条件2:找到了
			return root;
		}else {//递归体
			Node node1 = this.findKey(value, root.getLeftChild());
			Node node2 = this.findKey(value, root.getRightChild());
			if(node1 != null && node1.getData() == value){
				return node1;
			}else if(node2 != null && node2.getData() == value){
				return node2;
			}else{
				return null;
			}
		}
	} 
	@Override
	public void preOrderTraverse() {
		if(root != null){
			//1.输出根结点的值
			System.out.print(root.getData()+"  ");
			//2.对左子树进行先序遍历
			//构建一个二叉树,根是左子树的根
			BinaryTree  leftTree = new LinkedBinaryTree(root.getLeftChild());
			leftTree.preOrderTraverse();
			//对右子树进行先序遍历
			//3.构建一个二叉树,根是右子树的根
			BinaryTree  rightTree = new LinkedBinaryTree(root.getRightChild());
			rightTree.preOrderTraverse();
		}
	}

	@Override
	public void inOrderTraverse() {
		System.out.println("中序遍历:");
		inOrderTraverse(root);
		System.out.println();
		
	}
	private void inOrderTraverse(Node root) {
		if(root!=null) {
		this.inOrderTraverse(root.getLeftChild());
		System.out.print(root.getData()+"  ");
		this.inOrderTraverse(root.getRightChild());
		}
	}

	@Override
	public void postOrderTraverse() {
		System.out.println("后序遍历:");
		postOrderTraverse(root);
		System.out.println();
	}

	@Override
	public void postOrderTraverse(Node node) {
		if(node!=null) {
			this.postOrderTraverse(node.getLeftChild());
			this.postOrderTraverse(node.getRightChild());
			System.out.print(node.getData()+"  ");
		}
	}

	@Override
	public void inOrderByStack() {
		System.out.println("中序非递归遍历:");
		// 创建栈
		Deque<Node> stack = new LinkedList<Node>();
		Node current = root;
		while (current != null || !stack.isEmpty()) {
			while (current != null) {
				stack.push(current);
				current = current.getLeftChild();
			}

			if (!stack.isEmpty()) {
				current = stack.pop();
				System.out.print(current.getData() + " ");
				current = current.getRightChild();
			}
		}
		System.out.println();	
		
	}

	@Override
	public void preOrderByStack() {
		// TODO 自动生成的方法存根
		
	}

	@Override
	public void postOrderByStack() {
		// TODO 自动生成的方法存根
		
	}

	@Override
	public void levelOrderByQueue() {
		System.out.println("按照层次遍历二叉树");
		if(root == null) return;
	    Queue<Node> queue = new LinkedList<Node>() ;
	    queue.add(root);
	    while(queue.size() != 0)
	    {
	        int len = queue.size();
	        for(int i=0;i <len; i++)
	        {
	        	Node temp = queue.poll();
	            System.out.print(temp.getData()+" ");
	            if(temp.getLeftChild() != null)  queue.add(temp.getLeftChild());
	            if(temp.getRightChild() != null) queue.add(temp.getRightChild());
	        }
	    }
	    
	    System.out.println();
		
	}

}

测试

/**
 * 
 */
package com.liang.datastructure.btree;

/**
 * @author Administrator
 *
 */
public class Test {
	public static void main(String[] args) {
		//创建一个二叉树
		Node node5=new Node(5);
		Node node4 = new Node(null, 4, node5);
		Node node7 = new Node(7);
		Node node6 = new Node(null, 6, node7);
		Node node3 = new Node(3);
		Node node2 = new Node(node3, 2, node6);
		Node node1 = new Node(node4, 1, node2);
		
		BinaryTree btree=new LinkedBinaryTree(node1);
				//判断二叉树是否为空
				System.out.println(btree.isEmpty());
				
				//先序遍历递归  1  4  5  2  3  6  7
				System.out.println("先序遍历");
				btree.preOrderTraverse();
				System.out.println();
				
				//中序遍历递归  4  5  1  3  2  6  7
				btree.inOrderTraverse();
				
				//后序遍历递归  5  4  3  7  6  2  1 
				btree.postOrderTraverse();
				
				System.out.println(btree.getHeight());
				System.out.println(btree.size());
				//中序遍历非递归(借助栈) 4  5  1  3  2  6  7
				//btree.inOrderByStack();
				btree.levelOrderByQueue();
	}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值