简体   繁体   English

调试由AVL树支持的地图?

[英]Debugging a Map backed by an AVL tree?

This is one of three trees I am using to parse text and print out every unique word, the line numbers it appears on, and the number of times it appears. 这是我用来解析文本并打印出每个唯一单词,出现的行号以及出现的次数的三棵树之一。 I have already used a hash and tree map and have both of them working correctly. 我已经使用了哈希表和树形图,并且它们都能正常工作。 My instructor said that we need to use an AVL tree for the third map and gave us code. 我的教练说,我们需要为第三张地图使用AVL树,并提供了代码。 This is where I am unsure where to go. 这是我不确定要去的地方。 I will include the method that creates/fills the AVL map as well as the AVL map class. 我将包括用于创建/填充AVL映射以及AVL映射类的方法。 If further code is needed, I will gladly include it. 如果需要更多代码,我将很乐意将其包含在内。

    public void avlMap(String fileName){

    //try/catch block to check for invalid file name
    try{
        //creates new bufferedreader object for input file
        BufferedReader inFile = new BufferedReader(new FileReader(fileName));

        //creates new treeMap object named avlMap
        Map avlMap = new AvlMap();
        String oneLine;

        //Read the words and add them to the avlMap
        for (int lineNum = 1; (oneLine = inFile.readLine()) != null; lineNum++){
            String delims = " !@#$%{}[]/^&*,.()-;:\'\"\t";
            StringTokenizer st = new StringTokenizer(oneLine, delims);
            while (st.hasMoreTokens()){
                String word = st.nextToken();
                WordStats stats = (WordStats) avlMap.get(word);

                //if WordStats is empty/doesnt exist,
                //if exists, adds line numbers into a WordStats in the value
                //...field for the int's respective key
                if (stats == null){
                    stats = new WordStats();
                    avlMap.put(word, stats);
                }
                //WordStats already exists for the word
                //calls addOccurrence method and adds the line number
                stats.addOccurrence(new Integer(lineNum));  
            }
        }

        //creates a new iterator object to iterate entries
        Iterator itr = avlMap.entrySet().iterator();

        //runs printEntry for each key in the treeMap
        while (itr.hasNext()){
            printEntry((Map.Entry) itr.next());
        }
    }
        //the file name used wasn't able to be reached
        catch(IOException e){
            e.printStackTrace();
        }
}

AvlMap class. AvlMap类。 I know it is quite lengthy, but the methods seem to be pretty much the same as the rest of the map classes I have been using. 我知道这很长,但是方法似乎与我一直在使用的其余地图类几乎相同。

    public class AvlMap <AnyType extends Comparable<? super AnyType>> implements Map 
    {
    //construct the tree
    public AvlMap( ){
        root = null;
    }

    //inserts object into the map
    public void insert( AnyType x, AnyType y ){
        root = insert( x, y, root );
    }

    //removes the key from the map
    public void remove( AnyType x ){
        root = remove( x, root );
    }

    //internal method to remove from a subtree
    private AvlNode<AnyType> remove( AnyType x, AvlNode<AnyType> t ){
        if( t == null )
            return t;   // Item not found; do nothing

        int compareResult = x.compareTo( t.key );

        if( compareResult < 0 )
            t.left = remove( x, t.left );
        else if( compareResult > 0 )
            t.right = remove( x, t.right );
        else if( t.left != null && t.right != null ) // Two children
        {
            t.key = findMin( t.right ).key;
            t.right = remove( t.key, t.right );
        }
        else
            t = ( t.left != null ) ? t.left : t.right;
        return balance( t );
    }

    //returns the smallest item in the tree
    public AnyType findMin( ){
        if( isEmpty( ) )
            throw new UnderflowException("Error" );
        return findMin( root ).key;
    }

    //returns the largest item in the tree
    public AnyType findMax( ){
        if( isEmpty( ) )
            throw new UnderflowException("Error" );
        return findMax( root ).key;
    }

    //finds the provided item in the tree
    public boolean contains( AnyType key ){
        return contains( key, root );
    }

    //make the tree empty
    public void makeEmpty( ){
        root = null;
    }

    //tests if the tree is empty
    public boolean isEmpty( ){
        return root == null;
    }

    //prints the tree in sorted order
    public void printTree( ){
        if( isEmpty( ) )
            System.out.println( "Empty tree" );
        else
            printTree( root );
    }

    private static final int ALLOWED_IMBALANCE = 1;

    // Assume t is either balanced or within one of being balanced
    private AvlNode<AnyType> balance( AvlNode<AnyType> t )
    {
        if( t == null )
            return t;

        if( height( t.left ) - height( t.right ) > ALLOWED_IMBALANCE )
            if( height( t.left.left ) >= height( t.left.right ) )
                t = rotateWithLeftChild( t );
            else
                t = doubleWithLeftChild( t );
        else
        if( height( t.right ) - height( t.left ) > ALLOWED_IMBALANCE )
            if( height( t.right.right ) >= height( t.right.left ) )
                t = rotateWithRightChild( t );
            else
                t = doubleWithRightChild( t );

        t.height = Math.max( height( t.left ), height( t.right ) ) + 1;
        return t;
    }

    //checks the trees balance
    public void checkBalance( ){
        checkBalance( root );
    }

    //driver for checking the trees balance
    private int checkBalance( AvlNode<AnyType> t ){
        if( t == null )
            return -1;

        if( t != null )
        {
            int hl = checkBalance( t.left );
            int hr = checkBalance( t.right );
            if( Math.abs( height( t.left ) - height( t.right ) ) > 1 ||
                    height( t.left ) != hl || height( t.right ) != hr )
                System.out.println( "OOPS!!" );
        }

        return height( t );
    }

    //method to insert into a subtree
    private AvlNode<AnyType> insert( AnyType key, AnyType value, AvlNode<AnyType> t ){
        if( t == null )
            return new AvlNode<>( key, value, null, null );

        int compareResult = key.compareTo( t.key );

        if( compareResult < 0 )
            t.left = insert( key, value,t.left );
        else if( compareResult > 0 )
            t.right = insert( key, value, t.right );
        else
            ;  // Duplicate; do nothing
        return balance( t );
    }

    //returns the smallest item in a subtree
    private AvlNode<AnyType> findMin( AvlNode<AnyType> t )
    {
        if( t == null )
            return t;

        while( t.left != null )
            t = t.left;
        return t;
    }

    //finds the largest item in a subtree
    private AvlNode<AnyType> findMax( AvlNode<AnyType> t ){
        if( t == null )
            return t;

        while( t.right != null )
            t = t.right;
        return t;
    }

    //finds an item in a subtree
    private boolean contains( AnyType x, AvlNode<AnyType> t ){
        while( t != null ){
            int compareResult = x.compareTo( t.key );

            if( compareResult < 0 )
                t = t.left;
            else if( compareResult > 0 )
                t = t.right;
            else
                return true;    // Match
        }
        return false;   // No match
    }

    //prints the subtree in sorted order
    private void printTree( AvlNode<AnyType> t ){
        if( t != null ){
            printTree( t.left );
            System.out.println( t.key + " " + t.value );
            printTree( t.right );
        }    
    }

    //returns the height of node t or -1 if null
    private int height( AvlNode<AnyType> t ){
        return t == null ? -1 : t.height;
    }

    //rotates tree node with left child
    private AvlNode<AnyType> rotateWithLeftChild( AvlNode<AnyType> k2 ){
        AvlNode<AnyType> k1 = k2.left;
        k2.left = k1.right;
        k1.right = k2;
        k2.height = Math.max( height( k2.left ), height( k2.right ) ) + 1;
        k1.height = Math.max( height( k1.left ), k2.height ) + 1;
        return k1;
    }

    //rotates tree node with right child
    private AvlNode<AnyType> rotateWithRightChild( AvlNode<AnyType> k1 ){
        AvlNode<AnyType> k2 = k1.right;
        k1.right = k2.left;
        k2.left = k1;
        k1.height = Math.max( height( k1.left ), height( k1.right ) ) + 1;
        k2.height = Math.max( height( k2.right ), k1.height ) + 1;
        return k2;
    }

    //double rotates tree node.  first left child with its right child, then 
    //...node k3 with new left child.
    private AvlNode<AnyType> doubleWithLeftChild( AvlNode<AnyType> k3 ){
        k3.left = rotateWithRightChild( k3.left );
        return rotateWithLeftChild( k3 );
    }

    //double rotates tree node.  first right child with its left child, then
    //...node k1 with new right child
    private AvlNode<AnyType> doubleWithRightChild( AvlNode<AnyType> k1 ){
        k1.right = rotateWithLeftChild( k1.right );
        return rotateWithRightChild( k1 );
    }

    private static class AvlNode<AnyType>{
            // Constructors
        @SuppressWarnings("unused")
        AvlNode( AnyType theKey, AnyType theValue ){
            this( theKey, theValue, null, null );
        }

        AvlNode( AnyType theKey, AnyType theValue, AvlNode<AnyType> lt, AvlNode<AnyType> rt ){
            key  = theKey;
            value = theValue;
            left     = lt;
            right    = rt;
            height   = 0;
        }

        AnyType           key;      // The data in the node
        AnyType           value;
        AvlNode<AnyType>  left;         // Left child
        AvlNode<AnyType>  right;        // Right child
        int               height;       // Height
    }

    //trees root
    private AvlNode<AnyType> root;

    //implemented methods for AvlTreeMap
    @Override
    public void clear() {
        makeEmpty();    
    }

    @SuppressWarnings("unchecked")
    @Override
    public boolean containsKey(Object key) {
        contains ((AnyType)key);

        return false;
    }

    @SuppressWarnings("unchecked")
    @Override
    public boolean containsValue(Object value) {
        contains ((AnyType)value);
        return false;
    }

    @Override
    public Set entrySet() {
        return null;
    }

    @Override
    public Object get(Object key) {
        return key;
    }

    @Override
    public Set keySet() {
        return null;
    }

    @SuppressWarnings("unchecked")
    @Override
    public Object put(Object key, Object value) {
        insert ((AnyType)key, (AnyType) value);

        return true;
    }

    @Override
    public void putAll(Map m) {
    }

    @SuppressWarnings("unchecked")
    @Override
    public Object remove(Object key) {
        remove ((AnyType)key);
        return null;
    }

    @Override
    public int size() {
        return 0;
    }

    @Override
    public Collection values() {
        return null;
    }
    }

Here is my WordStats class that saves everything into a set and keeps occurrance. 这是我的WordStats类,可将所有内容保存到集合中并保持出现。

    import java.util.SortedSet;
    import java.util.TreeSet;


    public class WordStats {
private int occurrences;
private SortedSet<Integer> lineNumbers = new TreeSet<Integer>();

public void addOccurrence(int lineNumber){
    occurrences++;
    lineNumbers.add(lineNumber);
}

public int getOccurrences(){
    return occurrences;
}

public SortedSet<Integer> getLines(){
    return lineNumbers;
}
    }

When I run the program, I get the error: 运行程序时,出现错误:

Exception in thread "main" java.lang.ClassCastException : 线程“主要” java.lang.ClassCastException异常:

java.lang.String cannot be cast to WordStats java.lang.String无法转换为WordStats

at driver1.avlMap(driver1.java:182) driver1.avlMap(driver1.java:182)

at driver1.main(driver1.java:36) driver1.main(driver1.java:36)

Thanks in advance for any insight you can provide. 在此先感谢您提供的任何见解。 There are also not any compiler errors. 也没有任何编译器错误。

The root cause of this issue, as mentioned in the stack trace, is that you are trying to cast an object of type String to something of type WordStats . 如堆栈跟踪中所述,此问题的根本原因是您试图将String类型的对象转换为WordStats类型的WordStats I think that this occurs in this line: 我认为这发生在这一行:

WordStats stats = (WordStats) avlMap.get(word);

So let's look at avlMap.get(word) . 因此,让我们看一下avlMap.get(word) This looks as follows: 如下所示:

@Override
public Object get(Object key) {
    return key;
}

So this is problematic - it looks like every time you try to do a lookup, you're just returning the key that you were trying to look up inside the map! 所以这是有问题的-看起来每次您尝试进行查找时,您只是在返回要在地图中查找的键! That would explain the casting error - you're passing in a String into avlMap.get() , which then returns it. 这将解释转换错误-您将String传递给avlMap.get() ,然后将其返回。 When you try casting it to a WordStats , you're getting an error because a String isn't a WordStats . 当您尝试将其强制转换为WordStats ,会遇到错误,因为String不是WordStats

To fix this, I think you need your get method to actually do a search in the AVL tree and do a lookup. 要解决此问题,我认为您需要您的get方法才能在AVL树中进行搜索并进行查找。 I will leave this for you to complete yourself. 我会把这个留给你完成。 I would strongly suggest not trying to integrate your map into a larger program until you've tested it more thoroughly - having all of the logic to process words layered on top of a buggy AVL tree will make debugging extremely difficult, if not impossible. 强烈建议您在对地图进行更彻底的测试之前,不要尝试将其集成到一个更大的程序中-将所有逻辑处理单词叠放在多虫的AVL树的顶部将使调试变得非常困难,即使不是不可能。 Try writing some unit tests for your AVL tree to see whether it's working. 尝试为AVL树编写一些单元测试,以查看其是否正常工作。 You could also consider swapping out your AVL tree map for a normal TreeMap in the interim to see if the driver code works. 您也可以考虑在此期间将AVL树图换成普通的TreeMap ,以查看驱动程序代码是否起作用。

As another note - you should strongly consider not implementing the raw type Map and instead implement Map parameterized over a key and value type. 另外请注意-您应该强烈考虑不实现原始类型Map ,而是实现通过键和值类型参数化的Map This makes the interface way easier to use and would help catch the bug that you encountered. 这使界面方式更易于使用,并有助于捕获所遇到的错误。

Hope this helps! 希望这可以帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM