二叉树的三种遍历方式

二叉树的定义:
二叉树是每个结点最多有两个子树的树结构。子树被称为“左子树” 和 “右子树”。

二叉树常被用于实现二叉查找树和二叉堆。

基本概念:
二叉树是递归定义的,其结点有左右子树之分,逻辑上二叉树有五种基本形态:
1、空二叉树

2、只有一个根节点的二叉树

3、只有左子树

4、只有右子树

5、完全二叉树

注意:尽管二叉树与树有许多相似之处,但二叉树不是树的特殊情况

二叉树的特性:
1、在非空二叉树中,第i层的结点总数不超过 ,i>=1;

2、深度为h的二叉树最多有  个结点(h>=1),最少有h个结点;

3、对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,则N0=N2+1;

4、具有n个结点的完全二叉树的深度为  

5、有N个结点的完全二叉树各结点如果用顺序方式存储,则结点之间有如下关系:

若I为结点编号则 如果I>1,则其父结点的编号为I/2;
如果2*I<=N,则其左孩子(即左子树的根结点)的编号为2*I;若2*I>N,则无左孩子;
如果2*I+1<=N,则其右孩子的结点编号为2*I+1;若2*I+1>N,则无右孩子。
 
6、给定N个节点,能构成h(N)种不同的二叉树。
h(N)为卡特兰数的第N项。h(n)=C(2*n,n)/(n+1)。
 
(7)设有i个枝点,I为所有枝点的道路长度总和,J为叶的道路长度总和J=I+2i
存储结构:
顺序存储方式
typenode=record
data:datatype
l,r:integer;
end;
vartr:array[1..n]ofnode;

 链表存储方式

typebtree=^node;
node=record
data:datatye;
lchild,rchild:btree;
end;

 二叉树的遍历

遍历是对树的一种最基本的运算,所谓遍历二叉树,就是按一定的规则和顺序走遍二叉树的所有结点,使每一个结点都被访问一次,而且只被访问一次,由于二叉树是非线性结构,因此,树的遍历实质上是将二叉树的各个结点转换成为一个线性序列来表示。

设L、D、R分别表示遍历左子树、访问根结点和遍历右子树, 则对一棵二叉树的遍历有三种情况:DLR(称为先根次序遍历),LDR(称为中根次序遍历),LRD (称为后根次序遍历)。

java实现

public class DoubleTree {

private Node root;
private List<Node> list = new ArrayList<Node>();
public DoubleTree() {
  init();
}
	
private void init() {
  Node x=new Node("X",null,null);
  Node y=new Node("Y",null,null);
  Node d=new Node("d",x,y);
  Node e=new Node("e",null,null
  Node f=new Node("f",null,null);   Node c=new Node("c",e,f);   Node b=new Node("b",d,null);   Node a=new Node("a",b,c);
  root =a;
} private class Node{ private String data; private Node lchid; private Node rchid; public Node(String data, Node lchid, Node rchid) {   this.data = data;   this.lchid = lchid;   this.rchid = rchid;   } }

 先序遍历  【根左右】

list.add(node);
if(node.lchid != null) {
  preOrder(node.lchid);
}
if(node.rchid != null) {
  preOrder(node.rchid);
}

 中序遍历【左根右】

public void inOrder(Node node) {
  if(node.lchid!=null){
  inOrder(node.lchid); //left
}
list.add(node); //root
if(node.rchid!=null){
  inOrder(node.rchid); //right
}
}
            

 后续遍历配【左右根】

public void postOrder(Node node) {
if(node.lchid!=null){
  postOrder(node.lchid);
}
if(node.rchid!=null){
  postOrder(node.rchid);
}
list.add(node);
}

层次遍历

即按照层次访问,通常用队列来做。访问根,访问子女,再访问子女的子女(越往后的层次越低)(两个子女的级别相同)

public int getTreeDepth(Node node) {

if(node.lchid == null && node.rchid == null)
{
  return 1;
}
int left=0,right = 0;
if(node.lchid!=null)
{
  left = getTreeDepth(node.lchid);
}
if(node.rchid!=null)
{
  right = getTreeDepth(node.rchid);
}
return left>right?left+1:right+1;
}
//得到遍历结果
public List<Node> getResult(){
  return list;
}

 测试类

public static void main(String[] args) {
  DoubleTree tree=new DoubleTree();
  System.out.println("根节点是:"+tree.root.data);
  tree.postOrder(tree.root);
  for(Node node:tree.getResult()){
    System.out.print(node.data+" ");
  }
  System.out.println();   System.out.println("树的深度是"+tree.getTreeDepth(tree.root)); }

根节点是:a
X Y d b e f c a
树的深度是:4

二叉树是一个相当重要的数据结构,它的应用面非常广,并且由他改进生成了很多重要的树类数据结构,如红黑树,堆等,应用价值之高后面深入学习便有体会,因此,掌握它的基本特征和遍历方式实现是学好后续数据结构的基础,理论方面其实我们看到二叉树的形状,我们自己画图都能总结出来,但是代码实现这一块,初学者不是很好理解,树的遍历利用了递归的思想,递归的思想本质无非就是循环,方法调方法,所以,理解二叉树遍历的代码实现最好的方式就是按照它的遍历思想自己画出图来一步一步的遍历一遍,先把这个遍历过程想明白了,然后再根据递归的思想,什么时候调什么样的方法,自然就能很容易想明白了。

 

posted @ 2018-10-22 11:13  提拉没有米苏  阅读(867)  评论(0编辑  收藏  举报