好的,所以我一直在研究这几天,每次我想我已经把它弄下来我开始编写代码而我到达了一个我无法弄清楚究竟是什么的点要做。
树不是递归的,所以我可以真正地遵循所有内容,直到我开始尝试修改它,因此它使用延迟删除而不是真正的删除。 (现在它将删除的节点归零)
我设法弄清楚:
我不知道的事情:
这是代码的其余部分,以便您可以看到我正在使用的内容。我真的很沮丧,因为我老老实实地理解如何完全删除节点比这个愚蠢的延迟删除实现更好。这是他们在书中教的内容!洛尔
请帮助...... :(
所以这是我的搜索方法:
public String search(E data){
Node<E> current = root;
String result = "";
while(current != null){
if(data.compareTo(current.e) < 0){
current = current.left;
}
else if (data.compareTo(current.e) > 0){
current = current.right;
}
else{
if (current.isDeleted == false){
return result += "Found node with matching data that is not deleted!";
}
else{
return result += "Found deleted data, not usable, continuing search\n";
}
}
}
return result += "Did not find non-deleted matching node!";
}
树代码(真正的删除方法在最后被注释掉,所以我可以用延迟删除替换它):
package mybinarytreeexample;
公共类MyBinaryTree&gt; {
private Node<E> root = null;
public class Node<E> {
public boolean isDeleted = false;
public E e = null;
public Node<E> left = null;
public Node<E> right = null;
}
public boolean insert(E e) {
// if empty tree, insert a new node as the root node
// and assign the elementy to it
if (root == null) {
root = new Node();
root.e = e;
return true;
}
// otherwise, binary search until a null child pointer
// is found
Node<E> parent = null;
Node<E> child = root;
while (child != null) {
if (e.compareTo(child.e) < 0) {
parent = child;
child = child.left;
} else if (e.compareTo(child.e) > 0) {
parent = child;
child = child.right;
} else {
if(child.isDeleted){
child.isDeleted = false;
return true;
}
return false;
}
}
// if e < parent.e create a new node, link it to
// the binary tree and assign the element to it
if (e.compareTo(parent.e) < 0) {
parent.left = new Node();
parent.left.e = e;
} else {
parent.right = new Node();
parent.right.e = e;
}
return true;
}
public void inorder() {
System.out.print("inorder: ");
inorder(root);
System.out.println();
}
private void inorder(Node<E> current) {
if (current != null) {
inorder(current.left);
System.out.printf("%3s", current.e);
inorder(current.right);
}
}
public void preorder() {
System.out.print("preorder: ");
preorder(root);
System.out.println();
}
private void preorder(Node<E> current) {
if (current != null) {
System.out.printf("%3s", current.e);
preorder(current.left);
preorder(current.right);
}
}
public void postorder() {
System.out.print("postorder: ");
postorder(root);
System.out.println();
}
private void postorder(Node<E> current) {
if (current != null) {
postorder(current.left);
postorder(current.right);
System.out.printf("%3s", current.e);
}
}
public String search(E data){
Node<E> current = root;
String result = "";
while(current != null){
if(data.compareTo(current.e) < 0){
current = current.left;
}
else if (data.compareTo(current.e) > 0){
current = current.right;
}
else{
if (current.isDeleted == false){
return result += "Found node with matching data that is not deleted!";
}
else{
return result += "Found deleted data, not usable, continuing search\n";
}
}
}
return result += "Did not find non-deleted matching node!";
}
public boolean delete(E e) {
}
// an iterator allows elements to be modified, but can mess with
// the order if element not written with immutable key; it is better
// to use delete to remove and delete/insert to remove or replace a
// node
public java.util.Iterator<E> iterator() {
return new PreorderIterator();
}
private class PreorderIterator implements java.util.Iterator<E> {
private java.util.LinkedList<E> ll = new java.util.LinkedList();
private java.util.Iterator<E> pit= null;
// create a LinkedList object that uses a linked list of nodes that
// contain references to the elements of the nodes of the binary tree
// in preorder
public PreorderIterator() {
buildListInPreorder(root);
pit = ll.iterator();
}
private void buildListInPreorder(Node<E> current) {
if (current != null) {
ll.add(current.e);
buildListInPreorder(current.left);
buildListInPreorder(current.right);
}
}
// check to see if their is another node in the LinkedList
@Override
public boolean hasNext() {
return pit.hasNext();
}
// reference the next node in the LinkedList and return a
// reference to the element in the node of the binary tree
@Override
public E next() {
return pit.next();
}
@Override
public void remove() {
throw new UnsupportedOperationException("NO!");
}
}
}
// binary search until found or not in list
// boolean found = false;
// Node<E> parent = null;
// Node<E> child = root;
//
// while (child != null) {
// if (e.compareTo(child.e) < 0) {
// parent = child;
// child = child.left;
// } else if (e.compareTo(child.e) > 0) {
// parent = child;
// child = child.right;
// } else {
// found = true;
// break;
// }
// }
//
//
// if (found) {
// // if root only is the only node, set root to null
// if (child == root && root.left == null && root.right == null)
// root = null;
// // if leaf, remove
// else if (child.left == null && child.right == null) {
// if (parent.left == child)
// parent.left = null;
// else
// parent.right = null;
// } else
// // if the found node is not a leaf
// // and the found node only has a right child,
// // connect the parent of the found node (the one
// // to be deleted) to the right child of the
// // found node
// if (child.left == null) {
// if (parent.left == child)
// parent.left = child.right;
// else
// parent.right = child.right;
// } else {
// // if the found node has a left child,
// // the node in the left subtree with the largest element
// // (i. e. the right most node in the left subtree)
// // takes the place of the node to be deleted
// Node<E> parentLargest = child;
// Node<E> largest = child.left;
// while (largest.right != null) {
// parentLargest = largest;
// largest = largest.right;
// }
//
// // replace the lement in the found node with the element in
// // the right most node of the left subtree
// child.e = largest.e;
//
// // if the parent of the node of the largest element in the
// // left subtree is the found node, set the left pointer of the
// // found node to point to left child of its left child
// if (parentLargest == child)
// child.left = largest.left;
// else
// // otherwise, set the right child pointer of the parent of
// // largest element in the left subtreeto point to the left
// // subtree of the node of the largest element in the left
// // subtree
// parentLargest.right = largest.left;
// }
//
// } // end if found
//
// return found;
答案 0 :(得分:1)
您的树只会根据所使用的真实空间而增长,并且永不缩小。如果您选择列表作为实现树的数据结构,而不是通常的构造Node E {V value; E right; E; left}
,这将非常有用。我稍后会再回来。
我看过许多资源,有些人说你需要做的就是设置 节点的已删除标志为true。这是否意味着我不必 在设置旗帜后担心链接?
是的,如果通过链接你的意思是node.left,node.right。删除只需将其标记为已删除即可。它不会改变任何其他内容,它不应该,因为即使x或y标记为已删除,x.CompareTo(y)
必须仍然有效
这样做是非常肤浅的合适方式吗?就像在,不要 如果标志设置为,则让方法报告找到了某些内容 即使方法确实找到了什么,也删除了?
这种方法的定义&#34;东西&#34;表示没有删除标志的节点。删除标志的任何内容都是&#34;没有&#34;对于树的用户。
我应该更改哪些方法来使用延迟删除?只有删除() 方法
当然不是。您已经自己更改了搜索方法。我们来看isEmpty()
。您应该保留已删除节点和总节点之一的计数器。如果它们相等,则树是空的。否则树不是。
您的算法中存在一个小错误。当您插入并发现已登陆已删除的节点时,您只需取消标记该节点。您还必须设置节点的值。毕竟compareTo
并不确保所有字段都严格相等,只是对象是等价的。
if(child.isDeleted){
child.isDeleted = false;
child.e = e; <---- missing
return true;
}
可能还有其他人。
旁注:
如前所述,此方法有用的一个实例是由列表支持的树(让我们说数组列表)。使用此方法,位置i处元素的子元素位于2*i+1
和2*i+2
位置。通常,当您删除带有子节点的节点p时,将该节点替换为右子树的最左侧节点q(或左子树中最右侧的节点)。在这里,您可以将p标记为已删除,并交换已删除节点的值和最左侧。 您的阵列在内存中保持不变