简体   繁体   中英

Why method doesn't recognize that a variable pointing to a static variable?

I am trying to implement a Red Black Tree that each node of it consists of another RBTree. So that I'll get good sort of my songs. First tree is of bands, and each node(band) has it's RBTree of songs.

So I try to insert a new song to an inner song tree of a Band node in the band tree, and the inner tree doesn't recognize that its' head is pointing to the static variable of nilNode. Don't know why.

The methods of insertion are the same in both of the classes of the RBTrees. each insertion takes into account the static variable "nilNode" and work according to it. when I insert nodes to the outer tree (the bands tree) the method recognize it. but when I use a getter to the inner tree from one of the band nodes, and use the inner tree's insert method, it doesn't recognize it's nilNode in it's method.

The insertion method goes like this:
1. the tree of band calls the insertion.
2. the method first finds the node of the band in the bandsTree.
3. then the node uses a getter to get the inner songs Tree of his.
4. the innerTree calls the same insert method(his insert method which is identical to the bands Tree's insert method).

now the insertion method uses a search method to see if a node(band or song) exists already or need to be created. if exists it returns the node, if not it returns the static "nilNode" which is connected to every "loose ends" of a node. the search method starts from the head of the tree.
and at the first insertion the songs tree(of the current band node) is empty meaning the head points to the static "nilNode" . so the search method suppose to stop at the first check of the loop. but it doesn't recognize that the head equals to the nilNode so it continues and the error comes when it gets the left node of the nilNode which is null and tries to use it.

These are the 4 classes I created: BandNode , BandsRBTree , SongNode , SongsRBTree

1. BandNode :

import java.io.Serializable;

public class BandNode implements Serializable{
    private Band band;
    private BandNode left;
    private BandNode right;
    private BandNode parent;
    private SongsRBTree innerTreeOfSongNames = new SongsRBTree(); **// another RBTree**
    ...

    public BandNode(String bandName) **// I got 4 constructors and each looks like this one**
    {   
        Band band = new Band(bandName);
        this.band = band;
        left = null;
        right = null;
        parent = null;
        innerTreeOfSongNames = new SongsRBTree();
    }
    ...
}//end of class BandNode

2. SongNode : // doesn't have an inner tree like BandNode

public class SongNode implements Serializable{
    private Song song;
    private SongNode left;
    private SongNode right;
    private SongNode parent;
    ...

    public SongNode(String songName) // same here 4 constructors
    {
        Song _song = new Song(songName);
        this.song = _song;
        left=null;
        right=null;
        parent=null;
    }
    ...
}//end of SongNode class

3. BandsRBTree

import java.io.Serializable;

public class BandsRBTree implements Serializable{
    private BandNode head; // head of the tree
    static BandNode nilNodeBand; // Nil node to be connected to every 2 (left and right) null ends of a node
    ...

    public BandsRBTree()
    {
        nilNodeBand = new BandNode("Nill)");
        head = nilNodeBand;
    }

    //******************************************************
    //          methods for inner tree:

    public BandNode insert(BandNode z , SongNode songNde)
    {
        BandNode b = search(z.getBand().getBandName()); // searches for the band node
        if(b.equals(nilNodeBand)) // meaning the band node doesn't exists
        {
            //nothing to show here since it doesn't go in this part. 
            because the band node already exsits and the condition is false
            ...
        }
        else // the band is already in the tree. 
            now update it's inner tree of songs
        {   
            //checking if the song node is good
            if(songNde != null && songNde.getSong() != null)
            {
                    if(songNde.getSong().getSongName().length()>0  ) // name of the song is good
                    {
                        b.getInnerTreeOfSongNames().insert(songNde); // using the inner tree of songs
                        return b; // return the band node
                    }
                    else 
                        //print error
            }

            return null; // something was null
        }

    }//insert


    //search in the band tree:
    public BandNode search(String bandNameToSearch)
    {
        BandNode temp = head;
        while( !temp.equals( nilNodeBand)) 
        {
            if( temp.getBand().getBandName().compareTo(bandNameToSearch) == 0  )
                return temp;
            else if(bandNameToSearch.compareTo(temp.getBand().getBandName()) < 0  )
                temp = temp.getLeft();
            else
                temp = temp.getRight();
        }
        return nilNodeBand;
    }

}// class BandsRBTree end

4. SongsRBTree

import java.io.Serializable;

public class SongsRBTree implements Serializable{
    private SongNode head; // head of the tree
    static SongNode nilNodeSong; // Nil node to be connected as every null child
    ...
    //constructor
    public SongsRBTree()
    {
        nilNodeSong = new SongNode(new Song("Nill"));
        head = nilNodeSong;  // the head is nilNode at the start
    }

    public SongNode insert(SongNode z )
    {     
        // first search:
        SongNode b = search(z.getSong().getSongName()); 

        ...
        //the method get here because of the error in the search method

    }//insert


    public SongNode search(String songNameToSearch)
    {
        SongNode temp = head; // here the head is nilNode. see in the constructor

        while( !temp.equals( nilNodeSong) ) // it enters the loop. ALTOUGH IT SHOULDN'T
        {                                   //  because temp = head. and the head suppose to be nilNodeSong
                                            //  since the tree is empty at the beginning
                                            //  see constructor
            if( temp.getSong().getSongName().compareTo(songNameToSearch) == 0  )
                return temp;
            else if(songNameToSearch.compareTo(temp.getSong().getSongName()) < 0  )
                temp = temp.getLeft();
            else
                temp = temp.getRight();
        }
        return nilNodeSong;

    }
} // end of BandsRBTree class  

Anyway the situation is this:
1. I have a band tree set up with 10 band nodes
2. each node has an empty inner tree by the constructor of a bandNode.
3. I try to use one of the inner trees's insert method to insert a song to it for the first time .
4. the search method doesn't recognize that the head of the tree is pointing to nilNode.
why doesn't recognize that? (head is nilNode at the start because it's empty)

the problem occurs in the condition of the while loop in the search method of the class BandsRBTree. the condition suppose to prevent the method from going in the body of the loop since at the first insert the head is nilNode by the constructor, but the condition fails to recognize that. why??

please help.

The only way to reproduce your issue is when multiple instances of the class with the search method are created. And the comparison is done in an instance which is not created latest. Perhaps the approach is wrong to do what you want to do. To fulfill your needs it would be enough to implement .equals.

Kind regards

Each time you construct SongsRBTree you are wiping out the prior contents of your static variable and creating a new SongNode in its place. Quick step-by-step: You create SongsRBTree tree1 . Now nilNodeSong is a SongNode which we will call nill1 . The head of tree1 is nill1 .

Now you create SongsRBTree tree2 . Now nilNodeSong is a SongNode which we will call nill2 . The head of tree2 is nill2 but the head of tree1 is still nill1 . When you insert into tree1 of course it doesn't recognize nill1 == nill2 .

Solution: Static initializer or override the equals method in SongNode and don't bother with the special static SongNode nillNodeSong . I'd probably go with overriding equals but either should do the trick.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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