是否需要构造函数来初始化静态变量?
is constructor required to initialize a static variable?
我有以下 java 代码用于在二叉搜索树中插入和删除。但这是我第一次尝试 java,在我可以 google 概念之前,我想寻求某些事情的帮助。
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;
}
}
我有两个问题如下
- 拥有根有意义吗,(这是一个静态变量)
在构造函数中初始化为 null?这么想,因为,
无论创建了多少对象,都只有 root(因为 root
是静态的),那么,为什么需要在构造函数中声明
每次创建新对象时都会调用它。
- 为什么需要构造函数?我们不能 declare/initialize
创建时的所有变量,如下
public class BinarySearchTree {
public static Node root = null;
...
}
有一个static
成员变量意味着它属于class本身,而不是某个特定的成员。换句话说,它在所有实例之间共享。现在我们明白了,很清楚为什么拥有 static
根成员是一个有问题的设计 - 它不允许您拥有两棵断开连接的树,因为它们都共享同一个根节点。
如果这确实是您想要的,root
绝对应该内联初始化 (private static Node root = null;
) 而不是在构造函数中。在构造函数中具有此逻辑意味着每次创建新树时 all 现有树将失去其根。
必须仔细考虑静态成员的使用,因为正如您正确指出的那样,您创建的 BinarySearchTree
的所有实例总是相同的实例。出于这个原因,在您的代码中,每次创建新实例时 root
都会重置为 null。所以不要这样做。
您实际上可以按照您的建议在您定义的地方初始化 root
。
不过,最好通过删除 static
关键字使 root
成为 BinarySearchTree
的成员,或者将树的数据结构与搜索分开算法。然后将 root
元素作为参数传递给方法。
从数据的角度考虑整个事情 - 您要搜索的树,由它的根节点表示 - 以及对数据进行操作的服务。服务不应与数据紧密相关:您应该能够使用相同的服务来处理不同的输入数据集。
我有以下 java 代码用于在二叉搜索树中插入和删除。但这是我第一次尝试 java,在我可以 google 概念之前,我想寻求某些事情的帮助。
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;
}
}
我有两个问题如下
- 拥有根有意义吗,(这是一个静态变量) 在构造函数中初始化为 null?这么想,因为, 无论创建了多少对象,都只有 root(因为 root 是静态的),那么,为什么需要在构造函数中声明 每次创建新对象时都会调用它。
- 为什么需要构造函数?我们不能 declare/initialize 创建时的所有变量,如下
public class BinarySearchTree {
public static Node root = null;
...
}
有一个static
成员变量意味着它属于class本身,而不是某个特定的成员。换句话说,它在所有实例之间共享。现在我们明白了,很清楚为什么拥有 static
根成员是一个有问题的设计 - 它不允许您拥有两棵断开连接的树,因为它们都共享同一个根节点。
如果这确实是您想要的,root
绝对应该内联初始化 (private static Node root = null;
) 而不是在构造函数中。在构造函数中具有此逻辑意味着每次创建新树时 all 现有树将失去其根。
必须仔细考虑静态成员的使用,因为正如您正确指出的那样,您创建的
BinarySearchTree
的所有实例总是相同的实例。出于这个原因,在您的代码中,每次创建新实例时root
都会重置为 null。所以不要这样做。您实际上可以按照您的建议在您定义的地方初始化
root
。
不过,最好通过删除 static
关键字使 root
成为 BinarySearchTree
的成员,或者将树的数据结构与搜索分开算法。然后将 root
元素作为参数传递给方法。
从数据的角度考虑整个事情 - 您要搜索的树,由它的根节点表示 - 以及对数据进行操作的服务。服务不应与数据紧密相关:您应该能够使用相同的服务来处理不同的输入数据集。