Testing if a string is a palindrome using a stack - java

I am attempting to take a user inputted word, ad it to a stack and then check to see if that word is a palindrome. I am attempting to pop everything off the stack and onto a new string and then compare the strings. I believe my current issue is that my pop() function doesn't actually return a value. It actually just cuts off the tail node and then reprints the string without the tail node. I guess my question is, how do I write my pop() function so that it returns the "popped" value?
Here is my main method
Scanner input = new Scanner(System.in);
Stack_Scott_Robinson<Character> myList = new Stack_Scott_Robinson<Character>(); //create a list object
System.out.println("Enter a string: ");
String s = input.next();
for (int i = 0; i < s.length(); i++){
myList.push(s.charAt(i));
}
String reverseInput = "";
while (!myList.isEmpty()){
reverseInput = reverseInput + myList.Pop();
}
if (s.equals(reverseInput)){
System.out.println("This is a palindrome");
}else{
System.out.println("This is not a palidrome");
System.out.print("Would you like to re-run code with different input string(y/n)?");
another = input.next();
}
Here is my pop() method
public void Pop()
{
Node countList = end; //set "count" node at the front of the list
int size = 0; //initialize the size variable
//moves the count node down the list and increments the size variable
while (countList != null)
{
countList = countList.next;
size++;
}
if (size == 0){ //empty list
System.out.println("error: empty list");
}else if (size == 1) //one node list
{
top = null;
end = null;
System.out.println("list is now empty");
}
else{
Node current = end;//set a current node at the front of the list
for (int i = 0; i<size-2; i++)//-2 because the list starts at 0 and we want the second to last position
{
current = current.next;//moves the current node down the list until it is
}
Node temporary = current.next; //the second to last position
Node temp = top;//create a new node space
top = current;//set the new node equal to the second to last position
top.next = null;//sets the node as the tail
}
}

Here is how java.util.Vector does it (java.util.Stack extends Vector)
public synchronized E pop() {
E obj;
int len = size();
obj = peek();
removeElementAt(len - 1);
return obj;
}
and
public synchronized void removeElementAt(int index) {
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " +
elementCount);
}
else if (index < 0) {
throw new ArrayIndexOutOfBoundsException(index);
}
int j = elementCount - index - 1;
if (j > 0) {
System.arraycopy(elementData, index + 1, elementData, index, j);
}
modCount++;
elementCount--;
elementData[elementCount] = null; /* to let gc do its work */
}
In the pop method, you can see that we know what object to remove because they get it using peek(); Then they just remove the element at the end of the vector. Hopefully this helps. I'm not sure how you are representing your Stack under the hood, so I can't really give you a better answer without that.

Related

Adding object to last element of arraylist

I'm creating a resizeable Object Array. Below is my add function in which I pass through the object I want to add into my arraylist.
The function works, however if someone could explain this code
temp[theList.length] = toAdd;
I understand that it's adding the parameter argument to the end of the new Arraylist. But what's confusing me is the index that I pass into temp[]. Shouldn't I be including theList.length + 1 rather than just theList.length?
public boolean add(Object toAdd) {
if (toAdd != null) {
Object[] temp = new Object[theList.length + 1];
for (int i = 0; i < theList.length; i++) {
temp[i] = theList[i];
}
temp[theList.length] = toAdd;
theList = temp;
return true;
} else {
System.out.println("Invalid type");
return false;
}
}
Explanation for the add method:
Assume, the size of the theList is 10.
They have created an temp array which takes size as theList + 1, so size of temp is 11.
Now, objects are added to the temp except for the last element tem[10].
For adding the last element, you can use any of the 2 ways:
temp[theList.length] //temp[10]
Or
temp[temp.length-1] //temp[10]
They used the 1st way to add the toAdd object.
You could use a standard method Arrays.copyOf which immediately creates a copy of the input array with the new size (in this case, the length is increased):
import java.util.Arrays;
//...
public boolean add(Object toAdd) {
if (toAdd != null) {
int oldLength = theList.length;
theList = Arrays.copyOf(theList, oldLength + 1);
theList[oldLength] = toAdd;
return true;
} else {
System.out.println("Cannot add null object");
return false;
}
}

I wrote a delete method for a node in Linked List at specific index (Java) but it makes no changes to the list?

The code makes no changes to the output and just reprints the original linked list and I don't know whether the problem is with my delete method or with the access specifiers I used for my Stack.
List item
Public static class Stack
{
Node first; *// newest node added*
private int size;
class Node
{
String item;
Node next;
}
public Node delete(int index,Stack list)
{
if (list.first== null) {
return null;
} else if (index == 0)
{
return list.first.next;
}
else
{
Node n = list.first;
for (int i = 0; i < index - 1; i++)
{
n = n.next;
if(i==index)
n.next = n.next.next;//skips over the existing element
}
return list.first;
}
}
}
//client test code
public static void main(String[] args) {
StdOut.print("Type the linked list:");
Stack list = new Stack();
int index;
String in=StdIn.readLine();
for(int i=0;i<=in.length();i++)
{
list.push(in);
}
StdOut.print("Type the index to be deleted:");
index=StdIn.readInt();
StdOut.println("Before deleting element at "+ index);
StdOut.println(in);
StdOut.println("After deleting element at "+ index);
StdOut.print(list.delete(index,list).item);
}
}
In your delete() function, you are returning list.first - which is pointing to the head node of the list, and not the Node first* //newest node added*, correct? I think you should just be returning from the function when the delete task is complete instead of returning null or a node.
Also, as you iterate through the list in the final else statement, you should move the n = n.next; line below the index check.
Your delete() function would look something like this:
public Node delete(int index,Stack list)
{
if (list.first== null)
{
return;
} else if (index == 0)
{
return;
}
else
{
Node n = list.first;
for (int i = 0; i < index; i++)
{
//If the next Node of the current node is +1 the current index
if(i+1==index)
{
n.next = n.next.next;//skips over the existing element
return;
}
n = n.next;
}
return;
}
}
And :
list.delete(index,list).item; //call the delete function
StdOut.println("After deleting element at "+ index);
list.print(); //Print the list using its print function (assuming you have one)
I hope this helps!

Turning a String into a LinkedList and browsing it with recursion

I'm very new to recursion (and I'm required to use it) and am having some serious logic trouble using one of my search methods. Please see below:
//these are methods within a Linked List ADT with StringBuilder functionality
//the goal here is to access the char (the Node data) at a certain index
public char charAt(int index)
{
if((firstNode == null) || (index < 0) || (index >= length + 1))
//firstNode is the 1st Node in the Linked List, where the search begins
{
System.out.println("Invalid Index or FirstNode is null");
IndexOutOfBoundsException e = new IndexOutOfBoundsException();
throw e;
}
else
{
char c = searchForChar(firstNode, index);
return c;
}
}
private char searchForChar(Node nodeOne, int index)
{
int i = 0;
if(nodeOne == null) //basecase --> end
{
i = 0;
System.out.println("nodeOne null, returning null Node data");
return 'n';
}
else if(i == index) //basecase --> found
{
i = 0;
return nodeOne.data; //nodeOne.data holds the char in the Node
}
else if(nodeOne != null) //search continues
{
searchForChar(nodeOne.next, index);
i++;
return nodeOne.data;
}
return nodeOne.data;
}
The output is length-1 prints of "nodeOne null, returning null Node data". I don't understand how the recursive statement in the last else-if statement if being reached when it seems like the null statement in the first if statement is being reached as well.
I tried rearranging the if statements so that the if(nodeOne != null) is first, but that gives me a NullPointerException. Not sure what I'm doing wrong. Especially because I can print the data in the Nodes using a toString() method so I know the Nodes don't have null data.
Can anyone please help me understand?
I wrote a complete example I hope this is what you need. If you would loop over the string StackOverflow with i < 14 it will also print the null character \0 if you would use i < 15 it will give you a IndexOutOfBoundsException. By reducing index by 1 every time you are actually saying I need to (index - 1) hops to my destination node.
public class CharTest {
public static class Node {
private char content;
private Node nextNode;
public Node () {
content = '\0';
nextNode = null;
}
public Node (String str) {
Node temp = this;
for (int i = 0; i < str.length(); i++) {
temp.content = str.charAt(i);
temp.nextNode = new Node();
temp = temp.nextNode;
}
}
public char charAt(int index) {
if (index == 0) {
return content;
} else if (index < 0 || nextNode == null) {
throw new IndexOutOfBoundsException();
}
return nextNode.charAt(index - 1);
}
}
public static void main(String[] args) {
Node test = new Node("StackOverflow");
for (int i = 0; i < 13; i++) {
System.out.print(test.charAt(i));
}
System.out.println();
}
}
I will leave making a toString() method either iteratively or recursively an exercise to the reader. But using a StringBuilder or a char[] would be a good idea, because of a performance reasons.

trim() method for linked list

I have a question, I've looked around on the internet but couldn't find an example. But making a String trim() method in java (remove lead/trailing whitespace), I know the basic code for this is:
public LString trim(){
int i = this.size;
int j = 0;
int k = this.offset;
char[] arrayOfChar = this.data;
while ((j < i) && (arrayOfChar[(k + j)] <= ' '))
++j;
while ((j < i) && (arrayOfChar[(k + i - 1)] <= ' '))
--i;
return (((j > 0) || (i < this.size)) ? substring(j, i) : this);
}
But, how would you write this same method, but applied to a linked list? More specifically, a linked list that uses a Node class.
Here is what I did....correct me if this is wrong...I'll include relevant class information that pertains to the question.
public class LString{
private Node front = null; //first val in list
private Node back; //last val in list
private int size = 0;
private int i;
private int offset;
public LString(){
//construct empty list
Node LString = new Node();
front = null;
}
.......//skip down some methods to this one
//returns new lstring that is slice of lstring
//contains an endIndex as well
public LString substring(int beginIndex, int endIndex){
Node current = this.front;
int size = 0;
while(current != null && size < beginIndex){
size++;
current = current.getNext();
}
front = new Node();
front.setData(current.getData());
Node ocurrent = front;
while(current != null && size < endIndex){
current = current.getNext();
Node curr2 = new Node();
curr2.setData(current.getData());
ocurrent.setNext(curr2);
ocurrent = curr2;
size++;
}
ocurrent.setNext(null); //set next val to null to term string
return this;
}
public LString trim(){
String lstr;
int i = this.size;
int m = this.offset;
int k = charAt(m);
Node current = front;
while(current != null){
current = current.getNext();
if(current.data > '\u0020'){
return this;
} else if(current.data < '\u0020'){
LString lstring = new LString(); //this worked!?
return lstring;
}
}
return this.substring(k, m+1);
}
...............................................................
//My Node class:
public class Node{
public char data;
public Node next;
//constructors from page 956
public Node()
{
this('\0',null); //'\0' is null char for java
}
public Node(char initialData, Node initialNext)
{
data = initialData;
next = initialNext;
}
}
(If you are unfamiliar with the node class, it basically just creates a singly linked node to use as your links between data in your linked list class)
I've never seen an example or anything, so I thought I'd ask the community.
Assuming that
by trimming the list you want to remove leading and trailing elements that are null
and under "linked list that uses a Node class" you mean java.util.LinkedList
You should keep in mind that in java internal implementation of LinkedList is not exposed (note: java.util.LinkedList.Node has private access modifier), all modifications are performed through methods of iterator and LinkedList itself.
Implementation would be:
public static void trim (LinkedList list){
if (list == null || list.size() == 0) return;
Object element = null;
ListIterator i = list.listIterator();
while (i.hasNext() && element == null) {
element = i.next();
if (element == null) {
i.remove();
}
}
element = null;
i = list.listIterator(list.size());
while (i.hasPrevious() && element == null) {
element = i.previous();
if (element == null) {
i.remove();
}
}
}
However if you are reimplementing mutable strings via linked list as an exercise
(if not as an exercise then stop right there and use StringBuilder or StringBuffer), then, assuming that you implement it with doubly linked list, it will go like this:
EDIT: my bad, you can iterate to the first non-empty element and set reference directly to it, updated algorithm
Fetch first element
While fetched element is empty fetch next
Set head reference to the last fetched element, set last fetched element's prev reference to null
Fetch last element
While fetched element is empty fetch previous
Set tail reference to the last fetched element, set last fetched element's next reference to null
UPDATE With code you provided try something like this (since you are using singly-linked list, it is slightly different then the one described above):
public void trim(){
//early out if empty
if (front == null || back==null) return;
Node current = front;
//looking for the first non-empty element
while(current != null && current.data<'\u0020' ){
current = current.next;
}
//left trim
this.front = current;
//looking for last non-empty element
while (current!=null&&current.next!=null&&current.next.data>'\u0020'){
current = current.next;
}
//right trim
this.back = current;
if (current!=null){
current.next = null;
}
}
Assuming you just want to trim each String in a LinkedList, why not just iterate over each item?
LinkedList<String> myNodes = new LinkedList<String>();
myNodes.add('This is a node ');
myNodes.add(' another node '));
for (String s : myNodes){
s.trim();
}

Assignment on sorting a list

I'm very close to being done, but can't quite figure out how to tie everything together. I have the separate methods responsible for their particular task, but i feel like my cohesion is really bad. not real sure how they tie together and what needs to be called in main. The goal here is to read a text file from the command line and list the words in the story lexicographically.
% java Ten < story.txt
Word Occurs
==== ======
a 21
animal 3
.
.
.
zebra 1
%
Here's my code thus far:
import java.util.Scanner;
public class Ten2
{
public static void main(String [] arg)
{
Scanner input = new Scanner(System.in);
String word;
List sortedList = new List();
word = nextWord(input);
while (word!=null) {
sortedList.insert(word);
word = nextWord(input);
}
sortedList.printWords();
}
private static String nextWord(Scanner input)
{
// return null if there are no more words
if (input.hasNext() == false )
return null;
// take next element, convert to lowercase, store in s
else {
String s = input.next().toLowerCase() ;
// empty string
String token = "";
// loop through s and concatonate chars onto token
for (int i =0; i < s.length(); i++) {
if (Character.isLetter(s.charAt(i)) == true)
token = token + s.charAt(i);
else if (s.charAt(i) == '\'' )
token = token + s.charAt(i);
else if (s.charAt(i) == '-')
token = token + s.charAt(i);
}
return token;
}
}
}
class List
{
/*
* Internally, the list of strings is represented by a linked chain
* of nodes belonging to the class ListNode. The strings are stored
* in lexicographical order.
*/
private static class ListNode
{
// instance variables for ListNode objects
public String word;
public ListNode next;
public int count;
// Listnode constructor
public ListNode(String w, ListNode nxt)
{
word = w; // token from nextWord()?
next = nxt; // link to next ListNode
count = 1; // number of word occurences
}
}
// instance variables for List object
private ListNode first;
private int numWords;
// constructor postcondition: creates new Listnode storing object
public List()
{
first = null; // pointer to ListNode?
numWords = 0; // counter for nodes in list
}
// Insert a specified word into the list, keeping the list
// in lexicographical order.
public void insert(String word)
{
// check if first is null
if (first == null) {
ListNode newNode;
newNode = addNode(word, null);
first = newNode;
}
// else if (first is not null) check if word matches first word in List
else if (word.equals(first.word)) {
// increase count
first.count++;
}
// else (first is not null && doesn't match first word)
else {
ListNode newNode;
ListNode current;
current = first;
ListNode previous;
previous = null;
int cmp = word.compareTo(current.word);
/*
* Fist two cases of empty list and word already existing
* handled in above if and else statements, now by using compareTo()
* method between the words, the insertion postion can be determined.
* Links between ListNode variables current and previous need to be
* modified in order to maintain the list
*/
// loop as long as value comparing to is positive
// when compareTo() returns positive this means the "word" parameter is greater than the word in the list
while ((cmp >0) && (current.next != null)) {
previous = current;
current = current.next;
cmp = word.compareTo(current.word);
}
// insert after current at end of list
if ((cmp >0 && current.next == null)) {
newNode = addNode(word, null);
current.next = newNode;
}
// increments count when word already exists
else if (cmp==0) {
current.count++;
}
// else (cmp < 0) we insert BEFORE current
else {
newNode = addNode(word, current);
// first node in list comes after new word
if (previous == null) {
first = newNode;
}
else {
// inserting new word in middle of list
previous.next = newNode;
}
}
}
}
// method to add new ListNode and increase counter
private ListNode addNode(String word, ListNode next)
{
ListNode newNode = new ListNode(word, next);
numWords++;
return newNode;
}
// Returns a string array that contains all the words in the list.
public String[] getWords()
{
String[] Words = new String[numWords];
ListNode current = first;
int i =0;
while (current != null) {
Words[i] = current.word;
current = current.next;
i++;
}
return Words;
}
// Returns an int array that contains the number of times
// each word occurs in the list.
public int[] getNumbers()
{
int[] Numbers = new int[numWords];
ListNode current = first;
int i =0;
while (current != null) {
Numbers[i] = current.count;
current = current.next;
i++;
}
return Numbers;
}
// Outputs the string array and int array containing all the
// words in the list and the number of times each occurs.
public void printWords()
{
int[] Numbers = getNumbers();
String[] Words = getWords();
System.out.println("Word \t \t Occurs");
System.out.println("==== \t \t ======");
for (int i =0; i < numWords; i++) {
System.out.println(Words[i] + " \t " + Numbers[i]);
}
}
}
Well, I would start by defining what you want your program to do, which you've already done:
The goal here is to read a text file from the command line and list the words in the story lexicographically.
You're main function does this almost. Basically, what you need is a loop to tie it together:
public static void main(String [] arg)
{
// print out your initial information first (i.e. your column headers)
// ...
List sortedList = new List();
String word = nextWord();
// now, the question is... what is the end condition of the loop?
// probably that there aren't any more words, so word in this case
// will be null
while (word != null)
{
sortedList.insert(word);
word = nextWord();
}
// now, your list takes care of the sorting, so let's just print the list
sortedList.printWords();
}
I think that's all there is to it. Normally, I don't like to post solutions to homework questions, but in this case, since you already had all of the code and you just needed a little nudge to drive you in the right direction, I think it's fine.
There are a few things I noticed that are incorrect with your
Your list constructor has a 'void' return type - there should be no return type on constructors:
public List() //make an empty list
{
first = null;
numWords = 0;
}
The 'else' statement in this method is unneeded:
public static String nextWord()
{
if ( keyboard.hasNext() == false )
return null;
else {
String start = keyboard.next().toLowerCase() ;
String organized = "";
for (int i =0; i < start.length(); i++) {
if (Character.isLetter(start.charAt(i)) == true)
organized = organized + start.charAt(i);
else if (start.charAt(i) == '\'' )
organized = organized + start.charAt(i);
else if (start.charAt(i) == '-')
organized = organized + start.charAt(i);
}
return organized;
}
}
So, this should be:
public static String nextWord()
{
if ( keyboard.hasNext() == false )
return null;
String start = keyboard.next().toLowerCase() ;
String organized = "";
for (int i =0; i < start.length(); i++) {
if (Character.isLetter(start.charAt(i)) == true)
organized = organized + start.charAt(i);
else if (start.charAt(i) == '\'' )
organized = organized + start.charAt(i);
else if (start.charAt(i) == '-')
organized = organized + start.charAt(i);
}
return organized;
}
If you want to use a BufferedReader, it's pretty easy. Just set it up in your main method:
if (arg.length > 0)
{
// open our file and read everything into a string buffer
BufferedReader bRead = null;
try {
bRead = new BufferedReader(new FileReader(arg[0]));
} catch(FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.exit(0);
}
setupScanner(bRead);
}
Then, create a new method that sets up the scanner object:
public static void setupScanner(BufferedReader rdr)
{
keyboard = new Scanner(rdr);
}
And then just pass it in on the command line (i.e. java ten2 [filename])
import java.util.Scanner;
public class Ten2
{
public static void main(String [] arg)
{
Scanner input = new Scanner(System.in);
String word;
List sortedList = new List();
word = nextWord(input);
while (word!=null) {
sortedList.insert(word);
word = nextWord(input);
}
sortedList.printWords();
}
private static String nextWord(Scanner input)
{
// return null if there are no more words
if (input.hasNext() == false )
return null;
// take next element, convert to lowercase, store in s
else {
String s = input.next().toLowerCase() ;
// empty string
String token = "";
// loop through s and concatonate chars onto token
for (int i =0; i < s.length(); i++) {
if (Character.isLetter(s.charAt(i)) == true)
token = token + s.charAt(i);
else if (s.charAt(i) == '\'' )
token = token + s.charAt(i);
else if (s.charAt(i) == '-')
token = token + s.charAt(i);
}
return token;
}
}
}
class List
{
/*
* Internally, the list of strings is represented by a linked chain
* of nodes belonging to the class ListNode. The strings are stored
* in lexicographical order.
*/
private static class ListNode
{
// instance variables for ListNode objects
public String word;
public ListNode next;
public int count;
// Listnode constructor
public ListNode(String w, ListNode nxt)
{
word = w; // token from nextWord()?
next = nxt; // link to next ListNode
count = 1; // number of word occurences
}
}
// instance variables for List object
private ListNode first;
private int numWords;
// constructor postcondition: creates new Listnode storing object
public List()
{
first = null; // pointer to ListNode?
numWords = 0; // counter for nodes in list
}
// Insert a specified word into the list, keeping the list
// in lexicographical order.
public void insert(String word)
{
// check if first is null
if (first == null) {
ListNode newNode;
newNode = addNode(word, null);
first = newNode;
}
// else if (first is not null) check if word matches first word in List
else if (word.equals(first.word)) {
// increase count
first.count++;
}
// else (first is not null && doesn't match first word)
else {
ListNode newNode;
ListNode current;
current = first;
ListNode previous;
previous = null;
int cmp = word.compareTo(current.word);
/*
* Fist two cases of empty list and word already existing
* handled in above if and else statements, now by using compareTo()
* method between the words, the insertion postion can be determined.
* Links between ListNode variables current and previous need to be
* modified in order to maintain the list
*/
// loop as long as value comparing to is positive
// when compareTo() returns positive this means the "word" parameter is greater than the word in the list
while ((cmp >0) && (current.next != null)) {
previous = current;
current = current.next;
cmp = word.compareTo(current.word);
}
// insert after current at end of list
if ((cmp >0 && current.next == null)) {
newNode = addNode(word, null);
current.next = newNode;
}
// increments count when word already exists
else if (cmp==0) {
current.count++;
}
// else (cmp < 0) we insert BEFORE current
else {
newNode = addNode(word, current);
// first node in list comes after new word
if (previous == null) {
first = newNode;
}
else {
// inserting new word in middle of list
previous.next = newNode;
}
}
}
}
// method to add new ListNode and increase counter
private ListNode addNode(String word, ListNode next)
{
ListNode newNode = new ListNode(word, next);
numWords++;
return newNode;
}
// Returns a string array that contains all the words in the list.
public String[] getWords()
{
String[] Words = new String[numWords];
ListNode current = first;
int i =0;
while (current != null) {
Words[i] = current.word;
current = current.next;
i++;
}
return Words;
}
// Returns an int array that contains the number of times
// each word occurs in the list.
public int[] getNumbers()
{
int[] Numbers = new int[numWords];
ListNode current = first;
int i =0;
while (current != null) {
Numbers[i] = current.count;
current = current.next;
i++;
}
return Numbers;
}
// Outputs the string array and int array containing all the
// words in the list and the number of times each occurs.
public void printWords()
{
int[] Numbers = getNumbers();
String[] Words = getWords();
System.out.println("Word \t \t Occurs");
System.out.println("==== \t \t ======");
for (int i =0; i < numWords; i++) {
System.out.println(Words[i] + " \t " + Numbers[i]);
}
}
}

Categories

Resources