简体   繁体   中英

Binary Search Trees : how can I compare variable's values of its elements?

So I have a BST and its elements are type TreeNode. Each TreeNode object includes a WordFreq object which consists of a String variable called word, and an integer variable called freq. The elements are words that my program reads from a file, so the variable "word" is that String, and variable freq represent the frequency that the word appears in the text. So what i want to do is go through the whole BST and find the TreeNode with the max frequency(max freq). I tried many ways, but it doesnt seem to work. The words are sorted on the tree alphabetically, NOT sorted by frequency. Here is my method:

public WordFreq getMaximumFrequency() {
    return getMaximumFrequencyR(head, 1);
}

public WordFreq getMaximumFrequencyR(TreeNode h, int i) {
    WordFreq temp = h.getWordFreq();
    if (h.getWordFreq().getFreq() > getMeanFrequency()) {    //line 3

        if (h.l != null) {
            if (h.getWordFreq().getFreq() >= i){
                i = h.getWordFreq().getFreq();
                temp = h.getWordFreq();
                getMaximumFrequencyR(h.l, i);
            }
        }
        if (h.r != null) {
            if (h.getWordFreq().getFreq() >= i){
                i = h.getWordFreq().getFreq();
                temp = h.getWordFreq();
                getMaximumFrequencyR(h.r, i);
            }
        }
    }
    else {
        if (h.l != null) {
            getMaximumFrequencyR(h.l, i);
        }
        if (h.r != null) {
            getMaximumFrequencyR(h.r, i);
        }
    }
    return temp;
}

getMeanFrequency() is a method that returns average frequency. The comparison on line 3 makes sense because it is required (for my assignment) that when a word has bigger frequency than average frequency of the tree, to be inserted at the root. That means that the maximum frequency I am looking for cannot be somewhere at the bottom of the tree. (Language is Java) Do you have any idea how I could make this work?

here are some helpfull method info to better comprehend my code: class TreeNode:

public class TreeNode {

    private WordFreq wf;
    private TreeNode l, r;
    private int N;
    private TreeNode head;

    public TreeNode() {
        head = null;
        l = null;
        r = null;
    }

    public TreeNode(WordFreq wf) {
        this.wf =wf;
        l = null;
        r = null;
        N = 0;
    }

    public void incrSubtree(TreeNode tn) {
        tn.N++;
    }

    public void decrSubtree(TreeNode tn) {
        tn.N--;
    }

    public WordFreq getWordFreq() {
        return wf;
    }
}

class WordFreq:

public class WordFreq {
private String word;
private int freq;

public WordFreq(String word) {
    this.word = word;
    freq=1;
}

public String key() {
    return this.word;
}

public void freqIncrease(WordFreq w) {
    w.freq++;
}

public String toString() {
    return "The word " + key() + " has frequency " + getFreq() + ".";
}

public int getFreq() {
    return freq;
}

}

The pseudo-code for the algorithm you want is:

maxFrequency(NULL) = 0
maxFrequency(Node) =  max(frequency(Node.value),maxFrequency(Node.right),maxFrequency(Node.Left));

It should not be hard to convert this pseudo-code to java.

Note that this does not take advantage of the fact that a node with above average frequency is inserted at the root. I do not think that it is easy to implement an algorithm that does.

If you need to do an exhaustive search of the tree (ie the highest frequency word could be anywhere) then this becomes relatively easy I believe.

However, first of all I suggest you don't set your l and r members to null in TreeNode . Instead I suggest you have a private static EMPTY TreeNode which overrides appropriate methods to play the part of null - such as returing a word frequency of 0. There are lots of reasons to do it this way but rather than list them I suggest you google it! I'm going to assume you've done that in the code below as it makes things a lot neater.

Add a TreeNode method:

public TreeNode maxFrequency() {
    return Arrays.asList(this, l.maxFrequenc(), r.maxFrequency()).stream()
        .max((tn1, tn2) -> tn1.wf.compareTo(tn2.wf))
        .orElse(EMPTY);
}    

Let me explain how this works in case you are not experienced with Java 8 streams. The Arrays.asList line creates a list of the current node and the maximum word frequency nodes from the left and right and then turns them into a stream. The max statement finds the one with the highest word frequency using a compareTo method (which you will need to add to the WordFrequency class). This returns a Optional<TreeNode> which could potentially be not present so the orElse statement returns EMPTY if there is no maximum.

Finally you'll need to override this maxFrequency method in the EMPTY TreeNode to just return this to avoid infinite recursion.

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