Counting frequency of words - linked list

ashpcj24 :

I am trying to insert words into a linked list because I want to count the number of times a word appears in the list and then return the words in the order of highest frequency to lowest. However, I keep getting an assertion error. Here are my insert, getCount, and getWords methods. It seems like insert and getCount are giving me problems.

public class Frequency<E extends Comparable<E>> implements Iterable<E>{
    private Node first; //starting node
    private Node parent;    //parent of currently processed node
    private int N;  //number of words


    /**
     * Linked List Node
     */
    private class Node{
        private E key;
        private int count;
        private Node next;

        Node(E e){
           key = e;
           count = 1;
           next = null;
        }

        Node(E e, Node r){
            key = e;
            count = 1;
            next = r;
         }

        @Override 
        public String toString(){
            return "("+key +","+count+")";
        }
    }

   /**
    * Inserts a word into linked list
    * @param key to be inserted 
    * @return true if the key is inserted successfully.
    */
    public boolean insert(E key){
        if (first == null || first.key != key) {
            first = new Node(key, first);
        } else {
            Node curr = first;
            while (curr.next != null) {
                curr.next = new Node(key, first.next);
            }
            curr = curr.next;
            N++;
        }
        return true;
    }

/**
     * 
     * @param key is the key to be searched for
     * @return frequency of the key. Returns -1 if key does not exist
     * 
     */
    public int getCount(E key){
        // go through the linked list and count the number of times each word appears
        // return the count of the word that is being called.
        if (key == null) {
            return -1;
        }
        int N = 0;
        Node curr = first;
        while (curr != null) {
            if (curr.key.equals(key)) {
                N++;
            }
            curr = curr.next;
        }
        return N;   
    }
    /**
     * Returns the first n words and count
     * @param n number of words to be returned
     * @return first n words in (word, count) format
     */
    public String getWords(int n){
        Node curr = first;
        for (int i = 1; i < n; i++) {
            curr = curr.next;
        }
        return curr.toString();
    }


    /**
     * Frequency List iterator
     */
    @Override
    public Iterator<E> iterator() {
        return new FreqIterator();
    }
    /**
     * 
     * Frequency List iterator class
     *
     */
    private class FreqIterator implements Iterator<E>{

        @Override
        public boolean hasNext() {
            Node curr = first;
            if(curr != null) {
                return true;
            }
            return false;
        }

        @Override
        public E next() {
            Node curr = first;
            if(hasNext() == false) {
                return null;
            }
            E item = curr.key;
            curr = curr.next;
            return item;
        }
    }
}

EDIT

This is my test to insert the same word twice into a linked list. I want the result to be 2, but I am actually getting 1. I'm assuming it has to do with my insert method.

    @Test
    public void testInsert() {
        Frequency<String> freq = new Frequency<>();
        freq.insert("dog");
        freq.insert("dog");
        String answer = freq.getWords(1);
        assertEquals("(dog,2)", answer);
    }
Nicholas K :

It doesn't work because in your getCount(E key) you never check if the key passed in is equal to the curr node while iterating through it.

Make this minor alteration to the method:

public int getCount(E key) {
    if (key == null) {
        return -1;
    }
    int N = 0;
    Node curr = first;
    while (curr != null) {
        if (curr.key.equals(key)) {  // change made here 
            N++;
        }
        curr = curr.next;
    }
    return N;
}

As per the edit, there is a logic error in the insert(E key). You need to iterate to find the last element in the list and then assign the next reference to the newly created node.

public boolean insert(E key) {
    if (first == null || first.key != key) {
        first = new Node(key, first);
    } else {
        Node curr = first;
        while (curr.next != null) {  // iterate till the end of the list
            curr = curr.next; 
        }
        curr.next = new Node(key);   // point last node's next ref to new node
        N++;
    }
    return true;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=133964&siteId=1