存储在随机访问中的Int二进制搜索树removeOne并删除所有不正确的

时间:2017-10-07 19:17:40

标签: java binary-search-tree randomaccessfile

所以这是我的代码。除removeOneremoveAll之外,所有方法都有效。 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;
    }

0 个答案:

没有答案