二叉树的各种概念以及代码操作

二叉树的各种概念以及代码操作

一、基本概念
* 每个结点最多有两棵子树,左子树和右子树,次序不可以颠倒。
性质:
1. 非空二叉树的第n层上至多有2^(n-1)个元素。
2. 深度为h的二叉树至多有2^h-1个结点。
* 满二叉树:所有终端都在同一层次,且非终端结点的度数为2。
在满二叉树中若其深度为h,则其所包含的结点数必为2^h-1。
* 完全二叉树:只有最下面的两层结点度能够小于2,并且最下面一层的结点都集中在该层最左边的若干位置的二叉树。
* 图样
http://images.cnblogs.com/cnblogs_com/niniwzw/WindowsLiveWriter/956d56030ec9_11E66/image_2.png

树的三种遍历方式

前序遍历:根节点->左子树->右子树
中序遍历:左子树->根节点->右子树
后序遍历:左子树->右子树->根节点

例如:求下面树的三种遍历

http://hi.csdn.net/attachment/201109/21/0_13166086420zyt.gif

前序遍历:abdefgc
中序遍历:debgfac
后序遍历:edgfbca

最优二叉树

  • 又名哈夫曼树,定义:给定n个权值作为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。

二叉查找树(Binary Search Tree)

  • 二叉查找树(Binary Search Tree),(又:二叉搜索树二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
  • 二叉查找树的插入:从根节点进行对比,小于根节点,在根节点左子树进行对比;大于根节点,在根节点右子树进行对比。一直重复上述过程,当找到节点为空的地方插入。
  • 二叉树的删除

    1. 被删除节点没有子树的情况,直接删除,并修改对应父节点的指针为空。
    2. 对于只有一个子树的情况,考虑将其子树作为其父节点的子树,关于是左还是右,根据被删除的节点确定。
    3. 最复杂的是有两个子数的情况,可以考虑两种方法,都是同样的思想:用被删除节点A的左子树的最右节点或者A的右子树的最左节点作为替代A的节点,并修改相应的最左或最右节点的父节点的指针,修改方法类似2 。
  • 图样
    https://img-my.csdn.net/uploads/201204/06/1333691114_6839.jpg

各种二叉树操作代码算法

    import java.util.ArrayList;
    import java.util.LinkedList;
    import java.util.List;

    /**
     * @author 高远</n>
     * 邮箱  wgyscsf@163.com</n>
     * 编写日期   2017-3-17下午2:31:24</n>
     * </n>
     */
    public class MyBinaryTreeList {
        BinaryTree root;

        // 定义二叉树
        class BinaryTree {
            BinaryTree left;
            BinaryTree right;
            int value;

            public BinaryTree(int value) {
                this.value = value;
            }

            public BinaryTree() {
                root = null;
            }
        }

        // 向二叉查找树插入数据
        boolean add(BinaryTree binaryTree,int value) {
            if (root == null) {
                root = new BinaryTree(value);
            } else {
                if (value < binaryTree.value) {
                    if (binaryTree.left == null) {
                        binaryTree.left = new BinaryTree(value);
                    } else {
                        add(binaryTree.left, value);
                    }
                } else {
                    if (binaryTree.right == null) {
                        binaryTree.right = new BinaryTree(value);
                    } else {
                        add(binaryTree.right, value);
                    }
                }
            }
            return true;
        }

        // 前序遍历
        void preScanner(BinaryTree binaryTree) {
            if (binaryTree == null)
                return;
            System.out.print(binaryTree.value + ",");
            preScanner(binaryTree.left);
            preScanner(binaryTree.right);
        }

        // 中序遍历
        void midScanner(BinaryTree binaryTree) {
            if (binaryTree == null)
                return;
            midScanner(binaryTree.left);
            System.out.print(binaryTree.value + ",");
            midScanner(binaryTree.right);
        }

        // 后序遍历
        void finScanner(BinaryTree binaryTree) {
            if (binaryTree == null)
                return;
            finScanner(binaryTree.left);
            finScanner(binaryTree.right);
            System.out.print(binaryTree.value + ",");
        }

        // 递归求树的深度
        int treeDeepByRecursion(BinaryTree binaryTree) {
            if (binaryTree == null)
                return 0;
            int leftDeep = treeDeepByRecursion(binaryTree.left);
            int rightDeep = treeDeepByRecursion(binaryTree.right);
            return leftDeep > rightDeep ? leftDeep + 1 : rightDeep + 1;
        }

        /*
         * 非递归求树的深度,思路:
         * 1.维护一个当前队列节点的长度a,在初始化一个长度为零的变量b。变量每次加一,取出一个数据,同时加入该节点的左右孩纸。当a=b,结束当前循环。
         * 2. 结束循环前维护一个深度l,深度l++。 3. 重复1,2。当队列时结束。
         */
        int treeDeepByNoRecursion(BinaryTree binaryTree) {
            if (binaryTree == null)
                return 0;
            // 维护一个队列,
            LinkedList<BinaryTree> binaryTreeList = new LinkedList<>();
            binaryTreeList.offer(binaryTree);
            int currentIndex;
            int lastIndex;
            BinaryTree currentBinaryTree;
            //深度
            int leval=0;
            //结束条件
            while(!binaryTreeList.isEmpty()){
                currentIndex=0;
                lastIndex=binaryTreeList.size();
                while (currentIndex < lastIndex) {
                    // poll取出一个元素,并从原来队列删除;peek查询第一个数据。
                    currentBinaryTree = binaryTreeList.poll();
                    currentIndex++;
                    // 以下是将下一层加入队列,在下次循环中进行计算
                    if (currentBinaryTree.left != null) {
                        binaryTreeList.offer(currentBinaryTree.left);
                    }
                    if (currentBinaryTree.right != null) {
                        binaryTreeList.offer(currentBinaryTree.right);
                    }
                }
                leval++;

            }
            return leval;

        }

        // 求树的宽度。思路和非递归求树的深度相对应。
        int treeWidth(BinaryTree binaryTree) {
            LinkedList<BinaryTree> linkedList = new LinkedList<>();
            linkedList.offer(binaryTree);
            int currentIndex;// 当前位置节点。
            int lastIndex;// 当前层最大节点的数量,即当前层树的宽度。
            BinaryTree currentBinaryTree;// 当前取出的节点。
            int maxLen = 0;// 最大层的值。
            while (!linkedList.isEmpty()) {
                currentIndex = 0;
                lastIndex = linkedList.size();
                while (currentIndex < lastIndex) {
                    currentBinaryTree = linkedList.poll();
                    currentIndex++;
                    // 以下是将下一层加入队列,在下次循环中进行计算
                    if (currentBinaryTree.left != null) {
                        linkedList.offer(currentBinaryTree.left);
                    }
                    if (currentBinaryTree.right != null) {
                        linkedList.offer(currentBinaryTree.right);
                    }
                }
                // 处理最大层的数量
                if (lastIndex > maxLen) {
                    maxLen = lastIndex;
                }
            }

            return maxLen;

        }

        // 找出二叉树的所有深度遍历路径
        ArrayList<Integer> list3 = new ArrayList<>();
        ArrayList<ArrayList<Integer>> listList3 = new ArrayList<>();

        private ArrayList<ArrayList<Integer>> getAllDeepPath(BinaryTree binaryTree) {
            if (binaryTree == null)
                return listList3;
            list3.add(binaryTree.value);
            if (binaryTree.left == null && binaryTree.right == null) {
                // 这种写法不行,原因:@param c the collection whose elements are to be placed
                // into this list
                // listList3.add(list3);
                listList3.add(new ArrayList<Integer>(list3));//
            }
            if (binaryTree.left != null)
                getAllDeepPath(binaryTree.left);
            if (binaryTree.right != null)
                getAllDeepPath(binaryTree.right);
            list3.remove(list3.size() - 1);
            return listList3;
        }

        // 在二叉树中找出和为某一值的所有路径
        List<Integer> list4 = new ArrayList<>();
        List<List<Integer>> allList4 = new ArrayList<>();
        private List<List<Integer>> getSpDeepTree(BinaryTree binaryTree, int target) {
            if (binaryTree == null)
                return allList4;
            list4.add(binaryTree.value);
            target -= binaryTree.value;
            if (target == 0 && binaryTree.left == null && binaryTree.right == null)
                allList4.add(new ArrayList<>(list4));
            if (binaryTree.left != null)
                getSpDeepTree(binaryTree.left, target);
            if (binaryTree.right != null)
                getSpDeepTree(binaryTree.right, target);

            list4.remove(list4.size() - 1);
            return allList4;
        }

        // test
        public static void main(String[] args) {
            int[] arr = new int[] { 5, 3, 4, 1, 7, 8, 2, 6, 0, 9 };
            MyBinaryTreeList binaryTreeList = new MyBinaryTreeList();
            for (int i = 0; i < arr.length; i++) {
                binaryTreeList.add(binaryTreeList.root, arr[i]);
            }
            System.out.println("前序遍历");
            binaryTreeList.preScanner(binaryTreeList.root);
            System.out.println("中序遍历");
            binaryTreeList.midScanner(binaryTreeList.root);
            System.out.println("后序遍历");
            binaryTreeList.finScanner(binaryTreeList.root);
            System.out.println();
            System.out.println("递归树的深度:"
                    + binaryTreeList.treeDeepByRecursion(binaryTreeList.root));
            System.out.println("非递归树的深度:"
                    + binaryTreeList.treeDeepByNoRecursion(binaryTreeList.root));
            System.out.println("递归树的宽度:"
                    + binaryTreeList.treeWidth(binaryTreeList.root));

            System.out.println("在二叉树中找所有路径2:");
            ArrayList<ArrayList<Integer>> findPath3 = binaryTreeList
                    .getAllDeepPath(binaryTreeList.root);
            for (List<Integer> arrayList : findPath3) {
                for (Integer integer : arrayList) {
                    System.out.print(integer + ",");
                }
                System.out.println();
            }

            System.out.println("在二叉树中找出和为某一值的所有路径2:");
            List<List<Integer>> findPath4 = binaryTreeList.getSpDeepTree(
                    binaryTreeList.root, 12);
            for (List<Integer> arrayList : findPath4) {
                for (Integer integer : arrayList) {
                    System.out.print(integer + ",");
                }
                System.out.println();
            }
        }
    }
  • 7
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值