二叉树概念总结
1、二叉树的递归定义
二叉树(Binary Tree)是个有限元素的集合,该集合或者为空、或者由一个称为根(root)的元素及两个不相交的、被分别称为左子树和右子树的二叉树组成。
当集合为空时,称该二叉树为空二叉树。在二叉树中,一个元素也称作一个结点。二叉树是有序的,即若将其左、右子树颠倒,就成为另一棵不同的二叉树。即使树中结点只有一棵子树,也要区分它是左子树还是右子树。(二叉树有五种形态)
2、二叉树的相关概念
(1)结点的度。结点所拥有的子树的个数称为该结点的度。
(2)叶结点。度为0 的结点称为叶结点,或者称为终端结点。
(3)分枝结点。度不为0 的结点称为分支结点,或者称为非终端结点。
(4)左孩子、右孩子、双亲。树中一个结点的子树的根结点称为这个结点的孩子。这个结点称为它孩子结点的双亲。具有同一个双亲的孩子结点互称为兄弟。
(5)路径、路径长度。如果一棵树的一串结点n1,n2,…,nk有如下关系:结点ni是ni+1的父结点(1≤i<k),就把n1,n2,…,nk称为一条由n1至nk的路径。这条路径的长度是k-1。
(6)祖先、子孙。在树中,如果有一条路径从结点M 到结点N,那么M 就称为N的祖先,而N 称为M 的孙。
(7)结点的层数。规定树的根结点的层数为1,其余结点的层数等于它的双亲结点的层数加1。
(8)树的深度。树中所有结点的最大层数称为树的深度。
(9)树的度。树中各结点度的最大值称为该树的度。
3、二叉树的主要性质
性质1: 在二叉树的第i层上至多有2的i-1次方个结点(i>=1)。
性质2: 深度为k的二叉树至多有2的k次方减1个结点(k>=1)。
性质3: 对任何一棵二叉树T,如果其终端结点数为n0,度为2的结点数为n2,则n0=n2+1。
性质4: 具有n个结点的完全二叉树的深度为|log2n|+1
性质5: 如果对一棵有n个结点的完全二叉树的结点按层序编号,则对任一结点i(1≤i≤n)有:
(1) 如果i=1,则结点i是二叉树的根,无双亲;如果i>1,则双亲PARENT(i)是结点i/2
(2) 如果2i>n,则结点i无左孩子(结点i为叶子结点);否则其左孩子LCHILD(i)是结点2i
(3) 如果2i+1>n,则结点i无右孩子;否则其右孩子RCHILD(i)是结点2i+1
图片来源:http://sunlei.blog.51cto.com/525111/111063
二叉树实现
import java.util.Queue;
import java.util.Vector;
import java.util.concurrent.ConcurrentLinkedQueue;
class BinaryTreeNode {
int data;
BinaryTreeNode leftchild;
BinaryTreeNode rightchild;
BinaryTreeNode(int t) {
this.data = t;
this.leftchild = null;
this.rightchild = null;
}
BinaryTreeNode(int t, BinaryTreeNode leftchild, BinaryTreeNode rightchild) {
this.data = t;
this.leftchild = leftchild;
this.rightchild = rightchild;
}
}
public class BinaryTree {
BinaryTreeNode root = null;
public BinaryTree(int[] t) {
creatBinaryTree(t);
}
/* 拷贝构造函数 */
public BinaryTree(BinaryTree otherTree) {
if (otherTree.root == null)
this.root = null;
else{
this.root=copy(otherTree.root);
//this.root=otherTree.root;
}
}
private BinaryTreeNode creatBinaryTree(int[] t) {
int length = t.length;
if (root == null) {
root = new BinaryTreeNode(t[0]);
}
for (int i = 1; i < length; i++) {
creat(root, t[i]);
}
return root;
}
// 构造二叉树
private void creat(BinaryTreeNode root, int t) {
if (t >= root.data) {
if (root.rightchild == null) {
root.rightchild = new BinaryTreeNode(t);
} else {
creat(root.rightchild, t);
}
} else {
if (root.leftchild == null) {
root.leftchild = new BinaryTreeNode(t);
} else {
creat(root.leftchild, t);
}
}
}
/* 遍历二叉树 前中后*/
public void inIterator(BinaryTreeNode b) {
if (b != null) {
inIterator(b.leftchild);
System.out.print(b.data + ",");
inIterator(b.rightchild);
}
}
public void levelOrderDisplay(BinaryTreeNode b){
ConcurrentLinkedQueue<BinaryTreeNode> q = new ConcurrentLinkedQueue<BinaryTreeNode>();//创建链式队列对象
if(b == null)return;
BinaryTreeNode curr;
q.add(b); //根结点入队列
while(!q.isEmpty()){ //当队列非空时循环
curr = (BinaryTreeNode)q.remove(); //出队列
System.out.println(curr.data); //访问该结点
if(curr.leftchild != null)
q.add(curr.leftchild); //左孩子结点入队列
if(curr.rightchild != null)
q.add(curr.rightchild);//右孩子结点入队列
}
}
/* 树的高度 */
public int treeHeight(BinaryTreeNode b) {
if (b == null)
return -1;
else
return (treeHeight(b.leftchild) >= treeHeight(b.rightchild) ? treeHeight(b.leftchild)
: treeHeight(b.rightchild)) + 1;
}
/* 求总节点数 */
public int treeNodes(BinaryTreeNode b) {
if (b == null)
return 0;
else if (b.leftchild == null && b.rightchild == null)
return 1;
else
return 1 + treeNodes(b.rightchild) + treeNodes(b.leftchild);
}
/* 求叶节点数 */
public int treeLeavesNode(BinaryTreeNode b) {
if (b == null)
return 0;
else if (b.leftchild == null && b.rightchild == null)
return 1;
else
return treeLeavesNode(b.rightchild) + treeLeavesNode(b.leftchild);
}
/* 复制树 */
public BinaryTreeNode copy(BinaryTreeNode b) {
BinaryTreeNode newNode;
if (b == null)
return null;
newNode=new BinaryTreeNode(b.data);
newNode.leftchild = copy(b.leftchild);
newNode.rightchild = copy(b.rightchild);
//newNode = new BinaryTreeNode(b.data, newLeftChild, newRightChild);
return newNode;
}
/*删除树*/
public void delete(){
deleteTree(this.root);
System.out.println(this.root.rightchild.rightchild.rightchild==null);
}
public void deleteTree(BinaryTreeNode b){
if(b!=null){
deleteTree(b.leftchild);
deleteTree(b.rightchild);
b=null;
}
}
/* 查找一个节点 */
public boolean findNode(BinaryTreeNode b,int key){
if(b==null)return false;
if(b.data==key)return true;
if(key>b.data)return findNode(b.rightchild,key);
return findNode(b.leftchild,key);
}
public void insertNode(BinaryTreeNode b,int t){
creat(b,t);
}
public static void main(String[] args) {
int[] data = { 12, 11, 34, 45, 67, 38, 56, 43, 22, 8};
System.out.println(data.length);
BinaryTree btree = new BinaryTree(data);
BinaryTreeNode r = btree.root;
btree.inIterator(r);
System.out.println();
System.out.println("Height:" + btree.treeHeight(r));
System.out.println("Nodes:" + btree.treeNodes(r));
System.out.println("Leaves:" + btree.treeLeavesNode(r));
BinaryTree copyTree=new BinaryTree(btree);
System.out.println("copyTree:");
copyTree.insertNode(copyTree.root, 57);
System.out.println("Height:" + copyTree.treeHeight(copyTree.root));
System.out.println("Nodes:" + copyTree.treeNodes(copyTree.root));
System.out.println("Leaves:" + copyTree.treeLeavesNode(copyTree.root));
System.out.println("Btree Height:" + btree.treeHeight(r));
System.out.println("Nodes:" + btree.treeNodes(r));
System.out.println("Leaves:" + btree.treeLeavesNode(r));
System.out.println(copyTree.findNode(copyTree.root, 8));
copyTree.inIterator(copyTree.root);
/* copyTree.delete();
System.out.println(copyTree.root==null);
System.out.println("deleteTree:");
System.out.println("Height:" + copyTree.treeHeight(copyTree.root));
System.out.println("Nodes:" + copyTree.treeNodes(copyTree.root));*/
System.out.println("LevelOrder:");
copyTree.levelOrderDisplay(copyTree.root);
}
}