所以这是我的代码。除removeOne
和removeAll
之外,所有方法都有效。 RemoveOne
递减计数为1,removeAll
应删除整个计数。我认为问题在于我的替换方法,但我无法找到它。有三种情况可能会删除没有子节点的节点,删除包含1个子节点的节点并删除具有2个子节点的节点。删除方法中的代码应该符合我的知识,这就是为什么我认为我的替换方法没有做它应该做的事情。此外,当插入新节点时,其中有一个空闲列表,并且所采用的节点位于列表的前面,由free表示(这由addFree完成)。如果删除了一个节点,则需要将其添加到列表的前面,这由addFree完成。
import java.io.*;
import java.util.*;
public class BinarySearchTree {
/*
*Implements a binary search tree of ints stored in a random access file.
*Duplicates are recorded by a count field associated with the int
*/
final int CREATE = 0;
final int REUSE = 1;
private RandomAccessFile f;
long root;//address of root node in file
long free;//address of first node in free list in file
private class Node{
private long left;
private int data;
private int count;
private long right;
private Node(long l, int d, long r){
//constructor for a new node
left = l;
data = d;
right = r;
count = 1;
}
private Node(long addr) throws IOException{
//constructor for node that exists and is stored in the file
f.seek(addr);
data = f.readInt();
count = f.readInt();
left = f.readLong();
right = f.readLong();
}
private void writeNode (long addr) throws IOException{
//writes the node to the file at location addr
f.seek(addr);
f.writeInt(data);
f.writeInt(count);
f.writeLong(left);
f.writeLong(right);
}
}
public BinarySearchTree(String fname, int mode) throws IOException {
//if mode is CREATE a new empty file is created
//if mode is CREATE and a file with file name fname exists the file with fname must be
//deleted before the the new empty file is created
//if mode is REUSE an existing file is used if it exists otherwise a new empty file
//is created
File path = new File(fname);
if (path.exists() && mode == 0) {
path.delete();
}
f = new RandomAccessFile(path, "rw");
if (mode == 0) {
root = 0;
free = 0;
f.writeLong(root);
f.writeLong(free);
}
else {
f.seek(0);
root = f.readLong();
free = f.readLong();
}
}
public void insert(int d) throws IOException {
//insert d into the tree
//if d is in the tree increment the count field associated with d
root = insert(root, d);
}
private long insert(long x, int d) throws IOException{
//recursive helper for insert
if(x == 0){
long addr = getFree();
Node newNode = new Node(0,d,0);
newNode.writeNode(addr);
return addr;
}
Node temp = new Node (x);
if (temp.data > d){
temp.left = insert(temp.left,d);
temp.writeNode(x);
}
else if (temp.data < d){
temp.right = insert(temp.right,d);
temp.writeNode(x);
}
else {
temp.count++;
temp.writeNode(x);
}
return x;
}
public long getFree() throws IOException{
if(free == 0){
return f.length();
}
else{
f.seek(free);
long tempFree = free;
long nextVal = f.readLong();
free = nextVal;
return tempFree;
}
}
public void removeOne(int d) throws IOException {
//remove one copy of d from the tree
//if the copy is the last copy remove d from the tree
//if d is not in the tree the method has no effect
removeOne(root,d);
}
private long removeOne(long x, int d) throws IOException{
//Recursive helper method
if(x == 0){
return 0;
}
Node retVal = new Node(x);
if(retVal.data == d)
retVal.count--;
if (retVal.count == 0){
if (retVal.left == 0){
addFree(x);
x = retVal.right;
} else if (retVal.right == 0) {
addFree(x);
x = retVal.left;
} else {
retVal.left = replace( retVal.left,x) ;
}
} else if(retVal.data > d){
retVal.left = removeOne(retVal.left,d);
retVal.writeNode(x);
} else {
retVal.right = removeOne(retVal.right,d);
retVal.writeNode(x);
}
return x;
}
private long replace(long r, long x) throws IOException {
//Move left once then right to find largest
Node temp = new Node(r);
if (temp.right != 0) {
temp.writeNode(r);
temp.right = replace(temp.right, x);
return r;
}
else{
Node temp2 = new Node(x);
temp2.data = temp.data;
temp2.count = temp.count;
temp2.left = temp.left;
temp2.writeNode(x);
return temp.left;
}
}
public void addFree(long x) throws IOException {
// seek to addr
// write what free was
// update new val of free
f.seek(x);
f.writeLong(free);
free = x;
}
public void removeAll(int d) throws IOException {
//remove d from the tree
//if d is not in the tree the method has no effect
removeAll(root,d);
}
private long removeAll(long x, int d) throws IOException{
if(x == 0){
return 0;
}
Node retVal = new Node(x);
if(retVal.data == d)
retVal.count = 0;
if (retVal.count == 0){
if (retVal.left == 0) {
x = retVal.right;
addFree(x);
} else if (retVal.right == 0){
x = retVal.left;
addFree(x);
} else {
retVal.left = replace(retVal.left, x);
}
} else if(retVal.data > d){
retVal.left = removeOne(retVal.left,d);
retVal.writeNode(x);
}
else {
retVal.right = removeOne(retVal.right,d);
retVal.writeNode(x);
}
return x;
}