I use this remove method to remove the 3rd element of list. But it removes all the elements before the specified index. So if Jhon, Sam, Philip, Emma are the list elements, if I remove 3rd element, the only remaining element is Nick. How can I fix this?
import java.util.*;
class List {
Customer listPtr;
int index;
public void add(Customer customer) {
Customer temp = customer;
if (listPtr == null) {
listPtr = temp;
index++;
} else {
Customer x = listPtr;
while (x.next != null) {
x = x.next;
}
x.next = temp;
index++;
}
}
public void remove(int index) {
int size = size();
Customer tmp = listPtr, tmp2;
int i = 0;
while (i != size) {
if ((i + 1) == index) {
tmp2 = tmp;
listPtr = tmp2.next;
break;
}
tmp = tmp.next;
++i;
}
}
public int size() {
int size = 0;
Customer temp = listPtr;
while (temp != null) {
temp = temp.next;
size++;
}
return size;
}
public void printList() {
Customer temp = listPtr;
while (temp != null) {
System.out.println(temp);
temp = temp.next;
}
}
}
class DemoList {
public static void main(String args[]) {
List list = new List();
Customer c1 = new Customer("10011", "Jhon");
Customer c2 = new Customer("10012", "Sam");
Customer c3 = new Customer("10013", "Philip");
Customer c4 = new Customer("10014", "Emma");
list.add(c1);
list.add(c2);
list.add(c3);
list.add(c4);
list.remove(3);
System.out.println(list.size());
list.printList();
}
}
class Customer {
String id;
String name;
Customer next;
public Customer(String id, String name) {
this.id = id;
this.name = name;
}
public String toString() {
return id + " : " + name;
}
public boolean equals(Object ob) {
Customer c = (Customer) ob;
return this.id.equals(c.id);
}
}
There are several problems with the remove() method.
First of all, you should only be changing listPtr if index == 0.
In all other cases, you need to adjust node.next of the node at position index - 1.
P.S. Having index as a data member of List looks like an accident waiting to happen.
public void remove(int index) {
if (i == 0) {
// TODO: do some checks (listPtr is set, has next...)
listPtr = listPtr.next;
}
else {
int currentIndex = 0;
Customer currentElement = listPtr;
while (currentIndex != size()) {
if ((currentIndex + 1) == index) {
currentElement.next = currentElement.next.next;
break;
}
currentElement = currentElement.next;
currentIndex++;
}
}
}
Related
I'm working on creating my own LinkedList. My L.L. worked 100% when running simple I/O from command line, but now I have to implement it into my Student class. It adds a Student, displays a student, won't remove Student # Node, in-fact, it won't even read THE ONLY student in the list! All BlueJ tells me is this:
Error(s) found in class
It's some kind of connection logic and for two days I have tried everything I can think of.
Here is my Student, removeStudent(), Class Node, and LinkedList
public class Node
{
private Student item;
private Node node;
private int thisIdx;
private String fullName,firstName,lastName,gender,major,netId;
private int uin,age;
private double gpa;
public Node()
{
this(null,null);
}
public Node(Student stu,Node node)
{
this.item = stu;
this.setNext(node);
thisIdx = totalCount() - 1;
this.setNodeIndex(thisIdx);
}
public int getIndex()
{
return this.thisIdx;
}
public void setNodeIndex(int idx)
{
thisIdx = idx;
}
public void setNext(Node n1)
{
node = n1;
}
public Node getNext()
{
return node;
}
public boolean isEmpty()
{
return ( this == null);
}
public Student display()
{
return this.item;
}
public void setItem(Links data)
{
this.item = data;
}
public Student getItem()
{
return item;
}
}
public class Links<E>
{
private Node start,tail,next;
private int size=0; private int idx; private String item;
private Student student;
/**
* Constructor for objects of class MyLList
*/
public Links()
{
start = new Node();
}
public void addLink(E object)
{
tail = start;
start = new Node(object,tail);
size++;
}
public int totalCount()
{
return size;
}
public Node get(Node node)
{
return node;
}
public void set(Node node)
{
node.setNext(node.getNext());
}
public String emptyMessage()
{
String message = "Your student is not in the student files.\n\n";
return message;
}
public Node getStart()
{
Node curr = start;
return curr;
}
public void clear()
{
Node start = new Node();
size = 0;
}
public void removeLink(Node node) throws NullPointerException
{
try{
Node del,curr,next,prev;
prev = start; curr = start;
while ( curr != node )
{
if ( curr.getNext() == null)
{
throw new NullPointerException();
}else
{
prev = curr;
curr = curr.getNext();
}
}
if ( curr == start)
{
start = start.getNext();
}else
{
prev.setNext(curr.getNext());
curr = curr.getNext();
}
}catch (NullPointerException npe)
{
Lab_12.viewer.append("Breaking in Links" + "\n\n");
}
}
public void sort()
{
Node curr,next,temp,prev;
prev = start;
curr = start;
next = start.getNext();
int move;
Student[] copyToThis = new Student[this.size];
if (this.totalCount() > 1)
{
//copy contents of linked list to array
for (int i=0; i < this.totalCount(); i++)
{
if ( !curr.isEmpty() )
{
Student copyItem = curr.getItem();
copyToThis[i] = copyItem;
prev = curr;
if ( curr.getNext() != null)
{
curr = curr.getNext();
}else
{
prev.setNext(curr.getNext());
}
}
for (int k=0; k < copyToThis.length-1;k++)
{
int tempIdx = k;
if ( copyToThis[k] == null )
{
copyToThis[tempIdx] = copyToThis[k];
while ( k < copyToThis.length-1 )
{
copyToThis[k] = copyToThis[k+1];
copyToThis[k+1] = copyToThis[tempIdx];
tempIdx = k;
k++;
}
}
}
}
//sort array in reverse order -----> LinkedList is FIFO structure
for (int i =0; i < copyToThis.length; i++)
{
Student first = copyToThis[i];
Student tempObject = copyToThis[i];
int tempIndex = i;
for (int k=i; k < copyToThis.length; k++)
{
if (copyToThis[k] != null)
{
move = copyToThis[k].getFullName().compareToIgnoreCase(first.getFullName());
if (move > 0)
{
first = copyToThis[k];
tempIndex = k;
}
}else
{
break;
}
}
if (first == null )
{
break;
}else
{
move = first.getFullName().compareToIgnoreCase(tempObject.getFullName());
if (move > 0 )
{
copyToThis[i] = first;
copyToThis[tempIndex] = tempObject;
tempIndex = i;
}
}
}
//clear list before setting in alphabetical order -----> if not cleared, list will append not replace
this.clear();
for (int i=0; i < copyToThis.length; i++)
{
if ( copyToThis[i] != null)
{
this.addLink(copyToThis[i]);
}
}
}
//test print of array
/*for (int i=0; i < copyToThis.length; i++)
{
Lab_12.viewer.append(i + ") " + copyToThis[i]);
}*/
}
public String displayFirst()
{
Node first = start;
String showFirst = first.getItem().toString();
return showFirst;
}
public void display()
{
String showThisView;
Node prev,curr,next;
prev = start; curr = prev; next = start.getNext();
for (int i=0; i < this.totalCount();i++)
{
if (!curr.isEmpty())
{
showThisView = curr.getItem().toString();
Lab_12.viewer.append(showThisView + "\n\n");
}else
{
prev.setNext(curr.getNext());
curr = curr.getNext();
next = next.getNext();
}
prev = next;
curr = prev;
if (prev.getNext() != null)
{
next = prev.getNext();
}else
{
break;
}
}
}
public String search(String data) throws NullPointerException
{
try{
Node p = start;
while(p!=null)
{
if ( !p.getItem().equals(data) )
{
p = p.getNext();
}else
{
return data;
}
}
}catch (NullPointerException npe)
{
System.out.println("Your item is not in the list\n");
}
}
}
public void removeStudent(Links<Student> studentLinks1)
{
try
{
String toRemove;
int choice;
int counter =0;
toRemove = JOptionPane.showInputDialog(null,"Enter the student last name to be removed:");
String find;
int uin;
for (Node i=studentLinks1.getStart(); i.getNext() != null; i.setNext(i.getNext()) )
{
if ( studentLinks1.get(i).getFullName().equalsIgnoreCase(toRemove) )
{
counter++;
}
}
if (counter > 1)
{
viewer.append("You have more than one student with the last name, " + toRemove + ".\n\n");
viewer.append("Students with last name: " + toRemove + "\n\n");
/*
* create array to hold current matching indexes;
*/
for (Node i=studentLinks1.getStart(); i.getNext() !=null; i.setNext(i.getNext()))
{
find = studentLinks1.get(i).getLastName().toString();
if ( studentLinks1.get(i).getLastName().equalsIgnoreCase(toRemove) )
{
uin = studentLinks1.get(i).getUin();
viewer.append("Name: " + studentLinks1.get(i).getFullName().toString() +
"\n\tUIN: " + uin + "\n\n");
}
}
/*
* Get user input for student removal & remove student
*/
int match = 0;
choice = Integer.parseInt(JOptionPane.showInputDialog(null,"Enter the UIN of the student you wish to remove: "));
for (Node i=studentLinks1.getStart(); i.getNext() !=null ; i.setNext(i.getNext()))
{
uin = studentLinks1.get(i).getUin();
if ( choice != uin)
{
match++;
}
if (match == Links.totalCount() )
{
throw new InputMismatchException();
}
}
for (Node i=studentLinks1.getStart(); i.getNext() != null; i.setNext(i.getNext()))
{
if ( studentLinks1.get(i).getUin() == choice )
{
String name = studentLinks1.get(i).getFullName().toString();
viewer.append(name + " " + " has been removed from the student file." + "\n\n");
studentLinks1.removeLink(i);
Student.removeStudent();
Student.getStudentCount();
}
}
viewer.append("There is " + Student.getStudentCount() + " student(s) in your student file." + "\n\n");
if ( counter == 1)
{
for (Node i=studentLinks1.getStart(); i.getNext() != null; i.setNext(i.getNext()))
{
if ( studentLinks1.get(i) != null && studentLinks1.get(i).getLastName().equalsIgnoreCase(toRemove) )
{
String firstName = studentLinks1.get(i).getFirstName().toString();
String lastName = studentLinks1.get(i).getLastName().toString();
viewer.append(firstName + " " + lastName + " has been removed from the student file." + "\n\n");
studentLinks1.removeLink(i);
Student.removeStudent();
}
}
viewer.append("There is " + Student.getStudentCount() + " student(s) in your student file." + "\n\n");
}else
{
viewer.append(studentLinks1.emptyMessage());
}
}
}catch (InputMismatchException ime )
{
viewer.append("You entered an incorrect student id.\nPlease re-enter the student id.");
throw ime;
}
}
As you can see in my removeStudent(), I have formatted the for loops to iterate through the L.L. with the nodes themselves. If in LL class, I can perform node.getElement() with results, then why will that not work in my main in Student? I have tried
studentLinks1.get(I).getItem().getElement();
studentLinks1.get(i.getElement())
I am seriously at a loss with this one. Any help is much appreciated!
I'm working on an assignment where I need to create a Linked List given a template. For each new node that is created, I need to print out the updated list. However, up until this point, I've been stumped on how to print out the linked list. Can anyone figure out what am I doing wrong? What I currently have just prints out the number that has been created, followed by blank space, instead of the entire list up to that point.
NumberList.java
import java.util.*;
public class NumberList {
private Node head;
public NumberList() {
}
public void insertAtHead(int x) {
Node newNode = new Node(x);
if (head == null)
head = newNode;
else {
newNode.setNext(head);
head = newNode;
}
}
public void insertAtTail(int x) {
}
public void insertInOrder(int x) {
}
public String toString() {
Node tmp = head;
String result = "";
while (tmp.getNext() != null) {
result += tmp.toString() + " ";
}
return result;
}
//---------------------
// test methods
//---------------------
public static void testInsertAtHead() {
Random r = new Random();
int n = 20;
int range = 1000;
NumberList list = new NumberList();
for (int i=1; i<=n; i++) {
int x = r.nextInt(range);
list.insertAtHead(x);
System.out.println("" + x + ": " + list);
}
}
public static void testInsertAtTail() {
Random r = new Random();
int n = 20;
int range = 1000;
NumberList list = new NumberList();
for (int i=1; i<=n; i++) {
int x = r.nextInt(range);
list.insertAtTail(x);
System.out.println("" + x + ": " + list);
}
}
public static void testInsertInOrder() {
Random r = new Random();
int n = 20;
int range = 1000;
NumberList list = new NumberList();
for (int i=1; i<=n; i++) {
int x = r.nextInt(range);
list.insertInOrder(x);
System.out.println("" + x + ": " + list);
}
}
public static void main(String[] args) {
//testInsertAtHead();
//testInsertAtTail();
testInsertInOrder();
}
}
Node.java
class Node {
private int number;
private Node next;
public Node(int n) {
this.number = n;
this.next = null;
}
public Node getNext() {
return next;
}
public int getNumber() {
return number;
}
public void setNext(Node n) {
if (n == null)
return;
n.setNext(next);
next = n;
}
public String toString() {
return number + "";
}
}
I think your toString() is looping endlessly once the second element is added. You need to move your pointer to the next node:
public String toString() {
Node tmp = head;
String result = "";
while (tmp != null) {
result += tmp.toString() + " ";
tmp = tmp.getNext();
}
return result;
}
I've also updated the condition to handle a null head.
On my count method, i am trying to compare the object being sent with the object calling it, and I have no idea why i can not cal o.get(i) to get the value for Object o being passed. It tells me the method cannot be found even though i can call get(i) normally. Any ideas how i can get the value for the object getting passed so i can compare them?
public class GenericLinkedList<E> implements List<E> {
private class Node<E>{
private E data;
private Node<E> next;
}
private E data;
private Node<E> head = null;
private int size = 0;
private Node<E> nodeAt(int index){
Node<E> curNode = head;
int curIndex = 0;
while(curIndex < index){
curNode = curNode.next;
curIndex++;
}
return curNode;
}
#Override
public E get(int index) {
return nodeAt(index).data;
}
#Override
public void add(E value) {
Node<E> node = new Node<E>();
node.data = value;
if(size == 0){
head = node;
}else{
Node<E> curNode = nodeAt(size - 1);
curNode.next = node;
}
size++;
}
public void add(int index, E value){
Node<E> node = new Node<E>();
node.data = value;
if(size == 0){
head = node;
}else if(index == 0){
node.next = head;
head = node;
}else{
Node<E> curNode = nodeAt(index - 1);
node.next = curNode.next;
curNode.next = node;
}
size++;
}
#Override
public void remove(int index) {
if(index == 0){
head = head.next;
}else{
Node<E> curNode = nodeAt(index - 1);
curNode.next = curNode.next.next;
}
size--;
}
#Override
public void set(int index, E value) {
nodeAt(index).data = value;
}
public String toString(){
String s = "";
Node<E> curNode = head;
s += curNode.data +" -> ";
while(curNode.next != null){
curNode = curNode.next;
s += curNode.data +" -> ";
}
s += "null";
return s;
}
public void clear() {
for (int i = 0; i < size; i++)
set(i, null);
size = 0;
}
#Override
public void removeAll(E o)//Clears out the array object by setting everything to null
{
for(int i = 0; i < this.size; i++)
{
}
}
#Override
public int count(Object o)
{
System.out.println(o);
int count = 0;
for(int i = 0; i< size;i++)
{
if(get(i) == o.get(i))
{
count++;
}
}
return count;
/*int count = 0;
for(int i = 0;i<this.size;i++)
{
for(int j = 0;i<size;j++)
{
}
}
return count;*/
}
public void reverse()
{
int x = size;
for(int i = 0; i < this.size; i++)
{
E temp = this.get(x);
this.set(x, get(i));
this.set(i, temp);
x++;
}
}
public Object subList(int beginIndex, int endIndex)
{
int j = 0;
GenericLinkedList<E> LinkedList = new GenericLinkedList<E>();
if(beginIndex == endIndex)
return LinkedList;
else if(beginIndex > endIndex||endIndex>size||beginIndex<0)
{
return null;
}
else
{
for(int i = beginIndex; i <= endIndex;i++)
{
LinkedList.add(get(i));
j++;
}
}
return LinkedList;
}
public static void main(String[] args) {
GenericLinkedList<Integer> myList = new GenericLinkedList<Integer>();
myList.add(4);
myList.add(7);
myList.add(123123);
System.out.println(myList.get(2));
GenericLinkedList<Integer> myList2 = new GenericLinkedList<Integer>();
myList2.add(4);
myList2.add(7);
myList2.add(8);
myList2.add(3,999);
System.out.println(myList2);
System.out.println(myList.count(myList2));
//System.out.println(myList2);
// myList2.clear();//Testing our clear class
// System.out.println(myList2);
//System.out.println(myList2.subList(1, 3));//Testing our clear class
// System.out.println(myList2);
}
}
You have a problem when trying to call o.get() because it is an object of the base type Object which has no method get defined. To get the proper result you have two possible solutions....
The short solution is to type cast.
((GenericLinkedList<Object>)o).get(i)
Or a more easily readable solution is to change the signature of your count method:
public int count(GenericLinkList<E> list) {
...
}
Change your count method to public int GenericLinkedList(Object o)
If you use Object as the type of the parameter, you can only call the methods which are available on Object.
I'm having a problem with implementing a very simple HashTable using an array. The problem is that the first Item put in the HashTable is always AVAILABLE. Maybe you guys can see what is going wrong. This is the HashTable class:
public class HashTable {
private Item[] data;
private int capacity;
private int size;
private static final Item AVAILABLE = new Item("Available", null);
public HashTable(int capacity) {
this.capacity = capacity;
data = new Item[capacity];
for(int i = 0; i < data.length; i++) {
data[i] = AVAILABLE;
}
size = 0;
}
public int size() {
return size;
}
public int hashThis(String key) {
return key.hashCode() % capacity;
}
public Object get(String key) {
int hash = hashThis(key);
while(data[hash] != AVAILABLE && data[hash].key() != key) {
hash = (hash + 1) % capacity;
}
return data[hash].element();
}
public void put(String key, Object element) {
if(key != null) {
size++;
int hash = hashThis(key);
while(data[hash] != AVAILABLE && data[hash].key() != key) {
hash = (hash + 1) % capacity;
}
data[hash] = new Item(key, element);
}
}
public Object remove(String key) {
// not important now.
throw new UnsupportedOperationException("Can't remove");
}
public String toString() {
String s = "<HashTable[";
for(int i = 0; i < this.size(); i++) {
s += data[i].toString();
if(i < this.size() - 1) {
s += ",";
}
}
s += "]>";
return s;
}
}
For more clarity, this is the Item class:
public class Item {
private String key;
private Object element;
public Item(String key, Object element) {
this.setKey(key);
this.setElement(element);
}
public String key() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public Object element() {
return element;
}
public void setElement(Object element) {
this.element = element;
}
public String toString() {
String s = "<Item(";
s += this.key() + "," + this.element() + ")>";
return s;
}
}
To give an example:
HashTable ht = new HashTable(10);
ht.put("1", "a");
The output of toString() after putting has to be:
"<HashTable[<Item(1,a)>]>"
but I get:
"<HashTable[<Item(Available,null)>]>"
update: I should probably mention that the next Item gets put correctly and the one after that is not again.
I think the problem is in your toString method. You loop for 0 - size when size = 1 so once so you only print out the first value in your hashTable problem is the first value in your hash table is not a real value it's an AVAILABLE you have to do something like this
EDIT: Sorry I forgot to move the index over.
public String toString() {
String s = "<HashTable[";
int i = 0;
int count = 0;
while(count < this.size()) {
//Skip the AVAILABLE cells
if(data[i] == AVAILABLE) {
i++;
continue;
}
s += data[i].toString();
if(count < this.size() - 1) {
s += ",";
}
count++;
}
s += "]>";
return s;
}
Try this for toString() if still interested in the solution, I ran it and its fine:
public String toString()
{
String s = "<HashTable[";
for (int i = 0; i < this.capacity; i++)
{
if (data[i].Element != null)
{
s += data[i].toString();
if (i < this.size - 1)
{
s += ",";
}
}
}
s += "]>";
return s;
}
There seems to be a problem in add method of the class I have written.. I want to make a SortedList using an array, but I can't figure out what the problem is. This is my code:
public class SortedList {
private Integer[] elements;
private int size;
private int capacity;
public SortedList(int cap) {
elements = new Integer[cap];
if (cap > 0)
{
cap = capacity;
}
else
capacity = 10;
}
public boolean isEmpty()
{
return size == 0;
}
public boolean isFull()
{
return size == capacity;
}
public int size()
{
return size;
}
public void doubleCapacity()
{
capacity = capacity * 2;
}
public void add(Integer el)
{
if(this.isEmpty())
{
elements[0] = el;
size++;
}
else if(this.isFull())
{
this.doubleCapacity();
for(int i = 0; i<this.size(); i++)
{
if(el >= elements[i])
{
elements[i+2] = elements[i+1];
elements[i+1] = el;
}
else
{
elements[i+1] = elements[i];
elements[i] = el;
}
}
size++;
}
else
{
for(int i = 0; i<this.size(); i++)
{
if(el >= elements[i])
{
elements[i+2] = elements[i+1];
elements[i+1] = el;
}
else
{
elements[i+1] = elements[i];
elements[i] = el;
}
}
size++;
}
}
public String toString()
{
String s = "";
s = s + "<SortedList[";
for(int i = 0; i < this.size(); i++)
{
s = s + elements[i];
if(i < this.size()-1)
s = s + ",";
}
s = s + "]>";
return s;
}
public static void main(String[] args)
{
SortedList sl = new SortedList(5);
sl.add(3);
//sl.add(2);
sl.add(4);
sl.add(5);
// sl.add(6);
System.out.println(sl.toString());
}
}
My code works if I only add 2 Integers to my list, but when I try to add the numbers 3,4,5 then I get 3,5,5...
What can be the problem? Thanks..
public class SortedList {
private Integer[] elements;
private int size=0;
private int capacity;
public SortedList(int cap) {
elements = new Integer[cap];
if (cap > 0)
{
capacity = cap;
}
else
capacity = 10;
}
public boolean isEmpty()
{
return size == 0;
}
public boolean isFull()
{
return size == capacity;
}
public int size()
{
return size;
}
public void doubleCapacity()
{
capacity = capacity * 2;
}
public void add(Integer el) throws Exception{
elements[size] = el;
size++;
if(size>capacity){
throw new Exception("Size Exceeded");
}
}
public String toString()
{
sort();
String s = "";
s = s + "<SortedList[";
for(int i = 0; i < this.size(); i++)
{
s = s + elements[i];
if(i < this.size()-1)
s = s + ",";
}
s = s + "]>";
return s;
}
public void sort(){
for (int i=0; i <size()-1; i++) {
if (elements[i] > elements[i+1]) {
// exchange elements
int temp = elements[i];
elements[i] = elements[i+1];
elements[i+1] = temp;
}
}
}
public static void main(String[] args)
{
try {
SortedList sl = new SortedList(5);
sl.add(3);
//sl.add(2);
sl.add(6);
sl.add(5);
// sl.add(6);
System.out.println(sl.toString());
} catch (Exception ex) {
Logger.getLogger(SortedList.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Your insertion code doesn't work.
elements[i+1] = elements[i];
elements[i] = el;
What happens to the old value of elements[i+1]?
I'd recommend the following changes to the previous solution. If you're only calling sort in toString(), your list is going to get out of order quickly in cases where you have multiple unsorted elements in a row (Now you could remove sort() from toString()). It's essentially a quick insertion sort that dies as soon as it can't make any more swaps down the list. Again, as dty suggested, a faster choice would be a binary search to find the insertion point.
public void doubleCapacity(){
capacity = capacity * 2;
Integer temp[] = new Integer[capacity];
for (int i = 0; i < size; i++){
temp[i] = elements[i];
}
elements = temp;
}
public void add(Integer el){
if(size+1>capacity){
doubleCapacity();
}
elements[size] = el;
size++;
sort();
}
public void sort(){
//Iterates down the list until it's sorted.
for (int i=size()-2; i >= 0 && (elements[i] < elements[i+1]); i--) {
// exchange elements
int temp = elements[i];
elements[i] = elements[i+1];
elements[i+1] = temp;
}
}