美文网首页
数据结构-二叉树

数据结构-二叉树

作者: 半个橙子 | 来源:发表于2018-11-28 12:13 被阅读0次

    性质

    1. 在二叉树的第i层上至多有2i-1个结点(i>=1)。
    2. 深度为k的二叉树至多有2k-1个结点(k>=1)。
    3. 对任何一颗二叉树T,如果其终端结点数为n0,度为2的 结点 数为n2,则n0 = n2+1.
    4. 具有n个结点的完全二叉树深度为[log2n]+1 ([x]表示不 大于 x的最大整数)。
    5. 如果对一颗有n个结点的完全二叉树(其深度为[log2n]+1) 的结点按层序编号(从第1层到第[log2n]+1层,每层从左到 右),对任意一个结点i(1<=i<=n)有:
      1).如果i=1,则结点i是二叉树的根,无双亲;如果i>1,则其双亲是结 点[i/2]
      2).如果2i>n,则结点i无左孩子(结点i为叶子结点);否则其左孩 子是结点2i。
      3).如果2i+1>n,则结点i无右孩子;否则其右孩子是结点2i+1。

    节点

     public class TreeNode<T>{
            public TreeNode leftChild;
            public TreeNode rightChild;
            public Integer index;
            public T data;
            public TreeNode( T data) {
                this.data = data;
            }
            public TreeNode(Integer index, T data) {
                this.index = index;
                this.data = data;
            }
    
            @Override
            public String toString() {
                return "TreeNode{" +
                        "leftChild=" + leftChild +
                        ", rightChild=" + rightChild +
                        ", index=" + index +
                        ", data=" + data +
                        '}';
            }
        }
    

    二叉树建立

    • 手动直接建立
      /**
         * 构建二叉树
         *           A
         *     B         C
         * D      E         F
         */
        public void createBinaryTree(){
            System.out.println("           A");
            System.out.println("       /      \\");
            System.out.println("      B         C");
            System.out.println("    /   \\       \\");
            System.out.println(" D      E         F");
            TreeNode<String> nodeA = new TreeNode<String>(1, "A");
            this.rootNode = nodeA;
            TreeNode<String> nodeB = new TreeNode<String>(2, "B");
            TreeNode<String> nodeC = new TreeNode<String>(3, "C");
            TreeNode<String> nodeD = new TreeNode<String>(4, "D");
            TreeNode<String> nodeE = new TreeNode<String>(5, "E");
            TreeNode<String> nodeF = new TreeNode<String>(7, "F");
            nodeA.leftChild = nodeB;
            nodeA.rightChild = nodeC;
            nodeB.leftChild = nodeD;
            nodeB.rightChild = nodeE;
            nodeC.rightChild = nodeF;
            //nodeF.rightChild = new TreeNode(8,"G");
        }
    
    • 前序遍历反向生成二叉树
        /**
         * 前序遍历反向生成二叉树
         * ABD##E##C#F
         */
        public TreeNode createBinaryTree(AtomicInteger dataIndex,T[] datas){
            if (dataIndex.get()>=datas.length||"#".equals(datas[dataIndex.get()])){
                return null;
            }
            TreeNode treeNode =  new TreeNode(dataIndex.get(), datas[dataIndex.get()]);
            if (this.rootNode == null){
                this.rootNode = treeNode;
            }
            dataIndex.incrementAndGet();
            treeNode.leftChild = createBinaryTree(dataIndex, datas);
            dataIndex.incrementAndGet();
            treeNode.rightChild = createBinaryTree(dataIndex, datas);
            return treeNode;
        }
    

    二叉树遍历

    • 前序遍历
        /**
         * 前序遍历 根 左 右
         */
        public void preOrder(TreeNode currNode){
            if (currNode==null)
                return;
            System.out.println(currNode.data);
            preOrder(currNode.leftChild);
            preOrder(currNode.rightChild);
        }
    
    • 中序遍历
     /**
         *
         * 中序遍历 左 根 右
         */
        public void midOrder(TreeNode currNode){
            if (currNode == null)
                return;
            midOrder(currNode.leftChild);
            System.out.println(currNode.data);
            midOrder(currNode.rightChild);
        }
    
    
    • 后序遍历
        /**
         * 后序遍历 左 右 根
         */
        public void afterOrder(TreeNode currNode){
            if (currNode==null)
                return;
            afterOrder(currNode.leftChild);
            afterOrder(currNode.rightChild);
            System.out.println(currNode.data);
        }
    
    • 非递归形式前序遍历
    
        /**
         * 非递归形式树的前中后序遍历
         */
        public void preNoneCycle(TreeNode currNode){
            Stack<TreeNode> treeNodeStack = new Stack<TreeNode>();
            treeNodeStack.push(currNode);
            while (!treeNodeStack.isEmpty()){
                TreeNode tempNode = treeNodeStack.pop();
                if (tempNode!=null)
                    System.out.println(tempNode.data);
                if (tempNode.rightChild !=null)
                    treeNodeStack.push(tempNode.rightChild);
                if (tempNode.leftChild !=null)
                    treeNodeStack.push(tempNode.leftChild);
            }
    
        }
    
    • 非递归遍历
    /**
         * 非递归中序遍历
         * @param currNode
         */
        public void midNoneCycle(TreeNode currNode){
            Stack<TreeNode> treeNodeStack = new Stack<TreeNode>();
            while (currNode != null || !treeNodeStack.isEmpty()) {
                // 一直循环到二叉排序树最左端的叶子结点(currentNode是null)
                while (currNode != null) {
                    treeNodeStack.push(currNode);
                    currNode = currNode.leftChild;
                }
                currNode = treeNodeStack.pop();
                System.out.println(currNode.data);
                currNode = currNode.rightChild;
            }
        }
    
        /**
         * 非递归后序遍历
         * @param currNode
         */
        public void afterNoneCycle(TreeNode currNode){
            LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
            TreeNode currentNode = currNode;
            TreeNode rightNode = null;
            while (currentNode != null || !stack.isEmpty()) {
                // 一直循环到二叉排序树最左端的叶子结点(currentNode是null)
                while (currentNode != null) {
                    stack.push(currentNode);
                    currentNode = currentNode.leftChild;
                }
                currentNode = stack.pop();
                // 当前结点没有右结点或上一个结点(已经输出的结点)是当前结点的右结点,则输出当前结点
                while (currentNode.rightChild == null || currentNode.rightChild == rightNode) {
                    System.out.print(currentNode.data + " ");
                    rightNode = currentNode;
                    if (stack.isEmpty()) {
                        return; //root以输出,则遍历结束
                    }
                    currentNode = stack.pop();
                }
                stack.push(currentNode); //还有右结点没有遍历
                currentNode = currentNode.rightChild;
            }
        }
    
    • 广度优先遍历
        /** 
         * 广度优先遍历二叉树,又称层次遍历二叉树 
         * @param node 
         */  
        public void breadthFirstTraverse(Node<E> root) {  
            Queue<Node<E>> queue = new LinkedList<Node<E>>();  
            Node<E> currentNode = null;  
            queue.offer(root);  
            while (!queue.isEmpty()) {  
                currentNode = queue.poll();  
                System.out.print(currentNode.value + " ");  
                if (currentNode.left != null)  
                    queue.offer(currentNode.left);  
                if (currentNode.right != null)  
                    queue.offer(currentNode.right);  
            }  
        }  
    

    二叉树高度

        public int getHeight(){
            return getHeight(this.rootNode);
        }
        public int getHeight(TreeNode currNode){
            if (currNode==null){
                return 0;
            }
            int lHeight = getHeight(currNode.leftChild);
            int rHeight = getHeight(currNode.rightChild);
            return Math.max(lHeight,rHeight)+1;
        }
    

    二叉树节点数量

     public int getSize(){
            return getSize(this.rootNode);
        }
        public int getSize(TreeNode currNode){
            if (currNode==null){
                return 0;
            }
            int lSize = getSize(currNode.leftChild);
            int rSize = getSize(currNode.rightChild);
            return lSize + rSize + 1;
        }
    
    

    测试代码

    package com.execlib;
    
    import java.util.Stack;
    import java.util.concurrent.atomic.AtomicInteger;
    
    public class BinaryTreeTree<T> {
        public TreeNode rootNode = null;
        /**
         * 树的建立
         */
        public class TreeNode<T>{
            public TreeNode leftChild;
            public TreeNode rightChild;
            public Integer index;
            public T data;
            public TreeNode( T data) {
                this.data = data;
            }
            public TreeNode(Integer index, T data) {
                this.index = index;
                this.data = data;
            }
    
            @Override
            public String toString() {
                return "TreeNode{" +
                        "leftChild=" + leftChild +
                        ", rightChild=" + rightChild +
                        ", index=" + index +
                        ", data=" + data +
                        '}';
            }
        }
        /**
         * 构建二叉树
         *           A
         *     B         C
         * D      E         F
         */
        public void createBinaryTree(){
            System.out.println("           A");
            System.out.println("       /      \\");
            System.out.println("      B         C");
            System.out.println("    /   \\       \\");
            System.out.println(" D      E         F");
            TreeNode<String> nodeA = new TreeNode<String>(1, "A");
            this.rootNode = nodeA;
            TreeNode<String> nodeB = new TreeNode<String>(2, "B");
            TreeNode<String> nodeC = new TreeNode<String>(3, "C");
            TreeNode<String> nodeD = new TreeNode<String>(4, "D");
            TreeNode<String> nodeE = new TreeNode<String>(5, "E");
            TreeNode<String> nodeF = new TreeNode<String>(7, "F");
            nodeA.leftChild = nodeB;
            nodeA.rightChild = nodeC;
            nodeB.leftChild = nodeD;
            nodeB.rightChild = nodeE;
            nodeC.rightChild = nodeF;
            //nodeF.rightChild = new TreeNode(8,"G");
        }
    
        /**
         * 前序遍历反向生成二叉树
         * ABD##E##C#F
         */
        public TreeNode createBinaryTree(AtomicInteger dataIndex,T[] datas){
            if (dataIndex.get()>=datas.length||"#".equals(datas[dataIndex.get()])){
                return null;
            }
            TreeNode treeNode =  new TreeNode(dataIndex.get(), datas[dataIndex.get()]);
            if (this.rootNode == null){
                this.rootNode = treeNode;
            }
            dataIndex.incrementAndGet();
            treeNode.leftChild = createBinaryTree(dataIndex, datas);
            dataIndex.incrementAndGet();
            treeNode.rightChild = createBinaryTree(dataIndex, datas);
            return treeNode;
        }
    
    
        /**
         * 递归形式树的前中后序遍历
         */
    
        /**
         * 前序遍历 根 左 右
         */
        public void preOrder(TreeNode currNode){
            if (currNode==null)
                return;
            System.out.println(currNode.data);
            preOrder(currNode.leftChild);
            preOrder(currNode.rightChild);
        }
    
        /**
         *
         * 中序遍历 左 根 右
         */
        public void midOrder(TreeNode currNode){
            if (currNode == null)
                return;
            midOrder(currNode.leftChild);
            System.out.println(currNode.data);
            midOrder(currNode.rightChild);
        }
    
        /**
         * 后序遍历 左 右 根
         */
        public void afterOrder(TreeNode currNode){
            if (currNode==null)
                return;
            afterOrder(currNode.leftChild);
            afterOrder(currNode.rightChild);
            System.out.println(currNode.data);
        }
    
    
    
        /**
         * 非递归形式树的前中后序遍历
         */
        public void preNoneCycle(TreeNode currNode){
            Stack<TreeNode> treeNodeStack = new Stack<TreeNode>();
            treeNodeStack.push(currNode);
            while (!treeNodeStack.isEmpty()){
                TreeNode tempNode = treeNodeStack.pop();
                if (tempNode!=null)
                    System.out.println(tempNode.data);
                if (tempNode.rightChild !=null)
                    treeNodeStack.push(tempNode.rightChild);
                if (tempNode.leftChild !=null)
                    treeNodeStack.push(tempNode.leftChild);
            }
    
        }
        public int getSize(){
            return getSize(this.rootNode);
        }
        public int getSize(TreeNode currNode){
            if (currNode==null){
                return 0;
            }
            int lSize = getSize(currNode.leftChild);
            int rSize = getSize(currNode.rightChild);
            return lSize + rSize + 1;
        }
    
        public int getHeight(){
            return getHeight(this.rootNode);
        }
        public int getHeight(TreeNode currNode){
            if (currNode==null){
                return 0;
            }
            int lHeight = getHeight(currNode.leftChild);
            int rHeight = getHeight(currNode.rightChild);
            return Math.max(lHeight,rHeight)+1;
        }
    
    
        public static void main(String[] args) {
            BinaryTreeTree<String> testTree = new BinaryTreeTree<String>();
            testTree.createBinaryTree();
            System.out.println("---------------");
            int height = testTree.getHeight();
            System.out.println("tree height :"+height);
            int size = testTree.getSize();
            System.out.println("tree size :"+size);
            System.out.println("---------------");
            System.out.println("tree preOrder :");
            testTree.preOrder(testTree.rootNode);
            System.out.println("tree midOrder :");
            testTree.midOrder(testTree.rootNode);
            System.out.println("tree afterOrder :");
            testTree.afterOrder(testTree.rootNode);
            System.out.println("tree preNoneCycle :");
            testTree.preNoneCycle(testTree.rootNode);
    
            System.out.println("create tree :");
            testTree.preOrder(testTree.createBinaryTree(new AtomicInteger(0),new String[]{"A","B","D","#","#","E","#","#","C","#","F"}));
        }
    }
    
    
              A
           /      \
          B         C
        /   \       \
     D      E         F
    ---------------
    tree height :3
    tree size :6
    ---------------
    tree preOrder :
    A
    B
    D
    E
    C
    F
    tree midOrder :
    D
    B
    E
    A
    C
    F
    tree afterOrder :
    D
    E
    B
    F
    C
    A
    tree preNoneCycle :
    A
    B
    D
    E
    C
    F
    create tree :
    A
    B
    D
    E
    C
    F
    

    查找二叉树

    节点
        public class SearchNode<T> extends TreeNode<T>{
            public SearchNode parent;
            public SearchNode(T data) {
                super(data);
            }
    
            public SearchNode(Integer index, T data) {
                super(index, data);
            }
        }
    
    加入节点
     /**
         * 二叉树存放节点
         * @param data
         * @return
         */
        public TreeNode put(int data){
            SearchNode<Integer> newNode = new SearchNode<Integer>(data);
            if (this.rootNode == null){
                rootNode = newNode;
                return newNode;
            }
            TreeNode<Integer> node = (SearchNode<Integer>) rootNode;
            TreeNode<Integer> parent = null;
            while (node!=null){
                parent = node;
               if (data<node.data){
                   node = node.leftChild;
               }else if (data>node.data){
                   node = node.rightChild;
               }else {
                   return node;
               }
            }
            if (parent.data>data)
                parent.leftChild =  newNode;
            else parent.rightChild = newNode;
            ((SearchNode)newNode).parent = (SearchNode) parent;
            return newNode;
        }
    
    查找数据
       /**
         * 查找数据
         * @param data
         * @return
         */
        public TreeNode search(int data){
            TreeNode<Integer> node = rootNode;
            while (node!=null){
                if (data<node.data){
                    node = node.leftChild;
                }else if (data>node.data){
                    node = node.rightChild;
                }else {
                    return node;
                }
            }
            return null;
        }
    
    删除数据
    /**
         * 删除数据并调整节点顺序
         * @param data
         * @return
         */
        public TreeNode delete(int data){
            SearchNode node = (SearchNode) search(data);
            if (node == null)
                return null;
            return delete(node);
        }
    
        /**
         * 删除节点
         * @param node
         * @return
         */
        private SearchNode delete(SearchNode node) {
            //没有左右孩子直接删除
            if (node.leftChild==null&&node.rightChild==null){
                SearchNode parent = node.parent;
                if (parent.leftChild==node){
                    parent.leftChild = null;
                }else {
                    parent.rightChild = null;
                }
                return node;
            }
            //只有左孩子
            if (node.leftChild!=null&&node.rightChild==null){
                SearchNode next = (SearchNode) node.leftChild;
                SearchNode parent = node.parent;
                if (parent.leftChild==node){
                    parent.leftChild = next;
                }else {
                    parent.rightChild = next;
                }
                return node;
            }
            //只有右孩子
            if (node.leftChild==null&&node.rightChild!=null){
                SearchNode next = (SearchNode) node.rightChild;
                SearchNode parent = node.parent;
                if (parent.leftChild==node){
                    parent.leftChild = next;
                }else {
                    parent.rightChild = next;
                }
                return node;
            }
            //有左右孩子 获取后继节点并删除后继然后将后继的值赋值给当前节点
            SearchNode nextNode = getNextNode(node);
            delete(nextNode);
            node.data = nextNode.data;
            return node;
        }
    
        /**
         * 获取某节点的后继节点
         * @param node
         * @return
         */
        private SearchNode getNextNode(SearchNode node) {
            //当前节点有右孩子
            if (node.rightChild!=null){
                node = (SearchNode) node.rightChild;
                while (node.leftChild!=null){
                    node = (SearchNode) node.leftChild;
                }
                return node;
            }
            //当前节点没有右孩子
            SearchNode parent = node.parent;
            while (parent!=null&&node==parent.rightChild){
                node = parent;
                parent = parent.parent;
            }
            return parent;
        }
    
    完整代码
    package com.execlib;
    
    public class BinarySearchTree extends BinaryTreeTree<Integer>{
    
        public class SearchNode<T> extends TreeNode<T>{
            public SearchNode parent;
            public SearchNode(T data) {
                super(data);
            }
    
            public SearchNode(Integer index, T data) {
                super(index, data);
            }
        }
        /**
         * 二叉树存放节点
         * @param data
         * @return
         */
        public TreeNode put(int data){
            SearchNode<Integer> newNode = new SearchNode<Integer>(data);
            if (this.rootNode == null){
                rootNode = newNode;
                return newNode;
            }
            TreeNode<Integer> node = (SearchNode<Integer>) rootNode;
            TreeNode<Integer> parent = null;
            while (node!=null){
                parent = node;
               if (data<node.data){
                   node = node.leftChild;
               }else if (data>node.data){
                   node = node.rightChild;
               }else {
                   return node;
               }
            }
            if (parent.data>data)
                parent.leftChild =  newNode;
            else parent.rightChild = newNode;
            ((SearchNode)newNode).parent = (SearchNode) parent;
            return newNode;
        }
    
        /**
         * 查找数据
         * @param data
         * @return
         */
        public TreeNode search(int data){
            TreeNode<Integer> node = rootNode;
            while (node!=null){
                if (data<node.data){
                    node = node.leftChild;
                }else if (data>node.data){
                    node = node.rightChild;
                }else {
                    return node;
                }
            }
            return null;
        }
    
        /**
         * 删除数据并调整节点顺序
         * @param data
         * @return
         */
        public TreeNode delete(int data){
            SearchNode node = (SearchNode) search(data);
            if (node == null)
                return null;
            return delete(node);
        }
    
        /**
         * 删除节点
         * @param node
         * @return
         */
        private SearchNode delete(SearchNode node) {
            //没有左右孩子直接删除
            if (node.leftChild==null&&node.rightChild==null){
                SearchNode parent = node.parent;
                if (parent.leftChild==node){
                    parent.leftChild = null;
                }else {
                    parent.rightChild = null;
                }
                return node;
            }
            //只有左孩子
            if (node.leftChild!=null&&node.rightChild==null){
                SearchNode next = (SearchNode) node.leftChild;
                SearchNode parent = node.parent;
                if (parent.leftChild==node){
                    parent.leftChild = next;
                }else {
                    parent.rightChild = next;
                }
                return node;
            }
            //只有右孩子
            if (node.leftChild==null&&node.rightChild!=null){
                SearchNode next = (SearchNode) node.rightChild;
                SearchNode parent = node.parent;
                if (parent.leftChild==node){
                    parent.leftChild = next;
                }else {
                    parent.rightChild = next;
                }
                return node;
            }
            //有左右孩子 获取后继节点并删除后继然后将后继的值赋值给当前节点
            SearchNode nextNode = getNextNode(node);
            delete(nextNode);
            node.data = nextNode.data;
            return node;
        }
    
        /**
         * 获取某节点的后继节点
         * @param node
         * @return
         */
        private SearchNode getNextNode(SearchNode node) {
            //当前节点有右孩子
            if (node.rightChild!=null){
                node = (SearchNode) node.rightChild;
                while (node.leftChild!=null){
                    node = (SearchNode) node.leftChild;
                }
                return node;
            }
            //当前节点没有右孩子
            SearchNode parent = node.parent;
            while (parent!=null&&node==parent.rightChild){
                node = parent;
                parent = parent.parent;
            }
            return parent;
        }
    
        public static void main(String[] args) {
            BinarySearchTree binarySearchTree = new BinarySearchTree();
            int[] ints = {50, 30, 20, 44, 88, 33, 87, 16, 7, 77};
            for (int i = 0; i < ints.length; i++) {
                binarySearchTree.put(ints[i]);
            }
            binarySearchTree.midOrder(binarySearchTree.rootNode);
            System.out.println("search result:"+binarySearchTree.search(88));
    
            binarySearchTree.delete(30);
            System.out.println("delete result:");
            binarySearchTree.midOrder(binarySearchTree.rootNode);
        }
    }
    
    
    测试结果
    7
    16
    20
    30
    33
    44
    50
    77
    87
    88
    search result:TreeNode{leftChild=TreeNode{leftChild=TreeNode{leftChild=null, rightChild=null, index=null, data=77}, rightChild=null, index=null, data=87}, rightChild=null, index=null, data=88}
    delete result:
    7
    16
    20
    33
    44
    50
    77
    87
    88
    

    相关文章

      网友评论

          本文标题:数据结构-二叉树

          本文链接:https://www.haomeiwen.com/subject/gdeaqqtx.html