• 二叉树的数组表示


    二叉树的数组表示:

    一、数据结构的本质

    二叉树在很多应用的地方,其实很多时候并不需要去建树。大多数学生陷入一个误区,二叉树一定要形如下面的样子。

    package tree;
    
    public class BinaryTree <T>{
    	private Node root;
    	class Node{
    		T data;
    		Node left;
    		Node right;
    		Node(T data){
    			this.data=data;
    			this.left=null;
    			this.right=null;
    		}
    	}
    	public BinaryTree(){
    		root = new Node(null);
    	}
    	/**
    	 * 各种遍历
    	 */
    }
    

      这其实在某种程度上陷入了一个误区。认为只要是树就长这样。其实树还可以这样定义。

    public class BinaryTree{
        int[] tree;
        
        /**
         * @param num 结点数
         */
        public BinaryTree(int num) {
            tree = new int[num];
        };
        /**
         * 其他方法
         */
        public ...{
            。。。
        }
    }

      有些朋友可能会奇怪。为什么树还可以这么定义呢?和书上教的并不一样啊。

      其实数据结构只是一种思维,一种思想,我们用多种方法来实现这种思想。

    二、实际应用。

      对于任何数据结构来说,没有实际应用都是纸上谈兵。

      这时,我挑选了一道题。题目选自算法竞赛入门经典。

      

    样例输入:
    4 2
    3 4
    10 1
    2 2
    8 128
    16 12345
    样例输出:
    12
    7
    512
    3
    255
    36358
    

      

     分析这道题。如果对这个题目进行建树,那我们需要写出很多很多代码,首先要定义数据结构,其次要根据数据结构定义对应的方法。

    这无疑对我们来说是很头疼的一件事。那么对于此次实现,我们应该定义 俩个规则:

    一、二叉树的俩个子节点与索引的关系

    对于索引为K的节点,其左孩子为(2*K) 右孩子为( 2*K+1)

     二、二叉树的根节点位置

    为了方便编程,我们设置根节点的索引为1 即root = Tree[1]

    然后根据此题逻辑,我们稍加思考即可写出以下代码

    package first;
    
    import java.util.Scanner;
    
    /**
     * @author GodofOrange
     * @算法竞赛入门经典:P149
     */
    public class A {
        // 树的数组 对于任何一个节点索引K
        // 索引K==0不参与此次算法
        // 其左子节点和右子节点的编号为2K和2K+1
        // Tree false=关闭 true=打开
        public static boolean[] Tree = new boolean[2 << 20 - 1];
    
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            int D = sc.nextInt();
            int I = sc.nextInt();
            int K = 0;
            // 让N个小球落下
            for (int i = 0; i < I; i++) {
                K= 1;
                while(true) {
                    //小球滑到该处 将true改成false;
                    Tree[K] = !Tree[K];
                    //如果Tree[K]=true 往左滑,否则往右滑
                    K = Tree[K] ? K*2:K*2+1;
                    if(K>(2<<D-1)-1)break;
                }
            }
            sc.close();
            System.out.println(K/2);
        }
    }

    这是运行后的结果。

    三、总结

    无论何种数据结构,都可以有很多种实现方法,不一定非得像书中定义的ADT那种格式,也不要将思想局限于此。

  • 相关阅读:
    剑指Offer_#7_重建二叉树
    剑指Offer_#6_从尾到头打印链表
    剑指Offer_#5_替换空格
    剑指Offer_#4_二维数组中的查找
    Redis详解(十三)- Redis布隆过滤器
    Redis详解(十二)- 缓存穿透、缓存击穿、缓存雪崩
    Redis详解(十一)- 过期删除策略和内存淘汰策略
    Redis详解(十)- 集群模式详解
    Redis详解(九)- 哨兵(Sentinel)模式详解
    Redis详解(八)- 主从复制
  • 原文地址:https://www.cnblogs.com/godoforange/p/10832628.html
Copyright © 2020-2023  润新知