树(tree)是一种抽象数据类型(ADT)或是实作这种抽象数据类型的数据结构,用来模拟具有树状结构性质的数据集合。它是由n(n>0)个有限节点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。
树的特点:
- 每个节点有零个或多个子节点;
- 没有父节点的节点称为根节点;
- 每一个非根节点有且只有一个父节点;
- 除了根节点外,每个子节点可以分为多个不相交的子树;
常用到的术语:
- 节点的度:一个节点含有的子树的个数称为该节点的度
(上图 A->2 B->3 J->0)
;
-
树的度:一棵树中,最大的节点的度称为树的度
(上图B节点 3个度 最大)
; -
叶节点或终端节点:度为零的节点
(上图A K O P)
; -
父亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点
(上图A是BC的父节点 B是DEF的父节点)
; - 孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点(上图BC是A的子节点 DEF是B的子节点)`;
-
兄弟节点:具有相同父节点的节点互称为兄弟节点
(上图BC DEF LM是相互的兄弟节点 )
; -
节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推
(上图A为第1层 BC第2层 DEFGH第三层 ...)
; -
树的高度或深度 :树中节点的最大层次
(上图为5层)
; -
堂兄弟节点:父节点在同一层的节点互为堂兄弟
(上图FG为堂兄弟节点)
; - 森林:由m(m>=0)棵互不相交的树的集合称为森林;
种类
- 无序树:树中任意节点的子节点之间没有顺序关系,这种树称为无序树,也称为自由树;
- 有序树:树中任意节点的子节点之间有顺序关系,这种树称为有序树;
-
二叉树:每个节点最多含有两个子树的树称为二叉树;
-
完全二叉树:对于一颗二叉树,假设其深度为d(d>1)。除了第d层外,其它各层的节点数目均已达最大值,且第d层所有节点从左向右连续地紧密排列,这样的二叉树被称为完全二叉树;
- 满二叉树:所有叶节点都在最底层的完全二叉树(下图所示);
- 平衡二叉树:当且仅当任何节点的两棵子树的高度差不大于1的二叉树;
- 排序二叉树(二叉查找树)(英语:Binary Search Tree),也称二叉搜索树、有序二叉树);
-
完全二叉树:对于一颗二叉树,假设其深度为d(d>1)。除了第d层外,其它各层的节点数目均已达最大值,且第d层所有节点从左向右连续地紧密排列,这样的二叉树被称为完全二叉树;
- ......
二叉树的性质:
- 在二叉树的第i层上至多有2^(i-1)个结点。
- 深度为k的二叉树之多有(2^k)-1个结点。
- 对任何一棵二叉树T,如果其终端结点数为n0,度为2的结点树为n2,则n0=n2+1。
- 具有n个结点的完全二叉树的深度为(logn)+1。
- 如果对一棵有n个结点的完全二叉树的结点按层序号遍历,对任意结点i有:
如果i=1,则结点i是二叉树的根,无双亲;如果i>1,则其双亲是结点i/2。
如果2i>n,则结点i无左孩子;否则其左孩子是结点2i。
如果2i+1>n,则结点i无右孩子;否则其右孩子是结点2i+1.
二叉树的表示方法:
双亲表示法
在每个结点中,附设一个指示器指示其双亲结点到链表中的位置。这种方式返回来找父节点不方便
孩子表示法:也不助于查找父节点
孩子兄弟表示法:
比较好的表示方案:借用HashMap
的思想,一个组head
表示父节点,一组都是该父节点的子节点。
二叉树的遍历:
- 前序遍历:若二叉树为空,则空操作返回,否则先访问根结点,然后前序遍历左子树,再前序遍历右子树。 中-->左-->右
- 中序遍历:若二叉树为空,则空操作返回,否则从根结点开始,中序遍历根节点的左子树,然后访问根结点,再中序遍历根结点的右子树。左-->中-->右
- 后序遍历:若二叉树为空,则空操作返回,否则从左到右先叶子后节点的方式遍历访问左子树和右子树,最后是访问根结点。左-->右-->中
- 层次遍历:若二叉树为空,则空操作返回,否则从树的第一层开始,也就是根结点开始访问,从上而下逐层遍历,在同一层中,按从左到右的顺序对结点逐个访问。一层一层的遍历
JAVA实现一个简单的二叉树的遍历
public class BinaryTree {
private TreeNode root = null;
public BinaryTree(){
root = new TreeNode(1, "A");
}
/**
* 构建二叉树
* A
* B C
* D E F
*/
public void createBinaryTree(){
TreeNode nodeB = new TreeNode(2, "B");
TreeNode nodeC = new TreeNode(3, "C");
TreeNode nodeD = new TreeNode(4, "D");
TreeNode nodeE = new TreeNode(5, "E");
TreeNode nodeF = new TreeNode(6, "F");
root.leftChild = nodeB;
root.rightChild = nodeC;
nodeB.leftChild = nodeD;
nodeB.rightChild = nodeE;
nodeC.rightChild = nodeF;
}
/**
* 求二叉树的高度
* @author Administrator
*
*/
public int getHeight(){
return getHeight(root);
}
private int getHeight(TreeNode node) {
if(node == null){
return 0;
}else{
int i = getHeight(node.leftChild);
int j = getHeight(node.rightChild);
return (i<j)?j+1:i+1;
}
}
/**
* 获取二叉树的结点数
* @author Administrator
*
*/
public int getSize(){
return getSize(root);
}
private int getSize(TreeNode node) {
if(node == null){
return 0;
}else{
return 1+getSize(node.leftChild)+getSize(node.rightChild);
}
}
/**
* 前序遍历——迭代
* @author Administrator
*
*/
public void preOrder(TreeNode node){
if(node == null){
return;
}else{
System.out.println("preOrder data:"+node.getData());
preOrder(node.leftChild);
preOrder(node.rightChild);
}
}
/**
* 前序遍历——非迭代
*/
public void nonRecOrder(TreeNode node){
if(node == null){
return;
}
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(node);
while(!stack.isEmpty()){
//出栈和进栈
TreeNode n = stack.pop();//弹出根结点
//压入子结点
System.out.println("nonRecOrder data"+n.getData());
if(n.rightChild!=null){
stack.push(n.rightChild);
}
if(n.leftChild!=null){
stack.push(n.leftChild);
}
}
}
/**
* 中序遍历——迭代
* @author Administrator
*
*/
public void midOrder(TreeNode node){
if(node == null){
return;
}else{
midOrder(node.leftChild);
System.out.println("midOrder data:"+node.getData());
midOrder(node.rightChild);
}
}
/**
* 后序遍历——迭代
* @author Administrator
*
*/
public void postOrder(TreeNode node){
if(node == null){
return;
}else{
postOrder(node.leftChild);
postOrder(node.rightChild);
System.out.println("postOrder data:"+node.getData());
}
}
public class TreeNode{
private int index;
private String data;
private TreeNode leftChild;
private TreeNode rightChild;
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public TreeNode(int index,String data){
this.index = index;
this.data = data;
this.leftChild = null;
this.rightChild = null;
}
}
public static void main(String[] args){
BinaryTree binaryTree = new BinaryTree();
binaryTree.createBinaryTree();
int height = binaryTree.getHeight();
System.out.println("treeHeihgt:"+height);
int size = binaryTree.getSize();
System.out.println("treeSize:"+size);
// binaryTree.preOrder(binaryTree.root);
// binaryTree.midOrder(binaryTree.root);
// binaryTree.postOrder(binaryTree.root);
binaryTree.nonRecOrder(binaryTree.root);
}
}
水平有限,文中有什么不对或者有什么建议希望大家能够指出,谢谢!