二叉树的遍历

来源:互联网 发布:魔音变声软件 编辑:程序博客网 时间:2024/06/03 05:30

这种东西还是做个标记吧。这里引申一下:如何创建、遍历树以及操作树的某个节点,这是某公司的面试题,其实在WEBKIT的Dom & Render tree的实现中有应用到。


遍历概念

     所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问。访问结点所做的操作依赖于具体的应用问题。
     遍历是二叉树上最重要的运算之一,是二叉树上进行其它运算之基础。

遍历方案

1.遍历方案

     从二叉树的递归定义可知,一棵非空的二叉树由根结点及左、右子树这三个基本部分组成。因此,在任一给定结点上,可以按某种次序执行三个操作:
     (1)访问结点本身(N),
     (2)遍历该结点的左子树(L),
     (3)遍历该结点的右子树(R)。
以上三种操作有六种执行次序:
     NLR、LNR、LRN、NRL、RNL、RLN。
  注意:
     前三种次序与后三种次序对称,故只讨论先左后右的前三种次序。

2.三种遍历的命名
     根据访问结点操作发生位置命名:
  ① NLR:前序遍历(PreorderTraversal亦称(先序遍历))
         ——访问结点的操作发生在遍历其左右子树之前。
  ② LNR:中序遍历(InorderTraversal)
        ——访问结点的操作发生在遍历其左右子树之中(间)。
   ③ LRN:后序遍历(PostorderTraversal)
        ——访问结点的操作发生在遍历其左右子树之后。
  注意:
    
 由于被访问的结点必是某子树的根,所以N(Node)、L(Left subtlee)和R(Right subtree)又可解释为根、根的左子树和根的右子树。NLR、LNR和LRN分别又称为先根遍历、中根遍历和后根遍历。

遍历算法

1.中序遍历的递归算法定义:

     若二叉树非空,则依次执行如下操作:
         (1)遍历左子树;
         (2)访问根结点;
         (3)遍历右子树。

2.先序遍历的递归算法定义:
    若二叉树非空,则依次执行如下操作:
         (1) 访问根结点;
         (2) 遍历左子树;
         (3) 遍历右子树。

3.后序遍历得递归算法定义:
    若二叉树非空,则依次执行如下操作:
         (1)遍历左子树;
         (2)遍历右子树;
         (3)访问根结点。

4.中序遍历的算法实现
     用二叉链表做为存储结构,中序遍历算法可描述为:
      void InOrder(BinTree T)
        { //算法里①~⑥是为了说明执行过程加入的标号
          ① if(T) { // 如果二叉树非空
          ②    InOrder(T->lchild);
          ③    printf("%c",T->data); // 访问结点
          ④    InOrder(T->rchild);
          ⑤  }
          ⑥ } // InOrder


在计算机科学里,树的遍历是指通过一种方法按照一定的顺序访问一颗树的过程。

对于二叉树,树的遍历通常有四种:先序遍历、中序遍历、后序遍历、广度优先遍历。(前三种亦统称深度优先遍历)对于多叉树,树的遍历通常有两种:深度优先遍历、广度优先遍历。

目录

  [隐藏] 
  • 1 二叉树的遍历
    • 1.1 深度优先遍历
      • 1.1.1 先序遍历
      • 1.1.2 中序遍历
      • 1.1.3 后序遍历
    • 1.2 广度优先遍历
  • 2 多叉树的遍历
    • 2.1 深度优先遍历
    • 2.2 广度优先遍历
  • 3 参考资料

二叉树的遍历 [编辑]

深度优先遍历 [编辑]

以下均是用递归方法

先序遍历 [编辑]

指先访问根,然后访问孩子的遍历方式,其C代码如下:

void XXBL(tree* root){

//Do Something with root
if(root->lchild!=NULL)
XXBL(root->lchild);
if(root->rchild!=NULL)
XXBL(root->rchild);

}

中序遍历 [编辑]

指先访问左(右)孩子,然后访问根,最后访问右(左)孩子的遍历方式,其C代码如下

void ZXBL(tree* root){

if(root->lchild!=NULL)
ZXBL(root->lchild);
//Do Something with root
if(root->rchild!=NULL)
ZXBL(root->rchild);

}

后序遍历 [编辑]

指先访问孩子,然后访问根的遍历方式,其C代码如下

void HXBL(tree* root){

if(root->lchild!=NULL)
HXBL(root->lchild);
if(root->rchild!=NULL)
HXBL(root->rchild);
//Do Something with root

}

广度优先遍历 [编辑]

和深度优先遍历不同,广度优先遍历会先访问离根节点最近的节点。二叉树的广度优先遍历又称按层次遍历。算法借助队列实现。

多叉树的遍历 [编辑]

对于嵌入式系统,我们一般采用非递归算法,否则可能会发生栈溢出。
这里虽然是JAVA代码,但转为c++代码也相当的容易。
简述树的深度优先及广度优先遍历算法,并说明非递归实现。

 

当时我看到这个题目的时候,已经完全记不得非递归算法该怎么实现了,后来查阅了一下,要用到两个辅助的数据结构:

深度优先遍历--->栈;

广度优先遍历--->队列;

这里以二叉树为例来实现。

Java代码 复制代码 收藏代码
  1. import java.util.ArrayDeque;   
  2.   
  3. public class BinaryTree {   
  4.     static class TreeNode{   
  5.         int value;   
  6.         TreeNode left;   
  7.         TreeNode right;   
  8.            
  9.         public TreeNode(int value){   
  10.             this.value=value;   
  11.         }   
  12.     }   
  13.        
  14.     TreeNode root;   
  15.        
  16.     public BinaryTree(int[] array){   
  17.         root=makeBinaryTreeByArray(array,1);   
  18.     }   
  19.   
  20.       
  21.     public static TreeNode makeBinaryTreeByArray(int[] array,int index){   
  22.         if(index<array.length){   
  23.             int value=array[index];   
  24.             if(value!=0){   
  25.                 TreeNode t=new TreeNode(value);   
  26.                 array[index]=0;   
  27.                 t.left=makeBinaryTreeByArray(array,index*2);   
  28.                 t.right=makeBinaryTreeByArray(array,index*2+1);   
  29.                 return t;   
  30.             }   
  31.         }   
  32.         return null;   
  33.     }   
  34.        
  35.       
  36.     public void depthOrderTraversal(){   
  37.         if(root==null){   
  38.             System.out.println("empty tree");   
  39.             return;   
  40.                  
  41.         ArrayDeque<TreeNode> stack=new ArrayDeque<TreeNode>();   
  42.         stack.push(root);          
  43.         while(stack.isEmpty()==false){   
  44.             TreeNode node=stack.pop();   
  45.             System.out.print(node.value+   ");   
  46.             if(node.right!=null){   
  47.                 stack.push(node.right);   
  48.             }   
  49.             if(node.left!=null){   
  50.                 stack.push(node.left);   
  51.                          
  52.         }   
  53.         System.out.print("\n");   
  54.     }   
  55.   
  56.       
  57.     public void levelOrderTraversal(){   
  58.         if(root==null){   
  59.             System.out.println("empty tree");   
  60.             return;   
  61.         }   
  62.         ArrayDeque<TreeNode> queue=new ArrayDeque<TreeNode>();   
  63.         queue.add(root);   
  64.         while(queue.isEmpty()==false){   
  65.             TreeNode node=queue.remove();   
  66.             System.out.print(node.value+   ");   
  67.             if(node.left!=null){   
  68.                 queue.add(node.left);   
  69.             }   
  70.             if(node.right!=null){   
  71.                 queue.add(node.right);   
  72.             }   
  73.         }   
  74.         System.out.print("\n");   
  75.     }   
  76.        
  77.       
  78.     public static void main(String[] args) {   
  79.         int[] arr={0,13,65,5,97,25,0,37,22,0,4,28,0,0,32,0};   
  80.         BinaryTree tree=new BinaryTree(arr);   
  81.         tree.depthOrderTraversal();   
  82.         tree.levelOrderTraversal();   
  83.     }   
  84.