【问题标题】:is constructor required to initialize a static variable?是否需要构造函数来初始化静态变量?
【发布时间】:2015-10-17 06:43:03
【问题描述】:

我有以下用于在二叉搜索树中插入和删除的 java 代码。但这是我第一次尝试使用 java,我想在谷歌搜索概念之前就某些事情寻求帮助。

public class BinarySearchTree {
    public static  Node root;
    public BinarySearchTree(){
        this.root = null;
    }

    public boolean find(int id){
        Node current = root;
        while(current!=null){
            if(current.data==id){
                return true;
            }else if(current.data>id){
                current = current.left;
            }else{
                current = current.right;
            }
        }
        return false;
    }

    public boolean delete(int id){
        Node parent = root;
        Node current = root;
        boolean isLeftChild = false;
        while(current.data!=id){
            parent = current;
            if(current.data>id){
                isLeftChild = true;
                current = current.left;
            }else{
                isLeftChild = false;
                current = current.right;
            }
            if(current ==null){
                return false;
            }
        }
        //if i am here that means we have found the node
        //Case 1: if node to be deleted has no children
        if(current.left==null && current.right==null){
            if(current==root){
                root = null;
            }
            if(isLeftChild ==true){
                parent.left = null;
            }else{
                parent.right = null;
            }
        }
        //Case 2 : if node to be deleted has only one child
        else if(current.right==null){
            if(current==root){
                root = current.left;
            }else if(isLeftChild){
                parent.left = current.left;
            }else{
                parent.right = current.left;
            }
        }
        else if(current.left==null){
            if(current==root){
                root = current.right;
            }else if(isLeftChild){
                parent.left = current.right;
            }else{
                parent.right = current.right;
            }
        }else if(current.left!=null && current.right!=null){

            //now we have found the minimum element in the right sub tree
            Node successor   = getSuccessor(current);
            if(current==root){
                root = successor;
            }else if(isLeftChild){
                parent.left = successor;
            }else{
                parent.right = successor;
            }           
            successor.left = current.left;
        }       
        return true;        
    }

    public Node getSuccessor(Node deleleNode){
        Node successsor =null;
        Node successsorParent =null;
        Node current = deleleNode.right;
        while(current!=null){
            successsorParent = successsor;
            successsor = current;
            current = current.left;
        }
        //check if successor has the right child, it cannot have left child for sure
        // if it does have the right child, add it to the left of successorParent.
//      successsorParent
        if(successsor!=deleleNode.right){
            successsorParent.left = successsor.right;
            successsor.right = deleleNode.right;
        }
        return successsor;
    }

    public void insert(int id){
        Node newNode = new Node(id);
        if(root==null){
            root = newNode;
            return;
        }
        Node current = root;
        Node parent = null;
        while(true){
            parent = current;
            if(id<current.data){                
                current = current.left;
                if(current==null){
                    parent.left = newNode;
                    return;
                }
            }else{
                current = current.right;
                if(current==null){
                    parent.right = newNode;
                    return;
                }
            }
        }
    }

    public void display(Node root){
        if(root!=null){
            display(root.left);
            System.out.print(" " + root.data);
            display(root.right);
        }
    }

    public static void main(String arg[]){
        BinarySearchTree b = new BinarySearchTree();
        b.insert(3);b.insert(8);
        b.insert(1);b.insert(4);b.insert(6);b.insert(2);b.insert(10);b.insert(9);
        b.insert(20);b.insert(25);b.insert(15);b.insert(16);
        System.out.println("Original Tree : ");
        b.display(b.root);      
        System.out.println("");
        System.out.println("Check whether Node with value 4 exists : " + b.find(4));
        System.out.println("Delete Node with no children (2) : " + b.delete(2));        
        b.display(root);
        System.out.println("\n Delete Node with one child (4) : " + b.delete(4));       
        b.display(root);
        System.out.println("\n Delete Node with Two children (10) : " + b.delete(10));      
        b.display(root);
    }
}

class Node{
    int data;
    Node left;
    Node right; 
    public Node(int data){
        this.data = data;
        left = null;
        right = null;
    }
}

我有两个问题如下

  1. 拥有root有意义吗(这是一个静态变量) 在构造函数中初始化为null?这么想,因为, 无论创建多少对象,都只有根(因为根 是静态的),那么,为什么要在构造函数内部声明 每次创建新对象时都会调用它。
  2. 为什么构造函数是必需的?我们不能声明/初始化吗 创建时的所有变量,如下所示


public class BinarySearchTree {
    public static  Node root = null;
    ... 
}

【问题讨论】:

  • root 根本不应该是静态的。每个树实例都有自己的根。
  • 我不确定,但是...不。用null 值初始化它。

标签: java constructor binary-search-tree static-members


【解决方案1】:

拥有static 成员变量意味着它属于类本身,而不是特定成员。换句话说,它在所有实例之间共享。现在我们明白了,很明显为什么拥有一个 static 根成员是一个有问题的设计 - 它不允许您拥有两个不连接的树,因为它们都共享同一个根节点。

如果这确实是您想要的,root 绝对应该内联初始化 (private static Node root = null;) 而不是在构造函数中。在构造函数中包含此逻辑意味着每次创建新树时所有现有树都将失去其根。

【讨论】:

    【解决方案2】:
    1. 必须仔细考虑静态成员的使用,因为正如您所说的那样,您创建的所有 BinarySearchTree 实例总是有相同的实例。因此,在您的代码中,每次创建新实例时,root 都会重置为 null。因此不要这样做。

    2. 您实际上可以按照您的建议在其中定义 root 进行初始化。

    但是,更好的做法是通过删除 static 关键字使 root 成为 BinarySearchTree 的成员,或者将树的数据结构和搜索算法分开。然后您将root 元素作为参数传递给方法。

    从数据的角度来考虑整个事情 - 您要搜索的树,由它的根节点表示 - 以及对数据进行操作的服务。服务不应以紧密的方式与数据绑定:您应该能够使用相同的服务来处理不同的输入数据集。

    【讨论】:

      猜你喜欢
      • 2017-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-14
      • 2011-02-15
      • 2013-01-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多