After calling the remove method, I call display and I'm getting an empty list; however, if I call the display method first it will display the correct list, I'm guessing the "first" value reached the end of the list or I got a broken node somewhere. Any help appreciated
public class LinkedList {
private Node first;
public LinkedList()
{
first = null;
}
//add students to the list
public void add(Student s)
{
Node newNode = new Node(s);
newNode.next = first;
first = newNode;
}
//remove duplicate records (return true if duplicate found)
public boolean remove(String fn, String ln)
{
Student remove;
boolean found = false;
int duplicate = 0;
while(first != null)
{
if(first.value.getFname().equals(fn) && first.value.getLname().equals(ln))
{
duplicate++;
if(duplicate > 1)
{
remove = first.value;
found = true;
}
}
first = first.next;
}
if(found)
return found;
else
return found;
}
//display list of student
public void display()
{
if(first == null)
System.out.println("List is empty!");
else
{
while(first != null)
{
System.out.println(first.value);
first = first.next;
}
}
}
}
main
public class Tester {
public static void main(String[] args) {
UnderGrad john = new UnderGrad("john", "doe", 2.7, "computer Science", "phisics");
UnderGrad jorge = new UnderGrad("jorge", "vazquez", 3.8, "computer Science", "programming");
UnderGrad john2 = new UnderGrad("john", "doe", 3.0, "Computer Engineering", "phisics");
Advisor jim = new Advisor("jim", "smith");
Grad jane = new Grad("jane", "doe", 3.0, "Electric Engineering", jim);
LinkedList students = new LinkedList();
students.add(john);
students.add(jorge);
students.add(john2);
students.add(jane);
System.out.println(students.remove("john", "doe"));
students.display();
}
}
output
run:
true
List is empty!
BUILD SUCCESSFUL (total time: 1 second)
You're using the linked list's head (first) as an iterator in the remove method. Instead, use a local variable:
for (Node current = first; current != null; current = current.next) {
if (current.value.getFname().equals(...
...
...
}
You have a few bugs. You cannot possibly mean this:
if(found)
return found;
else
return found;
That will always return true.
Set a breakpoint, draw a picture of the data structure (yes with a pencil) and watch the data structure in the debugger as you walk through the code.
If you get a code answer here, you will not be able to figure out the next assignment either. Sorry.
-Professor Archibald.
Step through your code and pay attention to what happens to the value of first after the first call to remove(...).
Hint: it will be null.
Since LinkedList.first is the only reference from LinkedList to its contents, after you call remove() the list has 'forgotten' what it contains.
the problem is in your add( ) method. look in there. :)
Related
(disclaimer: for school, so cant import other Java utilities)
So I have to merge sort on a linked list, and I have almost all of it down. Here it is:
class musicNode {
String track; // The name of the track
int played= 0; // The number of times played
int shuffleTag= 0; // For shuffling
musicNode next;
public musicNode() { // Here's how we construct an empty list.
next = null;
}
public musicNode(String t) {
track = t; next = null;
}
public musicNode(String t, musicNode ptr) {
track = t; next = ptr;
}
public boolean LTTrack(musicNode x) { // Compares tracks according to alphabetical order on strings
if (this.track.compareTo(x.track)<=0) return true;
else return false;
}
};
// This class represents a playlist;
// We assume that each track appears at most once in the playlist
public class MusicPlayer {
protected musicNode head = null; // Pointer to the top of the list.
int length=0; // the number of nodes in the list.
boolean debug= false;
public MusicPlayer() {
}
public void setToNull() {
head = null;
}
public boolean isEmpty() {
return head == null;
}
public musicNode head() {
return head;
}
void insertTrack(String name) { // Inserts a new track at the top of the list.
musicNode temp= new musicNode(name, head);
head= temp;
length++;
}
void sortTrack() { // TODO
musicNode main = this.head;
mergeSort(main);
}
public musicNode mergeSort(musicNode head) {
if ((head == null) || (head.next == null)){
return head;
}
musicNode left = head;
musicNode right = head.next;
while((right != null) && (right.next != null)){
head = head.next;
right = (right.next).next;
}
right = head.next;
head.next = null;
return merge(mergeSort(left), mergeSort(right));
}
There also this JUnit test:
public void testSortMixed() {
MusicPlayer trackList= new MusicPlayer();
trackList.insertTrack("d");
trackList.insertTrack("b");
trackList.insertTrack("e");
trackList.insertTrack("a");
trackList.insertTrack("c");
MusicPlayer trackListTwo= new MusicPlayer();
trackListTwo.insertTrack("e");
trackListTwo.insertTrack("d");
trackListTwo.insertTrack("c");
trackListTwo.insertTrack("b");
trackListTwo.insertTrack("a");
trackList.sortTrack();
musicNode tmp= trackList.head;
musicNode tmp2= trackListTwo.head;
for(int i=0; i< 5; i++){
assertEquals(tmp2.track, tmp.track);
tmp2= tmp2.next;
tmp=tmp.next;
}
}
The problem is that it sorts according to the last track you insert, and only from then on. So say you insert alphabets from a-f, but the last one you insert was "c", itll only show you "cdef". But if the last one was "a" then it works as intended.
So how it works is, when you insert a track it gets inserted onto the beginning of the list, not end, becoming the head. I feel like that may be whats messing it up, as I adapted and looked from my notes and online which insert at the bottom.
I dont know how to account for this though. Also I know it sorts based on what was inserted last (in the JUnit test above it sorts to "cde" because I created a main function and played around with it)
ANY help appreciated.
The key point is the second line in the method sortTrack:
void sortTrack() {
musicNode main = this.head;
this.head = mergeSort(main); // you forgot to set the head of linked list to the merged
}
I'd tested it in my laptop and everything goes okay now xD
I need help with a Circular Doubly Linked List in Java.
This is my code (originally coded by "sanfoundry"; it uses interfaces):
LinkedList.java:
public class LinkedList<T extends Comparable<T>> implements
ILinkedList<T> {
private ILinkedListNode<T> head;
private ILinkedListNode<T> end;
private int size;
public LinkedList() {
head = null;
end = null;
head = null;
size = 0;
}
#Override
public void append(T element) {
ILinkedListNode<T> tempNode = new LinkedListNode(element, null, null);
if (head == null) {
head = tempNode;
end = head;
} else {
tempNode.setPrev(end);
tempNode.setNext(tempNode);
end = tempNode;
}
size++;
}
// should return element at position "index"
#Override
public T get(int index) {
return null;
}
#Override
public int size() {
return size;
}
#Override
public ILinkedListNode<T> getHead() {
return head;
}
}
Now I need help to get it working. Did I do something wrong and what do I have to code in method "public T get (int index)"? Sorry, but I'm a Java noob :(
EDIT: Is this a possible solution?
public T get(int index) {
T element = null;
if (index == 0) {
element = head.getElement();
} else if (index == size()-1) {
element = head.getPrev().getElement(); // end.getElement() also possible
} else {
ILinkedListNode<T> temp = head;
for (int i = 0; i < index; i++) {
temp = temp.getNext();
}
element = temp.getElement();
}
return element;
}
You should traverse the LinkedList, keeping track of your current position as you go. When your current position is equal to the index passed in, then you can return the T from that node.
Read about traversing a linked list here.
Try making some test cases. Ideally you'll want to use a real test framework but using a normal main method could work. For example:
public static void main(String[] args) {
ILinkedList<String> a = new LinkedList<String>();
System.out.println(a.size()); // 0
System.out.println(a.getHead()); // null
a.append("foo");
System.out.println(a.size()); // 1
System.out.println(a.get(0)); // "foo"
System.out.println(a.get(1)); // decide yourself what this should result in
a.append("bar");
System.out.println(a.size()); // 2
System.out.println(a.get(0)); // "foo"
System.out.println(a.get(1)); // "bar"
a.append("baz");
System.out.println(a.size()); // 3
System.out.println(a.get(0)); // "foo"
System.out.println(a.get(1)); // "bar"
System.out.println(a.get(2)); // "baz"
}
Expand the test as necessary. See if the code returns what you expect it to, or if the code never returns, or throws an exception, etc.... The easiest way to check whether your code is running properly is, after all, to actually run it.
Hint: the code, as of this writing, has some errors.
Also, if the code can run as expected, consider:
Traversing the nodes backward if it's faster than forward.
Using a recursion instead of iteration.
So like the title says I'm trying to input a node in the third position of the linked list. The way I originally tried to do it was to insert two places down the list after numberOfItems was >= 3. I figured if I was getting an error it would be outputting the last 2 Players wrongly but it's just continuing to output Player 1. Can anybody point me to the right direction as to why this is happening?
Here is my linkedlist class
public class PlayerLinkedList extends ShellLinkedList
{
public PlayerLinkedList()
{
super();
}//end PlayerLinkedList constructor
public void insert(Player p)
{
if(numberOfItems >= 3)
{
PlayerNode pn = new PlayerNode(p);
head = pn;
pn.setNext(head.getNext().getNext());
numberOfItems++;
}
else
{
PlayerNode pn = new PlayerNode(p);
if(head == null)
{
head = pn;
}
pn.setNext(head);
head = pn;
numberOfItems++;
}
}//end insert method
public Player delete(int searchID) throws DataStructureException
{
PlayerNode current = head;
PlayerNode previous = null;
while(current != null && current.getPlayer().getID()!=searchID)
{
previous = current;
current = current.getNext();
}//end while
if(current == null) //not found
throw new DataStructureException(searchID + "not found: cannot be deleted");
else
{
if(current == head)
head = head.getNext(); //delete head
else
previous.setNext(current.getNext());
numberOfItems--;
return current.getPlayer();
}//end else
}//end delete
}//end class
Also just for reference here is my ShellLinkedList class
public abstract class ShellLinkedList
{
protected PlayerNode head;
protected int numberOfItems;
public ShellLinkedList()
{
head = null;
numberOfItems = 0;
}//end ShellLinkedList constructor
public int getNumberOfItems()
{
return numberOfItems;
}// end of getnumberOfItems
public boolean isEmpty()
{
return (numberOfItems==0);
}//end isEmpty
public String toString()
{
String listString="";
PlayerNode current = head;
for(int i = 0; i<numberOfItems && current != null; i++)
{
listString += current.getPlayer().toString()+"\n";
current = current.getNext();
}
return listString;
}//end toString
}//end class
My input is:
Player one = new Player(1, "Mike", "Mario");
Player two = new Player(2, "Brian", "Halo");
Player three = new Player(3, "John", "Minecraft");
Player four = new Player(4, "Thrall", "WoW");
Player five = new Player(5, "Scott", "Metroid");
list.insert(one);
list.insert(two);
list.insert(three);
list.insert(four);
list.insert(five);
System.out.println(list.toString());
And my output is:
id: 3 name: John game: Minecraft
id: 2 name: Brian game: Halo
id: 1 name: Mike game: Mario
id: 1 name: Mike game: Mario
id: 1 name: Mike game: Mario
There are a few problems with your code, your insert method behaves differently when numberOfItems >= 3 which is why you are not able to add more than 3 times. In that code block you are creating a new PlayerNode instance but you do not keep any reference to it.
You should also check whether you are expecting normal List#add behaviour which appends to the end of a list not the beginning.
I solved the issue by adding
head.getNext().setNext(pn);
after
pn.setNext(head.getNext().getNext());
I am working on an exercise and I ran into a problem.
In NodeList, create a static method Node arrayToNode(String[] arr)
which converts a String array into a list. Your method should create a first Node,
and then go through the rest of the array, creating a Node at each step, and using
append to put the created Node at the end of the list. Test this method on the
command line arguments. What happens if the array is empty?
Currently my code is like this
public static Node arrayToNode(String[] arr) {
Node first = new Node(arr[0]);
ArrayList<Node> list = new ArrayList<Node>();
for(int i=1; i<arr.length;i++){
list.add(new Node(arr[i]));
}
}
as you can see there is no return statement YET.
I am not sure if the person who wrote the exercise made a mistake by writing Node instead of void but I cannot ask him.
The append method is
public void append(Node fin){
if(next==null)
next=fin;
else
append(next);
}
and the instance variables and the constructor is as follows:
public String value;
public Node next;
public Node(String s){
value =s;
next=null;
}
I am quite unsure what it means to put the node at the end of the list as the ArrayList keeps on expanding.
Also, I have questions about using the deploying the append method as in how to even use it in the TestNode class.
Thanks for the comment.
I have now realized what the problem was and have made appropriate changes.
public static Node arrayToNode(String[] arr){
Node first = new Node(arr[0]);
for(int i=1; i<arr.length;i++){
Node nd = new Node(arr[i]);
nd.append(nd);
first.next=nd;
}
return first;
}
could you see if this is correct?
Unless I'm missing something, your append method should be this:
public void append(Node fin) {
if (next == null)
next = fin;
else
next.append(fin); // <- this line changed
}
That will append fin down the line until it reaches the end of the list while the way you have it in your OP will give infinite recursion.
If it's supposed to be that way then creating the list is very simple. You can just append each value to the original one.
public class Node {
public static void main(String[] args) {
Node begin = arrToLL(new String[] {
"hello 1", "hello 2", "hello 3", "hello 4", "hello 5"
});
while (begin != null) {
System.out.println(begin.val);
begin = begin.next;
}
}
static Node arrToLL(String[] arr) {
if (arr == null) {
return null;
} else if (arr.length == 0) {
return new Node("null");
}
int ind = 0;
Node begin = new Node(arr[ind++]);
while (ind < arr.length) {
begin.append(new Node(arr[ind++]));
}
return begin;
}
/* instance */
String val;
Node next;
Node(String val) { this.val = val; }
void append(Node ap) {
if (next == null) {
next = ap;
} else {
next.append(ap);
}
}
}
Output is:
hello 1
hello 2
hello 3
hello 4
hello 5
Inside the "to list" loop you could also "shuffle ahead" by assigning next to a variable like in my println loop. That way you aren't taking advantage of the "pass through".
public static Node arrayToNode(String[] arr){
Node first = new Node(arr[0]);
for(int i=1; i<arr.length;i++){
Node nd = new Node(arr[i]);
nd.append(nd); // <- appends nd to itself
first.next=nd; // <- always assigns the new value to first
}
return first;
}
That's getting closer but I've commented the two lines that are in err. I think what you will end up with is:
First Node with the first array element linked to
A second Node with the last array element linked to
Itself (the second Node)
You can do this without append but you need another variable to shuffle:
public static Node arrayToNode(String[] arr){
Node first = new Node(arr[0]);
Node current = first;
for(int i=1; i<arr.length;i++){
Node nd = new Node(arr[i]);
current.next = nd; // <- append the new node to the last
current = nd; // <- shuffle ahead to the new one
}
return first;
}
Otherwise if I'm correct in thinking append had an error you can do something closer to my main example (including the shuffle if you want and a for loop works just as well).
I'm trying to add a new Customer object (which should be node.data, not node) in sorted order by the customer object's name alphabetically. But it's not working. It's printing out the list in unsorted order (unchanged from original order).
public void add(Customer newNode, int dummy){
if (head == null){ // The first node
head = tail = this;
head.setData(newNode);
size=1;
return;
}else{
CustomerList last = null;
for(CustomerList node = head;
node != null && node.getData().toString().compareTo(newNode.name) < 0;
node = node.next){
last = node;
}
CustomerList newList = new CustomerList(newNode);
newList.setNext(last.next);
last.next = newList;
}
} // add
Input of Customer objects from txt file. Should print out again but in alphabetical order (customer name).
10121,Airgo Fresh ods,OH,870023
10125,Bird Out fittered ,MI,870023
10134,Kit river ,IL,870023
10167,Mouin Gontaods,OR,870021
10178,Theiasu El senter,CA,870022
Code which reads data from txt file and creates objects and adds to list:
public void byCustomerName()
{
records = null;
System.gc();
CustomerList.setHead(null);
records = new CustomerList();
try
{
String line;
StringTokenizer st;
String id, name, state, salesrep;
BufferedReader infile = new BufferedReader(new FileReader("Customer.txt"));
while ((line = infile.readLine()) != null)
{
st = new StringTokenizer(line, ",");
id = st.nextToken(",");
name = st.nextToken(",");
state = st.nextToken(",");
salesrep = st.nextToken(",");
records.add(new Customer(id, name, state, salesrep), 99);
}
infile.close();
} catch (IOException x) { System.err.println(x); }
} // byCustomerName
I think your code has all sorts of problems in it. For one, I don't ever see you updating head or tail if you replace the first or last element. Also, there is no check for last potentially being null. It'll be hard to say more without knowing how some of your underlying CustomerList items work.
I actually did this same exact assignment two semesters ago but decided to take the class again because I was unable to take the final. But since no programming for two semesters, I'm now extremely rusty. I'm just going to give up for now and use my old solution that I came up for the first time I took the class.
Solution:
public void add(Customer newNode, int dummy) {
CustomerList before = null;
boolean inserted = false;
if (head == null) { //first node
head = tail = this;
head.setData(newNode);
return;
} else {
CustomerList curr = head;
while(curr != null) {
String currentName = curr.getData().getName();
String newNodeName = newNode.name;
if (currentName.compareToIgnoreCase(newNodeName) > 0) {
CustomerList cList = new CustomerList(newNode);
cList.setNext(curr);//curr is greater than clist, therefore cList's next element is curr
if(before!=null)
before.setNext(cList);
else { //this tests the case when
//the newNode goes at the BEGINNING of the list
head = cList;
}
curr = cList;
inserted = true;
return;
}
before = curr;
curr = curr.next;
}
}
if(!inserted) {
add(newNode);
}
} // add
As Sudhanshu already told you can use Collections.sort(-) method on your List object or as an alternate just use TreeSet in case if you want unique objects. Its better to utilize inbuilt methods of java API as these are less error prone and more reliable, at the same time you can reduce your code and time to mug up in it.