二叉树和面试题

来源:互联网 发布:我要投诉淘宝小二 编辑:程序博客网 时间:2024/04/30 06:38

二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。二叉树的第i层至多有2^{i-1}个结点;深度为k的二叉树至多有2^k-1个结点;对任何一棵二叉树T,如果其终端结点数为n_0,度为2的结点数为n_2,则n_0=n_2+1。

一棵深度为k,且有2^k-1个节点称之为满二叉树;深度为k,有n个节点的二叉树,当且仅当其每一个节点都与深度为k的满二叉树中,序号为1至n的节点对应时,称之为完全二叉树。


1 满二叉树和完全二叉树

满二叉树一定是完全二叉树,但是反过来就不一定。满二叉树的定义是除了叶子结点,其它结点左右孩子都有,深度为k的满二叉树,结点数就是2的k次方减1。完全二叉树是每个结点都与深度为k的满二叉树中编号从1到n一一对应。

2 树的深度

树的最大层次就是深度,比如上图,深度是3。很容易得出,深度为k的树,拥有的最大结点数是2的k次方减1。

3 树的孩子,兄弟,双亲

上图中,B,C是A的孩子,B,C之间互为兄弟,A是B,C的双亲。


笔试/面试常见的2个问题:
1、写出三种遍历方式的代码
2、给出先序、中序的结果, 给出后续的结果;(考验你是否真的理解三种排序)

public class TestClass { private static int[] array = { 1, 2, 3, 4, 5, 6, 7};      private static List<Node> nodeList = null;     private static class Node {     Node leftChild;  //左子树   Node rightChild; //右子树       int data;  //节点数据        Node(int newData) {             leftChild = null;             rightChild = null;             data = newData;         }     }     public static void createBinTree() {         nodeList = new LinkedList<Node>();         for (int nodeIndex = 0; nodeIndex < array.length; nodeIndex++) {             nodeList.add(new Node(array[nodeIndex]));         }         for (int parentIndex = 0; parentIndex < array.length / 2 - 1; parentIndex++) {             nodeList.get(parentIndex).leftChild = nodeList                     .get(parentIndex * 2 + 1);             nodeList.get(parentIndex).rightChild = nodeList                     .get(parentIndex * 2 + 2);         }         int lastParentIndex = array.length / 2 - 1;         nodeList.get(lastParentIndex).leftChild = nodeList                 .get(lastParentIndex * 2 + 1);         if (array.length % 2 == 1) {             nodeList.get(lastParentIndex).rightChild = nodeList                     .get(lastParentIndex * 2 + 2);         }     }        /**     * 先序遍历     */     public static void preOrderTraverse(Node node) {         if (node == null)             return;         System.out.print(node.data + " ");         preOrderTraverse(node.leftChild);         preOrderTraverse(node.rightChild);     }      /**     * 中序遍历     */     public static void inOrderTraverse(Node node) {         if (node == null)             return;         inOrderTraverse(node.leftChild);         System.out.print(node.data + " ");         inOrderTraverse(node.rightChild);     }      /**     * 后序遍历     */     public static void postOrderTraverse(Node node) {         if (node == null)             return;         postOrderTraverse(node.leftChild);         postOrderTraverse(node.rightChild);         System.out.print(node.data + " ");     }  public static void main(String[] args) {// TODO Auto-generated method stubcreateBinTree();         // nodeList中第0个索引处的值即为根节点          Node root = nodeList.get(0);          System.out.print("先序:");        preOrderTraverse(root);        System.out.println("");        System.out.print("中序:");        inOrderTraverse(root);        System.out.println("");        System.out.print("后序:");        postOrderTraverse(root);        }}

 输出结果:
先序:1 2 4 5 3 6 7 
中序:4 2 5 1 6 3 7 
后序:4 5 2 6 7 3 1 
面试时可能告诉你先序和中序的结果, 让你画出二叉树并写出后序排序。  
解题技巧:
 1、先序排序的第一个数据是根节点, 中序排序中根节点左边的都是左子树、右边的都是右子树。 即1是根节点, 4、2、5是左子树,6、3、7是右子树;
 2、 先序的第2个值即2是根节点左子节点;在先序里的3、6、7中第一个值是根节点的右子节点。 
 3、记住三种排序是按照根节点的读取时序定义, 先序是先访问根节点,中序是第2次访问根节点,后序是第3次访问根节点。



0 0
原创粉丝点击