I'm working with a linked list in java and I need to take a list of x objects and move the odd positioned objects to the end of the list.
I have to do it by using linking, no new nodes, no list.data exchanges.
I feel like I have a decent handle when I'm moving stuff from one list to another, but traversing and appending with references to only one list is really tough.
Here's the actual question ---
Write a method shift that rearranges the elements of a list of integers by moving to the end of the list all values that are in odd-numbered positions and otherwise preserving list order. For example, suppose a variable list stores the following values:
[0, 1, 2, 3, 4, 5, 6, 7]
The call of list.shift(); should rearrange the list to be:
[0, 2, 4, 6, 1, 3, 5, 7]
you must solve this problem by rearranging the links of the list.
below is the class that I need to write the method before (with the aforementioned restrictions.
I can't really come up with a plan of attack.
// A LinkedIntList object can be used to store a list of integers.
public class LinkedIntList {
private ListNode front; // node holding first value in list (null if empty)
private String name = "front"; // string to print for front of list
// Constructs an empty list.
public LinkedIntList() {
front = null;
}
// Constructs a list containing the given elements.
// For quick initialization via Practice-It test cases.
public LinkedIntList(int... elements) {
this("front", elements);
}
public LinkedIntList(String name, int... elements) {
this.name = name;
if (elements.length > 0) {
front = new ListNode(elements[0]);
ListNode current = front;
for (int i = 1; i < elements.length; i++) {
current.next = new ListNode(elements[i]);
current = current.next;
}
}
}
// Constructs a list containing the given front node.
// For quick initialization via Practice-It ListNode test cases.
private LinkedIntList(String name, ListNode front) {
this.name = name;
this.front = front;
}
// Appends the given value to the end of the list.
public void add(int value) {
if (front == null) {
front = new ListNode(value, front);
} else {
ListNode current = front;
while (current.next != null) {
current = current.next;
}
current.next = new ListNode(value);
}
}
// Inserts the given value at the given index in the list.
// Precondition: 0 <= index <= size
public void add(int index, int value) {
if (index == 0) {
front = new ListNode(value, front);
} else {
ListNode current = front;
for (int i = 0; i < index - 1; i++) {
current = current.next;
}
current.next = new ListNode(value, current.next);
}
}
public boolean equals(Object o) {
if (o instanceof LinkedIntList) {
LinkedIntList other = (LinkedIntList) o;
return toString().equals(other.toString()); // hackish
} else {
return false;
}
}
// Returns the integer at the given index in the list.
// Precondition: 0 <= index < size
public int get(int index) {
ListNode current = front;
for (int i = 0; i < index; i++) {
current = current.next;
}
return current.data;
}
// Removes the value at the given index from the list.
// Precondition: 0 <= index < size
public void remove(int index) {
if (index == 0) {
front = front.next;
} else {
ListNode current = front;
for (int i = 0; i < index - 1; i++) {
current = current.next;
}
current.next = current.next.next;
}
}
// Returns the number of elements in the list.
public int size() {
int count = 0;
ListNode current = front;
while (current != null) {
count++;
current = current.next;
}
return count;
}
// Returns a text representation of the list, giving
// indications as to the nodes and link structure of the list.
// Detects student bugs where the student has inserted a cycle
// into the list.
public String toFormattedString() {
ListNode.clearCycleData();
String result = this.name;
ListNode current = front;
boolean cycle = false;
while (current != null) {
result += " -> [" + current.data + "]";
if (current.cycle) {
result += " (cycle!)";
cycle = true;
break;
}
current = current.__gotoNext();
}
if (!cycle) {
result += " /";
}
return result;
}
// Returns a text representation of the list.
public String toString() {
return toFormattedString();
}
// Returns a shorter, more "java.util.LinkedList"-like text representation of the list.
public String toStringShort() {
ListNode.clearCycleData();
String result = "[";
ListNode current = front;
boolean cycle = false;
while (current != null) {
if (result.length() > 1) {
result += ", ";
}
result += current.data;
if (current.cycle) {
result += " (cycle!)";
cycle = true;
break;
}
current = current.__gotoNext();
}
if (!cycle) {
result += "]";
}
return result;
}
// ListNode is a class for storing a single node of a linked list. This
// node class is for a list of integer values.
// Most of the icky code is related to the task of figuring out
// if the student has accidentally created a cycle by pointing a later part of the list back to an earlier part.
public static class ListNode {
private static final List<ListNode> ALL_NODES = new ArrayList<ListNode>();
public static void clearCycleData() {
for (ListNode node : ALL_NODES) {
node.visited = false;
node.cycle = false;
}
}
public int data; // data stored in this node
public ListNode next; // link to next node in the list
public boolean visited; // has this node been seen yet?
public boolean cycle; // is there a cycle at this node?
// post: constructs a node with data 0 and null link
public ListNode() {
this(0, null);
}
// post: constructs a node with given data and null link
public ListNode(int data) {
this(data, null);
}
// post: constructs a node with given data and given link
public ListNode(int data, ListNode next) {
ALL_NODES.add(this);
this.data = data;
this.next = next;
this.visited = false;
this.cycle = false;
}
public ListNode __gotoNext() {
return __gotoNext(true);
}
public ListNode __gotoNext(boolean checkForCycle) {
if (checkForCycle) {
visited = true;
if (next != null) {
if (next.visited) {
// throw new IllegalStateException("cycle detected in list");
next.cycle = true;
}
next.visited = true;
}
}
return next;
}
}
// YOUR CODE GOES HERE
}
see it this way:
first we need some sort of cursor that will go through the list and point to our "current" node
second we need some boolean variable (i'll call it INV) initialized as FALSE ... everytime we move a node in the list, we invert INV
if you go through the list from the left, the second element is the first to be rearanged, so that will be our initial cursor position
lets take a reference on that element/node, and keep that reference as abort criteria
start of loop:
now remove the current node from the list and insert it at the end of the list (move to the end ... not that the cursor may not move with the node ...)
move the cursor to the node that is right of the former position of the node we just moved (if that exists)
if the current element is our abort criteria (first element we moved) we can assume the list is sorted now in the desired order -> we are finished -> exit the loop ... if it's not our abort criteria ... go on
evaluate "index of the cursor is even" to either TRUE or FALSE ... XOR that with INV
if the result is TRUE move the cursor to the next element ... if it's FALSE remove the node and insert it at the end (move it to the end)
do the loop
--
this approach will not preserve the order while we move through the list, but will have the list in the desired order when it finishes ...
the INV var is for compensation the index shifts when removing a node ... (0,1,2,3 ... if you remove the 1 and put it at the end, 2 will have an odd index, so if we invert that with every move, we get the "right" elements)
Related
//code inside a reverse method that has the list object
//passed as a parameter from main method
int size = list.size();
//create temporary list object to hold contents of original list in reverse
MyListReferenceBased temp = new MyListReferenceBased();
for (int i = 0; i < size; i++)
{
//list add method requires which index your adding to, and object
//get method just gets the object at the specified index in list
temp.add(i, list.get((size-i)-1));
//remove method just removes object at specified index
list.remove((size-i)-1);
}
//now that original list is empty, put the contents back in
for (int i = 0; i<size; i++)
{
list.add(i, temp.get(i));
}
temp.removeAll();
//end result: original list is now reversed
//and temporary array is all empty
System.out.println("List has been Reversed.");
//is there a way to get rid of the 2nd loop?? Not possible to just assign?
So this code is in a reverse method inside the main class for reversing a linked list. Well reversing a list in general, since the user of the main class isn't suppose to interact with the linked list directly but just has access to the linked list methods (Didn't do reverse inside linked list class on purpose). Rather in the main/driver class, I'm reversing the list by first creating a second/temporary linked list, adding over each of the elements from the original list (in reverse) into the new list. And then since I need the contents to be in the original list and only need the temporary list during the duration of this method, I copy over the elements back into the old list.
The list object is instantiated as local in the main method of this main class and then calls the reverse method, passing the list object as a parameter. Instead of having the second loop, isn't there a way to just assign the temporary list object to the original list? I was able to do this when I the underlying implementation of the list was using arrays, but not sure how to it with linked lists.
Or any other efficient work around? Remember this is specifically for reversing a linked list without directly being inside the linked list class.
///FULL CODE IF NEEDED://
public class MyListReferenceBased implements ListInterface {
private Node head;
public MyListReferenceBased()
{
head = null;
}
public boolean isEmpty() {
return head == null;
}
// dont use find()
public int size() {
int size = 0;
Node curr = head;
while (curr != null) {
curr = curr.getNext();
size++;
}
return size;
}
private Node find (int index)
{
Node curr = head;
for (int skip = 0; skip < index; skip++)
{
curr = curr.getNext();
} // end for
return curr;
} // end find
public void add(int index, Object item)
throws ListIndexOutOfBoundsException
{
if (index >= 0 && index < size() + 1)
{
if (index == 0)
{
// insert the new node containing item at
// beginning of list
Node newNode = new Node(item, head);
head = newNode;
}
else
{
Node prev = find(index-1);
Node newNode = new Node(item, prev.getNext());
prev.setNext(newNode);
} // end if
}
else
{
throw new ListIndexOutOfBoundsException(
"List index out of bounds exception on add");
} // end if
} // end add
public Object get(int index)
throws ListIndexOutOfBoundsException
{
if (index >= 0 && index < size())
{
Node curr = find(index);
Object dataItem = curr.getItem();
return dataItem;
}
else
{
throw new ListIndexOutOfBoundsException(
"List index out of bounds exception on get");
} // end if
} // end get
public void remove(int index)
throws ListIndexOutOfBoundsException
{
if (index >= 0 && index < size())
{
if (index == 0)
{
head = head.getNext();
}
else
{
Node prev = find(index-1);
Node curr = prev.getNext();
prev.setNext(curr.getNext());
} // end if
}
else
{
throw new ListIndexOutOfBoundsException(
"List index out of bounds exception on remove");
} // end if
} // end remove
public void removeAll() {
head = null;
}
public String toString() {
String x = "";
Node curr = head;
int size = size();
for (int i = 0; i < size ; i++) {
// curr.getNext();
x += curr.getItem() + " ";
curr = curr.getNext();
}
return x;
}
}
///NODE CLASS///
public class Node
{
private Object item;
private Node next;
public Node(Object newItem)
{
item = newItem;
next = null;
} // end constructor
public Node(Object newItem, Node nextNode)
{
item = newItem;
next = nextNode;
} // end constructor
public void setItem(Object newItem)
{
item = newItem;
} // end setItem
public Object getItem()
{
return item;
} // end getItem
public void setNext(Node nextNode)
{
next = nextNode;
} // end setNext
public Node getNext()
{
return next;
} // end getNext
} // end class Node
Here's recursive implementation.
Base case: the tail becomes a new head, i.e. index argument is equal to size (or greater, which would be the case if the given list is empty).
Recursive case:
obtain the next that should be swapped using get(), indices of nodes to swap start from size - 2 (because it would be redundant to remove and immediately add the tail-node) and move towards 0;
invoke remove() to delete the current node;
add the new node to the tail using add();
invoke reverse() recursively passing index incremented by 1.
That's how it might look like:
public static void reverse(MyListReferenceBased list) {
reverse(list, 1, list.size()); // initial index is 1 (if the first call would with the index 0 the list would not change its state after the first execution of `reverse()` because we would be dialing with tail node which would stay on the same place)
}
public static void reverse(MyListReferenceBased list, int index, int size) {
if (index >= size) return; // Base case - tail becomes a head (we don't need to touch the tail)
// recursive case
Object valueToRemove = list.get(size - 1 - index);
list.remove(size - 1 - index);
list.add(size - 1, valueToRemove);
reverse(list, index + 1, size);
}
A link to Online Demo
Well, prepend one node after the other to an initially empty list:
/** Prepend the elements of <code>suffix</code> to <code>suffix</code>,
* in reverse order.
* #param emptied gets, well, <i>emptied</i>
* #param suffix
* #return <code>suffix</code> with the elements of
* <code>emptied</code> prepended in reverse order */
static ListInterface
prependReversed(ListInterface emptied, ListInterface suffix) {
while (!emptied.isEmpty()) {
suffix.add(0, emptied.get(0));
emptied.remove(0);
}
return suffix;
}
/** Reverse a List.
* #param emptied the list to reverse; will be empty on return
* #return a <code>MyListReferenceBased</code> containing
the elements of <code>emptied</code> in reverse order */
static MyListReferenceBased reverse_(ListInterface emptied) {
return prependReversed(emptied, new MyListReferenceBased());
}
/** Reverse a MyListReferenceBased in place (sort of).
* Argument is emptied temporarily and restored on return.
* #param toReverse the list to reverse; will be restored on return
* #return a <code>MyListReferenceBased</code> with
the elements of <code>toReverse</code> in reverse order */
public static MyListReferenceBased reverse(ListInterface toReverse) {
MyListReferenceBased
reversed = new MyListReferenceBased(),
saved = new MyListReferenceBased();
// an O(1) toReverse.clone() or saved.addAll(toReverse) would come in handy
while (!toReverse.isEmpty()) {
Object item = toReverse.get(0);
reversed.add(0, item);
saved.add(0, item);
toReverse.remove(0);
}
prependReversed(saved, toReverse);
return reversed;
}
True non-mutating variant (in O(1) time…) left as an exercise.
I am trying to make an application that will loop through a circular linked list. As it does so, it will use another linked list of index values, and it will use these values to delete from the circular linked list.
I have it set up now where it should fetch the index value to be deleted from my random linked list via runRandomList() method. It then uses the rotate() method to loop through the circular linked list and deletes the value from it. It will then add the deleted value to "deletedLinked list". Then, control should return back to runRandomList() method and it should feed the rotate() method the next value from the random linked list. The circular linked list should begin traversing where it left off. It should keep track of the count and node it is on. The count should reset to 0 when it reaches the first node, so it can properly keep track of which index it is on.
Unfortunately, this is not happening. I have been trying different things for the last few days as the code stands right now; it enters into a continuous loop. the issue appears to be in the rotate method.
This is the rotate method code. My thought was the counter would advance until it matches the index input. If it reaches the first node, the counter would reset to 0 and then start to increment again until it reaches the index value.
private void rotate(int x)
{
while(counter <= x)
{
if(p == names.first)
{
counter = 0;
}
p = p.next;
counter++;
}
deleteList.add((String) p.value);
names.remove(x);
}
This is my linked list class:
public class List<T>{
/*
helper class, creates nodes
*/
public class Node {
T value;
Node next;
/*
Inner class constructors
*/
public Node(T value, Node next)
{
this.value = value;
this.next = next;
}
private Node(T value)
{
this.value = value;
}
}
/*
Outer class constructor
*/
Node first;
Node last;
public int size()
{
return size(first);
}
private int size(Node list)
{
if(list == null)
return 0;
else if(list == last)
return 1;
else
{
int size = size(list.next) + 1;
return size;
}
}
public void add(T value)
{
first = add(value, first);
}
private Node add(T value, Node list)
{
if(list == null)
{
last = new Node(value);
return last;
}
else
list.next = add(value, list.next);
return list;
}
public void setCircularList()
{
last.next = first;
}
public void show()
{
Node e = first;
while (e != null)
{
System.out.println(e.value);
e = e.next;
}
}
#Override
public String toString()
{
StringBuilder strBuilder = new StringBuilder();
// Use p to walk down the linked list
Node p = first;
while (p != null)
{
strBuilder.append(p.value + "\n");
p = p.next;
}
return strBuilder.toString();
}
public boolean isEmpty()
{
boolean result = isEmpty(first);
return result;
}
private boolean isEmpty(Node first)
{
return first == null;
}
public class RemovalResult
{
Node node; // The node removed from the list
Node list; // The list remaining after the removal
RemovalResult(Node remNode, Node remList)
{
node = remNode;
list = remList;
}
}
/**
The remove method removes the element at an index.
#param index The index of the element to remove.
#return The element removed.
#exception IndexOutOfBoundsException When index is
out of bounds.
*/
public T remove(int index)
{
// Pass the job on to the recursive version
RemovalResult remRes = remove(index, first);
T element = remRes.node.value; // Element to return
first = remRes.list; // Remaining list
return element;
}
/**
The private remove method recursively removes
the node at the given index from a list.
#param index The position of the node to remove.
#param list The list from which to remove a node.
#return The result of removing the node from the list.
#exception IndexOutOfBoundsException When index is
out of bounds.
*/
private RemovalResult remove(int index, Node list)
{
if (index < 0 || index >= size())
{
String message = String.valueOf(index);
throw new IndexOutOfBoundsException(message);
}
if (index == 0)
{
// Remove the first node on list
RemovalResult remRes;
remRes = new RemovalResult(list, list.next);
list.next = null;
return remRes;
}
// Recursively remove the element at index-1 in the tail
RemovalResult remRes;
remRes = remove(index-1, list.next);
// Replace the tail with the results and return
// after modifying the list part of RemovalResult
list.next = remRes.list;
remRes.list = list;
return remRes;
}
}
This contains the main(), runRandomList(), and rotate() methods.
public class lottery {
private int suitors;
private List<String> names;
private List<Integer> random;
private List<String> deleteList = new List<>();
private int counter;
private Node p;
public lottery(int suitors, List<String> names, List<Integer> random)
{
this.suitors = suitors;
this.names = names;
this.random = random;
p = names.first;
}
public void start()
{
//Set names list to circular
names.setCircularList();
runRandomList(random);
}
public void runRandomList(List<Integer> random)
{
Node i = random.first;
while(i != null)
{
rotate((int) i.value, counter, p);
i = i.next;
}
}
public List getDeleteList()
{
return deleteList;
}
private void rotate(int x, int count, Node p)
{
Node i = p;
while(count <= x)
{
if(i == names.first)
{
count = 0;
}
i = i.next;
count++;
}
deleteList.add((String) i.value);
names.remove(x);
p = i;
counter = count;
}
public static void main(String[] args)
{
List<String> namesList = new List<>();
namesList.add("a");
namesList.add("b");
namesList.add("c");
namesList.add("d");
namesList.add("e");
namesList.add("f");
List<Integer> randomList = new List<>();
randomList.add(3);
randomList.add(1);
randomList.add(5);
randomList.add(4);
randomList.add(0);
lottery obj = new lottery(6, namesList, randomList);
obj.start();
System.out.println(obj.getDeleteList());
}
}
As I suspected it was the rotate method, this is the solution.
private void rotate(int x, int count)
{
while(count != x)
{
p = p.next;
count++;
if(count == x)
{
deleteList.add((String)p.value);
counter = x;
}
if(count >= suitors)
{
for (int j = 0; j < x ; j++)
{
p = p.next;
}
deleteList.add((String)p.value);
counter = x;
count = x;
}
}
}
Given singly Linked List: 1 -> 2 -> 3 -> 4 -> 5 -> null
Modify middle element as doubly Linked List Node
here middle element is 3
3 -> next should point to 4
3 -> prev should point to 1
Can any one suggest how can it be done ? interviewer gave me hint use interface. but I couldn't figure it out how.
I have to iterate over this linked list and print all the node and when it reaches to the middle, print where next and prev is pointing to, then print till the end of the list.
Expected output : 1, 2, Middle: 3, Prev: 1, Next: 4, 5
I'm facing problem in adding the middle node.
So, this "works", but if this is expected to be answered on an interview, it is way too much work.
LinkedList
public class LinkedList {
public interface Linkable<V, L extends Linkable> {
V getValue();
L getNext();
void setNext(L link);
}
public static class Node implements Linkable<Integer, Linkable> {
int value;
Linkable next;
Node(int value) {
this.value = value;
}
#Override
public Integer getValue() {
return value;
}
#Override
public Linkable getNext() {
return next;
}
#Override
public void setNext(Linkable link) {
this.next = link;
}
}
private Linkable head;
public boolean isEmpty() {
return this.head == null;
}
public Linkable getHead() {
return head;
}
public void add(int v) {
Node next = new Node(v);
if (isEmpty()) {
this.head = next;
} else {
Linkable tmp = this.head;
while (tmp.getNext() != null) {
tmp = tmp.getNext();
}
tmp.setNext(next);
}
}
}
Interface
interface DoublyLinkable<V, L extends LinkedList.Linkable> extends LinkedList.Linkable<V,L> {
LinkedList.Linkable getPrev();
void setPrev(LinkedList.Linkable prev);
}
DoubleNode
public class DoubleNode extends LinkedList.Node implements DoublyLinkable<Integer, LinkedList.Linkable> {
LinkedList.Linkable prev;
public DoubleNode(int value) {
super(value);
}
#Override
public LinkedList.Linkable getPrev() {
return prev;
}
#Override
public void setPrev(LinkedList.Linkable prev) {
this.prev = prev;
}
}
Driver
Outputs
1, 2, Middle: 3, Prev: 1, Next: 4, 5
public class Driver {
public static LinkedList getList() {
LinkedList list = new LinkedList();
for (int i = 1; i <= 5; i++) {
list.add(i);
}
return list;
}
public static void main(String[] args) {
LinkedList list = getList();
LinkedList.Linkable head = list.getHead();
LinkedList.Linkable beforeMiddle = null;
LinkedList.Linkable middle = list.getHead();
LinkedList.Linkable end = list.getHead();
if (head != null) {
// find the middle of the list
while (true) {
if (end.getNext() == null || end.getNext().getNext() == null) break;
beforeMiddle = middle;
middle = middle.getNext();
end = end.getNext().getNext();
}
// Replace middle by reassigning the pointer to it
if (beforeMiddle != null) {
DoubleNode n = new DoubleNode((int) middle.getValue()); // same value
n.setPrev(list.getHead()); // point back to the front
n.setNext(middle.getNext()); // point forward to original value
beforeMiddle.setNext((DoublyLinkable) n);
middle = beforeMiddle.getNext();
}
// Build the "expected" output
StringBuilder sb = new StringBuilder();
final String DELIMITER = ", ";
head = list.getHead();
boolean atMiddle = false;
if (head != null) {
do {
if (head instanceof DoublyLinkable) {
atMiddle = true;
String out = String.format("Middle: %d, Prev: %d, ", (int) head.getValue(), (int) ((DoublyLinkable) head).getPrev().getValue());
sb.append(out);
} else {
if (atMiddle) {
sb.append("Next: ");
atMiddle = false;
}
sb.append(head.getValue()).append(DELIMITER);
}
head = head.getNext();
} while (head != null);
}
sb.setLength(sb.length() - DELIMITER.length());
System.out.println(sb.toString());
}
}
}
By definition, a single-linked list consists of single-linked nodes only, and a double-linked consists of double-linked nodes only. Otherwise. it is neither.
By definition the field prev of a double-linked list must point to the previous element.
Whatever you are supposed to build. It's something not well specified. So if you really were asked this in an interview (and did not misunderstand the question - maybe he wanted you to point out that ghis violates the interface?) this is a case for the code horror stories of http://thedailywtf.com/ - section "incompetent interviewers".
If you haven't, you'd better define a lenght() function so given one linked list you can know how many nodes does it have.
Thanks to the response of Cereal_Killer to the previous version of this answer, I noticed that the list is firstly a singly linked list, and you just have to make the middle node be linked both to the next node and to some previous node.
Now I guess that you have defined two structures (Struct, Class or whatever depending on the language you're using). So lets say you have Node_s defined as a node with only a next pointer, and Node_d with both a next and a prev pointer. (Node_d may inherite from Node_s so you just have to add the prev attribute in the child class). Knowing this, the code above should be doing what you need:
function do_it(my_LinkedList linkedList){
int i_middle;
int length = linkedList.length();
if ( (length ÷ 2 ) != 0 ) i_middle = length / 2;
else return -1;
Node_s aux = linkedList.first();
int index = 0;
Node_d middle= null;
while (aux != null) {
if (index == i_middle - 1){ //now aux is the middle's previous node
middle.data = aux.next.data; //aux.next is the middle singly node, we assignate the data to the new double linked node
middle.prev = aux; //as we said, aux is the prev to the middle
midle.next = aux.next.next; //so aux.next.next is the next to the middle
print(what you need to print);
}else {
print("Node " + index " next: "+ aux.next);
}//end if
index++;
aux = aux.next;
} //end while
}//end function
This previous code should be doing what you need. I wrote the answer in some kind of pseudo-java code so if you're not familiar with Java or don't understand what my pseudo-code does, please let me know. Anyway, the idea of my code may present some troubles depending on the language you're working with, so you'll have to adapt it.
Note that at the end of the execution of this program, your data structure won't be a singly linked list, and neither a double one, since you'll have linkedList.length() - 1 nodes linked in a signly way but the middle one will have two links.
Hope this helps.
I'm implementing the remove() method of a custom LinkedList class, but it does not remove any items from the list, and I can't figure out why.
Here's how I do it:
public void remove(int position) {
if (position < 0 || position >= size) {
throw new IndexOutOfBoundsException(
"position should be beween 0 and size - 1");
}
Cell current = top;
for (int i = 0; i < position; i++) {
current = current.next;
}
current = current.next.next;
size--;
}
This method tries to remove an item between 2 nodes (removing first node and last node cases are ignored).
This is the test case I am executing, and after trying to remove the element with index 2, it still prints the hole list:
CustomList<String> list = new CustomList<String>();
list.add("Hello");
list.add("morena");
list.add("What");
list.add("Miranda");
list.add("Aston");
list.remove(2);
list.printAll();
For completion, here's the full implementation of the list:
public class CustomList<T> {
private class Cell {
T data;
Cell next;
public Cell(T data) {
this.data = data;
}
}
private Cell top;
private int size;
public void add(T data) {
addAtEndInOn(data);
size++;
}
/**
* adds an item at the end of the list in O(n) by iterating the whole list
* before adding the node
*/
private void addAtEndInOn(T data) {
if (top == null) {
top = new Cell(data);
} else {
Cell current = top;
while (current.next != null) {
current = current.next;
}
current.next = new Cell(data);
}
}
public void remove(int position) {
if (position < 0 || position >= size) {
throw new IllegalArgumentException(
"position should be a positive number");
}
Cell current = top;
for (int i = 0; i < position; i++) {
current = current.next;
}
current = current.next.next;
size--;
}
public void printAll() {
Cell current = top;
while (current != null) {
System.out.println(current.data);
current = current.next;
}
}
}
current = current.next.next changes nothing in your list.
In order to remove an element, you need to write :
current.next = current.next.next;
This would remove the element that is next to the current element. It that's not the element you meant to remove, you should change the for loop so that it stops when current is the element before the one you want to remove.
Make sure to test that current.next is not null, to avoid NullPointerException.
You have to break the link, not just change the position of current. The link is represented by current.next
I'm trying to implement the a Stack in Java with a circular singly linked list as the underlying data structure. I placed the insert function for a circular linked list in replacement of the push function for the stack and so on. I don't have any errors but I'm having troubles displaying the stack. If anyone could point me in the right direction of how to display the stack or what's going wrong I'd really appreciate it!
Here is my stack class:
public class Stack {
private int maxSize; // size of stack array
private long[] stackArray;
private int top; // top of stack
private Node current = null; // reference to current node
private int count = 0; // # of nodes on list
private long iData;
public Stack(int s) // constructor
{
maxSize = s; // set array size
stackArray = new long[maxSize]; // create array
top = -1; // no items yet
}
public void push(long j) // put item on top of stack
{
Node n = new Node(j);
if(isEmpty()){
current = n;
}
n.next = current;
current = n;
count++;
}
//--------------------------------------------------------------
public Node pop() // take item from top of stack
{
if(isEmpty()) {
return null;
}
else if(count == 1){
current.next = null;
current = null;
count--;
return null;
}else{
Node temp = current;
current = current.next;
temp.next = null;
temp = null;
count--;
}
return current;
}
//--------------------------------------------------------------
public Node peek(long key) // peek at top of stack
{
Node head = current;
while(head.iData != key){
head = head.next;
}
return head;
}
//--------------------------------------------------------------
public boolean isEmpty() // true if stack is empty
{
return (count == 0);
}
//--------------------------------------------------------------
public boolean isFull() // true if stack is full
{
return (count == maxSize-1);
}
//--------------------------------------------------------------
Here is my constructor class
public class Node{
public long iData; // data item (key)
public Node next; // next node in the list
public Node(long id){ // constructor
iData = id; // next automatically nulls
}
public void displayNode(){
System.out.print(iData + " ");
}
public static void main(String[] args) {
Stack newlist = new Stack(3);
newlist.push(1);
newlist.push(2);
newlist.push(3);
newlist.push(4);
newlist.pop();
newlist.pop();
newlist.push(4);
newlist.pop();
newlist.peek(1);
newlist.push(5);
while( !newlist.isEmpty() ) // until it’s empty,
{ // delete item from stack
Node value = newlist.pop();
System.out.print(value); // display it
System.out.print(" ");
} // end while
System.out.println("");
}
//newlist.displayList();
}
First, in your main function you are printing value using System.out.print function. This displays the object's class name representation, then "#" followed by its hashcode.
Replace following lines
System.out.print(value); // display it
System.out.print(" ");
with
value.displayNode();
Second, in pop method, you are returning null when count is 1. It should return the last element which is present in the list. Also, in last else if clause, you should return temp. Replace your code with this.
public Node pop() // take item from top of stack
{
if (isEmpty()) {
return null;
}
Node temp = current;
if (count == 1) {
current = null;
} else {
current = current.next;
}
count--;
temp.next = null;
return temp;
}
A few notes on your implementation:
1) stackArray member seems to be a leftover from another array based stack implementation.
2) is max size really a requirement? if so, you don't enforce the stack size limitation in push(..)
3) Your push(..) method doesn't keep the list circular. You should close the loop back to the new node.
4) Adding a dummy node allows you to keep the linked list circular, regardless of the stack size. This can make your push(..) method simpler (as well as any iteration for printing purposes for example)
5) The peek() method contract is unclear. Usually you want the peek method to return the value in the top of the stack, without removing it. Also, why do you return type Node? This class should be hidden from the caller - it's an internal implementation detail, not something you want to expose in your API.
Following is an alternative implementation, that also supports toString():
public class Stack {
private Node EOS;
private int count = 0;
public Stack() {
EOS = new Node(0);
EOS.next = EOS;
}
public void push(long j) {
Node newNode = new Node(j);
Node tmp = EOS.next;
EOS.next = newNode;
newNode.next = tmp;
count++;
}
public Long pop() {
if (isEmpty()) {
return null;
} else {
count--;
Node node = EOS.next;
EOS.next = node.next;
return node.iData;
}
}
public Long peek() {
if (isEmpty()) {
return null;
} else {
Node node = EOS.next;
return node.iData;
}
}
public boolean isEmpty() {
return (count == 0);
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
Node p = EOS.next;
while (p != EOS) {
sb.append(p).append("\n");
p = p.next;
}
return sb.toString();
}
private static class Node {
public long iData;
public Node next;
public Node(long id) {
iData = id;
}
#Override
public String toString() {
return "<" + iData + ">";
}
}
}