Link to home
Start Free TrialLog in
Avatar of datopdogg7
datopdogg7

asked on

How do I alphabetize a single linked list of words in Java?

Hi experts,

I have been racking my brain about this all day and can't seem to come up with a good way to implement an algorithm to solve my problem.

I have a single linked list. The list stores the object 'Word' which has some methods and members, namely the word itself.

I want to alphabetize this list. There are two scenarios of when it can be done: I can add all the objects in at once and sort after all objects have been put in, or I can put in one object sort the list and then carry on to the next word.

How would you tackle this problem?

The only solution that I have come up with that is viable and some what fast, is to store the words as an array of objects, sort them, then call upon the single linked list class and add them sequentially.

Any help on an algorithm would be appreciated, full points will be awarded for some code in the solution,

Cheers,

Dennis
Avatar of CEHJ
CEHJ
Flag of United Kingdom of Great Britain and Northern Ireland image

I would make your Word class Comparable. An insert method on your list could simply put it in the correct place immediately
Avatar of datopdogg7
datopdogg7

ASKER

Thanks CEHJ,

Can you give me an example of this implementation? I follow the part with the method, but I am not sure of where to go from there,

Dennis
Is this your own linked list implementation?
If so change your insert method to traverse down the list until it finds the spot to insert it.

If you are using java's collection class then it already contains methods for sorting collections, and maintaining sorted collections.

If you've got a Comparable Word class you can do something like the following, which will give you a sorted list:
    static boolean insert(Word w) {
	Word current;
	Word previous;
 
	if (head == null) { // Nothing
	    w.next = null;
	    head = w;
 
	    return true;
	}
 
	previous = head;
	current = head.next;
 
	if (head.data.compareTo(w.data) > 1) {
	    w.next = head;
	    head = w;
 
	    return true;
	}
 
	if (head.data.compareTo(w.data) == 0) {
	    return false;
	}
 
	while (current != null) {
	    if (current.data.compareTo(w.data) > 1) {
		w.next = current;
		previous.next = w;
 
		return true;
	    }
 
	    if (current.data == w.data) {
		return false;
	    } else {
		previous = current;
		current = current.next;
	    }
	}
 
	w.next = null;
	previous.next = w;
 
	return true;
    }

Open in new window

> If you've got a Comparable Word class you can do something like the following, which will give you a sorted list:

which is exactly what I already suggested :)

It's exactly what i'd already suggested
Hi again,

This is my current linked list class. Does the above implementation still fit nicely? If so what variable names would I need to change?
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
 
package assignment1;
 
 
public class LinkedList {// reference to the head node.
 
    private Node head;
	private int listCount;
 
	// LinkedList constructor
	public LinkedList()
	{
		// this is an empty list, so the reference to the head node
		// is set to a new node with no data
		head = new Node(null);
		listCount = 0;
	}
 
	public void add(Word data)
	// post: appends the specified element to the end of this list.
	{
		Node temp = new Node(data);
		Node current = head;
		// starting at the head node, crawl to the end of the list
		while(current.getNext() != null)
		{
			current = current.getNext();
		}
		// the last node's "next" reference set to our new node
		current.setNext(temp);
		listCount++;// increment the number of elements variable
	}
 
	public void add(Word data, int index)
	// post: inserts the specified element at the specified position in this list.
	{
		Node temp = new Node(data);
		Node current = head;
		// crawl to the requested index or the last element in the list,
		// whichever comes first
		for(int i = 1; i < index && current.getNext() != null; i++)
		{
			current = current.getNext();
		}
		// set the new node's next-node reference to this node's next-node reference
		temp.setNext(current.getNext());
		// now set this node's next-node reference to the new node
		current.setNext(temp);
		listCount++;// increment the number of elements variable
	}
 
	public Word get(int index)
	// post: returns the element at the specified position in this list.
	{
		// index must be 1 or higher
		if(index <= 0)
			return null;
 
		Node current = head.getNext();
		for(int i = 1; i < index; i++)
		{
			if(current.getNext() == null)
				return null;
 
			current = current.getNext();
		}
		return current.getData();
	}
 
	public boolean remove(int index)
	// post: removes the element at the specified position in this list.
	{
		// if the index is out of range, exit
		if(index < 1 || index > size())
			return false;
 
		Node current = head;
		for(int i = 1; i < index; i++)
		{
			if(current.getNext() == null)
				return false;
 
			current = current.getNext();
		}
		current.setNext(current.getNext().getNext());
		listCount--; // decrement the number of elements variable
		return true;
	}
 
	public int size()
	// post: returns the number of elements in this list.
	{
		return listCount;
	}
 
	public String toString()
	{
		Node current = head.getNext();
		String output = "";
		while(current != null)
		{
			output += "[" + current.getData().toString() + "]";
			current = current.getNext();
		}
		return output;
	}
 
	private class Node
	{
		// reference to the next node in the chain,
		// or null if there isn't one.
		Node next;
		// data carried by this node.
		// could be of any type you need.
		Word data;
 
 
		// Node constructor
		public Node(Word _data)
		{
			next = null;
			data = _data;
		}
 
		// another Node constructor if we want to
		// specify the node to point to.
		public Node(Word _data, Node _next)
		{
			next = _next;
			data = _data;
		}
 
		// these methods should be self-explanatory
		public Word getData()
		{
			return data;
		}
 
		public void setData(Word _data)
		{
			data = _data;
		}
 
		public Node getNext()
		{
			return next;
		}
 
		public void setNext(Node _next)
		{
			next = _next;
		}
	}
 
 
}

Open in new window

>                 // starting at the head node, crawl to the end of the list

instead just crawl until you find an element greater than the word being inserted

>         public void add(Word data, int index)

you can't guarantee it will remain sorted with that method available

be something like this:

                while(current.getNext() != null && current.getNext().getData().word.compareTo(data.word)<0)
                {
                        current = current.getNext();
                }

Hi objects,

Where would your snippet of code go in the above linked list code? I tried putting it instead of teh while loop in the 'add' method and the result was still an unsorted list.

Perhaps you could just modify the linked list code I pasted above.

I've done most of the work for this assignment, I'm just having quite a bit of trouble with this last feature.

Cheers,
Dennis
try this:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
 
package assignment1;
 
 
public class LinkedList {// reference to the head node.
 
    private Node head;
        private int listCount;
 
        // LinkedList constructor
        public LinkedList()
        {
                // this is an empty list, so the reference to the head node
                // is set to a new node with no data
                head = new Node(null);
                listCount = 0;
        }
 
        public void add(Word data)
        // post: appends the specified element to the end of this list.
        {
                Node temp = new Node(data);
                Node current = head;
                // starting at the head node, crawl to the end of the list
                while(current.getNext() != null && current.getNext().getData().word.compareTo(data.word)<0)
                {
                        current = current.getNext();
                }
                // the last node's "next" reference set to our new node
                temp.setNext(current.getNext());
                current.setNext(temp);
                listCount++;// increment the number of elements variable
        }
 
        public void add(Word data, int index)
        // post: inserts the specified element at the specified position in this list.
        {
                Node temp = new Node(data);
                Node current = head;
                // crawl to the requested index or the last element in the list,
                // whichever comes first
                for(int i = 1; i < index && current.getNext() != null; i++)
                {
                        current = current.getNext();
                }
                // set the new node's next-node reference to this node's next-node reference
                temp.setNext(current.getNext());
                // now set this node's next-node reference to the new node
                current.setNext(temp);
                listCount++;// increment the number of elements variable
        }
 
        public Word get(int index)
        // post: returns the element at the specified position in this list.
        {
                // index must be 1 or higher
                if(index <= 0)
                        return null;
 
                Node current = head.getNext();
                for(int i = 1; i < index; i++)
                {
                        if(current.getNext() == null)
                                return null;
 
                        current = current.getNext();
                }
                return current.getData();
        }
 
        public boolean remove(int index)
        // post: removes the element at the specified position in this list.
        {
                // if the index is out of range, exit
                if(index < 1 || index > size())
                        return false;
 
                Node current = head;
                for(int i = 1; i < index; i++)
                {
                        if(current.getNext() == null)
                                return false;
 
                        current = current.getNext();
                }
                current.setNext(current.getNext().getNext());
                listCount--; // decrement the number of elements variable
                return true;
        }
 
        public int size()
        // post: returns the number of elements in this list.
        {
                return listCount;
        }
 
        public String toString()
        {
                Node current = head.getNext();
                String output = "";
                while(current != null)
                {
                        output += "[" + current.getData().toString() + "]";
                        current = current.getNext();
                }
                return output;
        }
 
        private class Node
        {
                // reference to the next node in the chain,
                // or null if there isn't one.
                Node next;
                // data carried by this node.
                // could be of any type you need.
                Word data;
 
 
                // Node constructor
                public Node(Word _data)
                {
                        next = null;
                        data = _data;
                }
 
                // another Node constructor if we want to
                // specify the node to point to.
                public Node(Word _data, Node _next)
                {
                        next = _next;
                        data = _data;
                }
 
                // these methods should be self-explanatory
                public Word getData()
                {
                        return data;
                }
 
                public void setData(Word _data)
                {
                        data = _data;
                }
 
                public Node getNext()
                {
                        return next;
                }
 
                public void setNext(Node _next)
                {
                        next = _next;
                }
        }
 
 
}



I'm not sure whats going on but my code isn't outputting the right thing in the right order. There appears to be two general issues with the code.

1. The list isn't sorted alphabetically.
2. The output text file is not being written to properly. I expect for the output text to have the word and its frequency, then on the next line the next word with its frequency.

I will open a new question if it is desired to award more points.

The next 3 comments are the 2 classes and the main program.

Please help!
Dennis
Word Class
package assignment1;
import java.io.*;
import java.util.*;
import javax.swing.JOptionPane;
 
public class Main {
 
    public static void main(String[] args) {
 
        // Prompt the user for the file name
 
        String input_file_name;
        input_file_name = JOptionPane.showInputDialog("Please enter the file name");
 
        // Initialize a new instance of the class "LinkedList"
 
        LinkedList word_list = new LinkedList();
 
        // Initialize the flag "paragraph" which lets the loop know if the scanner has hit a paragraph or the end of the file
 
        boolean paragraph = true;
 
        // Initialize the line counter
 
        int line_counter = 0;
 
        //Begin main loop
 
        try {
 
            // Read in the the text from the user specified file name
 
            BufferedReader text = new BufferedReader(new FileReader(input_file_name));
            String line;
 
 
            // Do the loop while the next line is not white space and when a paragraph was not encountered on the previous line
 
            while(((line = text.readLine())!= null) || paragraph){
 
                // Increment line counter every iteration
 
                line_counter++;
 
                // If the read line is not white space, i.e a paragraph, then perform operations
 
                if (line!= null){
 
                    // Ensure that the flag has been reset
 
                    paragraph = true;
 
                    // Perform manipulation of string and add words to list
 
                    store(word_list,line, line_counter);
 
                }
 
                // If the read line does have white space then throw a flag
 
                else{
 
                    paragraph = false;
 
                }
 
            }
        
            text.close();
            
        } catch (IOException e) {}
 
        // Prompt user if he or she wishes to build a report
 
        String answer;
        answer = JOptionPane.showInputDialog("Would you like export the report to a text file?");
 
        // If the user wants to export the report perform the following
 
        if( answer.equals("Y") || answer.equals("y") || answer.equals("Yes") || answer.equals("yes")){
 
            reportGenerator(word_list);
            
        }
 
        // The user has chose not to export the report, so do nothing
 
        else{
 
 
        }
 
 
    }
 
    //
    // This function manipulates the line from the text in order to identify the unique words
    //
 
        public static void store(LinkedList word_list,String next_line, int line_number){
 
            int pos = 0;
            while (pos<next_line.length())
            {
                  // Find next space
 
                  int space = next_line.indexOf(' ', pos);
                  if (space==-1)
                  {
                        // End of string reached
 
                        space = next_line.length();
 
                  }
 
                  // Check the word length >0
 
                  if (space-pos>0)
                  {
                      
                      // Check to see if word is already in the linked list
 
                      int pos_in_list = unique(word_list,next_line.substring(pos, space));
 
                      // If the pos_in_list is '-1' then the word has not been entered in the list yet
 
                      if((pos_in_list) < 0){
 
                          // Since the word hasn't been read before, create new instance and add info about word
 
                          Word new_word = new Word();
                          new_word.setWord(next_line.substring(pos, space));
                          new_word.incrementWordFrequency();
                          new_word.addLineNumber(line_number);
 
                          // Add new_word to word list
 
                          word_list.add(new_word);
 
                      }
 
                      // If the pos_in_list is other than '-1' then the word is already in the linked list and the position in the list has been stored in pos_in_list
 
                      else{
 
                          // Since the word is not unique update instance of that word. The pos_in_list can be reused to update the word in the link list
 
                          Word temp_word = new Word();
 
                          temp_word = word_list.get(pos_in_list);
                          temp_word.incrementWordFrequency();
                          temp_word.addLineNumber(line_number);
 
                          // Replace the updated word back into the list at the same spot.
 
                          word_list.add(temp_word, line_number);
 
                      }
             
                  }
 
                  // Shift position past space
 
                  pos = space + 1;
 
            }
 
 
    }
        //
        // This function checks to see if the parsed word is already in the linked list
        //
 
        public static int unique(LinkedList word_list,String check_word){
 
            // Create a new array of all the words currently in the link list
 
            ArrayList words_in_list = new ArrayList();
 
            // Determine the number of words in the link list
 
            int list_size = word_list.size();
 
            // Begin filling the word list array with all the words currently in the link list
 
            for ( int i=0; i<=list_size; i++ )
            {
 
                words_in_list.add(word_list.get(i));
 
            }
 
            // Determine if the parsed word is in the list and where. If is not, return the position, if not a '-1'
 
            return words_in_list.indexOf(check_word);
        }
 
        public static void reportGenerator(LinkedList list){
 
            // Initialize variables
 
            Word temp_output = new Word();
 
            String word_output;
 
            // Begin file writing
 
            try {
 
                // Create new instance of the FileWriter class
 
                FileWriter output_file = new FileWriter(new File("Result.txt"));
 
                // Loop through list outputting the words and their information to the output file
 
                for ( int i=1; i<list.size(); i++ ){
 
                temp_output = list.get(i);
 
                word_output = "The word '" + temp_output.getWord() + "' has a frequency of " + temp_output.getWordFrequency() + " and occurs on the following lines " + temp_output.getLineNumber();
 
                output_file.write(word_output);
 
                output_file.close();
                
                }
 
 
            }catch (IOException e) {}
 
 
        }
 
 
}

Open in new window

Sorry the above was the Main. Below is the Word class
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
 
package assignment1;
import java.util.*;
 
public class Word {
 
 
    private String word;
    private ArrayList lineNumber = new ArrayList();
    private ArrayList linePosition = new ArrayList();
    private ArrayList textPosition = new ArrayList();
    private int wordFrequency;
 
    // This constructer intializes a new instance of the class Word. An empty data container is created.
 
	public Word()
	{
 
         wordFrequency = 0;
 
    }
 
    // This returns the word, as it is private.
 
    public String getWord()
    {
            return word;
    }
 
// This returns the line number array of the word, as it is private.
 
    public ArrayList getLineNumber()
    {
            return lineNumber;
    }
 
// This returns the array of the position of the word in a line, as it is private.
 
    public ArrayList getLinePosition()
    {
            return linePosition;
    }
 
// This returns the array of the position of the word in the text, as it is private.
 
    public ArrayList getTextPosition()
    {
            return textPosition;
    }
 
// This returns the frequency of the word in the text, as it is private.
 
    public int getWordFrequency()
    {
            return wordFrequency;
    }
 
// This sets the word.
 
    public void setWord(String inputWord)
    {
            word = inputWord;
    }
 
// This increments the frequency
 
    public void incrementWordFrequency(){
 
        wordFrequency = wordFrequency + 1;
 
    }
 
// This adds the line number in the array if there was no previous entry of that same number.
 
    public void addLineNumber(int number)
    {
 
        if(lineNumber.isEmpty()){
 
            lineNumber.add(number);
 
        }
 
        else if  (lineNumber.contains(number)){
 
 
        }
 
        else{
 
            lineNumber.add(number);
 
        }
 
 
    }
 
    public void addLinePosition(int pos){
 
        // add code here
 
    }
 
    public void addTextPosition(int pos){
 
        // add code here
 
    }
 
}

Open in new window

Linked list class, same as above but I will repost anyways
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
 
package assignment1;
 
 
public class LinkedList {// reference to the head node.
 
    private Node head;
        private int listCount;
 
        // LinkedList constructor
        public LinkedList()
        {
                // this is an empty list, so the reference to the head node
                // is set to a new node with no data
                head = new Node(null);
                listCount = 0;
        }
 
        public void add(Word data)
        // post: appends the specified element to the end of this list.
        {
                Node temp = new Node(data);
                Node current = head;
                // starting at the head node, crawl to the end of the list
                while(current.getNext() != null && current.getNext().getData().getWord().compareTo(data.getWord())<0)
                {
                        current = current.getNext();
                }
                // the last node's "next" reference set to our new node
                temp.setNext(current.getNext());
                current.setNext(temp);
                listCount++;// increment the number of elements variable
        }
 
        public void add(Word data, int index)
        // post: inserts the specified element at the specified position in this list.
        {
                Node temp = new Node(data);
                Node current = head;
                // crawl to the requested index or the last element in the list,
                // whichever comes first
                for(int i = 1; i < index && current.getNext() != null; i++)
                {
                        current = current.getNext();
                }
                // set the new node's next-node reference to this node's next-node reference
                temp.setNext(current.getNext());
                // now set this node's next-node reference to the new node
                current.setNext(temp);
                listCount++;// increment the number of elements variable
        }
 
        public Word get(int index)
        // post: returns the element at the specified position in this list.
        {
                // index must be 1 or higher
                if(index <= 0)
                        return null;
 
                Node current = head.getNext();
                for(int i = 1; i < index; i++)
                {
                        if(current.getNext() == null)
                                return null;
 
                        current = current.getNext();
                }
                return current.getData();
        }
 
        public boolean remove(int index)
        // post: removes the element at the specified position in this list.
        {
                // if the index is out of range, exit
                if(index < 1 || index > size())
                        return false;
 
                Node current = head;
                for(int i = 1; i < index; i++)
                {
                        if(current.getNext() == null)
                                return false;
 
                        current = current.getNext();
                }
                current.setNext(current.getNext().getNext());
                listCount--; // decrement the number of elements variable
                return true;
        }
 
        public int size()
        // post: returns the number of elements in this list.
        {
                return listCount;
        }
 
        public String toString()
        {
                Node current = head.getNext();
                String output = "";
                while(current != null)
                {
                        output += "[" + current.getData().toString() + "]";
                        current = current.getNext();
                }
                return output;
        }
 
        private class Node
        {
                // reference to the next node in the chain,
                // or null if there isn't one.
                Node next;
                // data carried by this node.
                // could be of any type you need.
                Word data;
 
 
                // Node constructor
                public Node(Word _data)
                {
                        next = null;
                        data = _data;
                }
 
                // another Node constructor if we want to
                // specify the node to point to.
                public Node(Word _data, Node _next)
                {
                        next = _next;
                        data = _data;
                }
 
                // these methods should be self-explanatory
                public Word getData()
                {
                        return data;
                }
 
                public void setData(Word _data)
                {
                        data = _data;
                }
 
                public Node getNext()
                {
                        return next;
                }
 
                public void setNext(Node _next)
                {
                        next = _next;
                }
        }
 
 
}

Open in new window

the code i posted above works fine here so your problem may be related to your driver code

try the following

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
 
package assignment1;
 
 
public class LinkedList {// reference to the head node.
 
      public static void main(String[] args)
      {
            LinkedList list = new LinkedList();
            list.add(new Word("dsd"));
            list.add(new Word("adf"));
            list.add(new Word("ggge"));
            list.add(new Word("hsg"));
            System.out.println(list);
      }
    private Node head;
        private int listCount;
 
        // LinkedList constructor
        public LinkedList()
        {
                // this is an empty list, so the reference to the head node
                // is set to a new node with no data
                head = new Node(null);
                listCount = 0;
        }
 
        public void add(Word data)
        // post: appends the specified element to the end of this list.
        {
                Node temp = new Node(data);
                Node current = head;
                // starting at the head node, crawl to the end of the list
//                while(current.getNext() != null)
                while(current.getNext() != null && current.getNext().getData().word.compareTo(data.word)<0)
                {
                        current = current.getNext();
                }
                // the last node's "next" reference set to our new node
                temp.setNext(current.getNext());
                current.setNext(temp);
                listCount++;// increment the number of elements variable
        }
 
        public void add(Word data, int index)
        // post: inserts the specified element at the specified position in this list.
        {
                Node temp = new Node(data);
                Node current = head;
                // crawl to the requested index or the last element in the list,
                // whichever comes first
                for(int i = 1; i < index && current.getNext() != null; i++)
                {
                        current = current.getNext();
                }
                // set the new node's next-node reference to this node's next-node reference
                temp.setNext(current.getNext());
                // now set this node's next-node reference to the new node
                current.setNext(temp);
                listCount++;// increment the number of elements variable
        }
 
        public Word get(int index)
        // post: returns the element at the specified position in this list.
        {
                // index must be 1 or higher
                if(index <= 0)
                        return null;
 
                Node current = head.getNext();
                for(int i = 1; i < index; i++)
                {
                        if(current.getNext() == null)
                                return null;
 
                        current = current.getNext();
                }
                return current.getData();
        }
 
        public boolean remove(int index)
        // post: removes the element at the specified position in this list.
        {
                // if the index is out of range, exit
                if(index < 1 || index > size())
                        return false;
 
                Node current = head;
                for(int i = 1; i < index; i++)
                {
                        if(current.getNext() == null)
                                return false;
 
                        current = current.getNext();
                }
                current.setNext(current.getNext().getNext());
                listCount--; // decrement the number of elements variable
                return true;
        }
 
        public int size()
        // post: returns the number of elements in this list.
        {
                return listCount;
        }
 
        public String toString()
        {
                Node current = head.getNext();
                String output = "";
                while(current != null)
                {
                        output += "[" + current.getData().toString() + "]";
                        current = current.getNext();
                }
                return output;
        }
 
        private class Node
        {
                // reference to the next node in the chain,
                // or null if there isn't one.
                Node next;
                // data carried by this node.
                // could be of any type you need.
                Word data;
 
 
                // Node constructor
                public Node(Word _data)
                {
                        next = null;
                        data = _data;
                }
 
                // another Node constructor if we want to
                // specify the node to point to.
                public Node(Word _data, Node _next)
                {
                        next = _next;
                        data = _data;
                }
 
                // these methods should be self-explanatory
                public Word getData()
                {
                        return data;
                }
 
                public void setData(Word _data)
                {
                        data = _data;
                }
 
                public Node getNext()
                {
                        return next;
                }
 
                public void setNext(Node _next)
                {
                        next = _next;
                }
        }
 
 
}

class Word
{
      String word;
      Word(String word)
      {
            this.word = word;
      }
      
      public String toString()
      {
            return word;
      }
}





>                           word_list.add(temp_word, line_number);

thats not replacing the node, its adding a new one
If I don't use that line of code, and just update the members in the word class, will I get the desired result because the pointer in the node is still pointing to that object?

That is one issue; however, the test text I had only had unique words so that line of code should never have executed....
ASKER CERTIFIED SOLUTION
Avatar of Mick Barry
Mick Barry
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
?

Dennis - can you explain why you ignored my (working) code?