I need to create data structure acting like stack (LIFO) with these functions: init(), push(Object), pop(), getMiddle(), getAt(k).
All of the fucntion except getAt() should be with complexity O(1), and getAt(k) with time complexity O(log(k)). Space Complexity should be O(n)
The problem is getAt(k) function, when k is index of k'th inserted (accoriding to inserting order) element in the stack.
I decided to go with DoublyLinkedList because then I'll can to move pointer to the middle element. I also share a code. If someone has any suggestions about how I can even get O(k) complexity or even the solution.
class Node {
Node prev;
Node next;
Object data;
int order; //index of inserted element
Node(Object data, int order) {
prev = null;
next = null;
this.data = data;
this.order = order;
}
}
public class LikeStack {
Node head;
Node mid;
int size;
//constructor
public LikeStack() {
this.size = 0;
this.head = null;
this.mid = null;
}
//push object to the stack and move the pointer to the middle of the stack if needed
public void push(Object o) {
size++;
Node toPush = new Node(o, size);
toPush.prev = null;
toPush.next = head;
if (size == 1) {
mid = toPush;
} else {
head.prev = toPush;
{
if (size % 2 == 1) {
mid = mid.prev;
}
}
}
head = toPush;
}
//pop object from the stack and move the pointer to the middle of the stack if needed
public Object pop() throws Exception {
if(size<=0)
{
throw new Exception("The stack is empty");
}
size--;
Object temp = head.data;
head=head.next;
if(head!=null)
{
head.prev=null;
}
if(size%2==1)
{
mid=mid.next;
}
return temp;
}
//just returning the middle element
public Object getMiddle(){
return mid.data;
}
First is to maintain an index variable, say index to 0.
When you do the push(), you will add the element to the map like:
void push(int value){
// your code
map.put(index++,your_node);
}
In your pop(), you would do
int pop(){
// your code
your_node.prev.next = null;
map.remove(index--);
}
So, getting the middle element will just be a lookup in the map
int middle(){
// your code
return map.get(index / 2).value;
}
Getting the value at k will be similar to the above:
int getKthElement(int K){
// your code
return map.get(K-1).value; // If K is above index, you can throw an exception
}
Related
I am implementing a cyclic DoublyLinkedList data structure. Like a singly linked list, nodes in a doubly linked list have a reference to the next node, but unlike a singly linked list, nodes in a doubly linked list also have a reference to the previous node.
Additionally, because the list is "cyclic", the "next" reference in the last node in the list points to the first node in the list, and the "prev" reference in the first node in the list points to the last node in the list.
I need help starting my get method, I've been looking around and I couldn't find anything that could help me since I am working with a Generic Type . I need to return E and every other examples show me it with int as an example. Here is my code:
public class DoublyLinkedList<E>
{
private Node first;
private int size;
#SuppressWarnings("unchecked")
public void add(E value)
{
if (first == null)
{
first = new Node(value, null, null);
first.next = first;
first.prev = first;
}
else
{
first.prev.next = new Node(value, first, first.prev);
first.prev = first.prev.next;
}
size++;
}
private class Node<E>
{
private E data;
private Node next;
private Node prev;
public Node(E data, Node next, Node prev)
{
this.data = data;
this.next = next;
this.prev = prev;
}
}
#SuppressWarnings("unchecked")
public void add(int index, E value)
{
if (first.data == null)
{
throw new IndexOutOfBoundsException();
} else if (index == 0)
{
first = new Node(value, first.next, first.prev);
}
else
{
Node current = first;
for (int i = 0; i < index - 1; i++)
{
current = current.next;
}
current.next = new Node(value, current.next, current.prev);
}
}
#SuppressWarnings("unchecked")
public void remove(int index)
{
if (first.data == null)
{
throw new IndexOutOfBoundsException();
}
else if (index == 0)
{
first = first.next;
}
else
{
Node current = first.next;
for (int i = 0; i < index - 1; i++)
{
current = current.next;
}
current.next = current.next.next;
}
size--;
}
I can't think of a way to get started on this, but basically what this method should do is return the element at the specified index in the list. If the index parameter is invalid, an IndexOutOfBoundsException should be thrown.
public E get(int index)
{
}
Also, my remove method isn't accurate, but I'll figure that one out myself, I just need help with my get method.
I figured it out, I'm just shocked that I wasn't getting any responses for this question. Either way, I am going to write some comments so it kind of guides future viewers who are struggling with this.
#SuppressWarnings("unchecked")
public E get(int index)
{
if(index < 0) //The index needs to be above 0.
{
throw new IndexOutOfBoundsException();
}
if(index > size) //Since we're going to run a for loop, we need to make sure the index doesn't go past the size of the list.
{
throw new IndexOutOfBoundsException();
}
Node current = first; //We want to create another node to perform this method.
for (int i = 0; i < index; i++) //We are going to set i to 0 and loop around this for loop until we reach the index.
{
current = current.next;
}
return (E) current.data; //Since we are working with generics, we need to return a type E, and it needs to be in parenthesis so it gets that object.
}
Another problem I sort of had was that in my Node Class I had the in there, when I could've moved on without it. Lets update it to be
private class Node
{
private E data;
private Node next;
private Node prev;
public Node(E data, Node next, Node prev)
{
this.data = data;
this.next = next;
this.prev = prev;
}
}
And now my getMethod() will be as follows:
#SuppressWarnings("unchecked")
public E get(int index)
{
if(index < 0)
{
throw new IndexOutOfBoundsException();
}
if(index > size)
{
throw new IndexOutOfBoundsException();
}
Node current = first;
for (int i = 0; i < index; i++)
{
current = current.next;
}
return current.data;
}
You can also use a hash map, and you will get the data on constant time
public T get(int position){
Node<T> node = map.get(position);
T dat = node.getData();
return dat;
}
So I'm trying to implement a priority queue with a linked list. I think I have the basics together, but for some reason my test cases aren't working. When I run it, the size show up fine, but none of the node values are showing (only an arrow "->" pops up once). If anyone could help me figure out why it isn't working, or suggest a better way to set up test cases in java (I've never done that before) it would be appreciated!
Node class:
public class Node { //Node class structure
int data; //data contained in Node; for assignment purposes, data is an int
Node next; //pointer to Next Node
//Node Constructor
public Node(int data) {
this.data = data;
next = null;
}
//Set Methods
public void setData(int data) { //set Node value
this.data = data;
}
public void setNext(Node next) { //set next Node value
this.next = next;
}
//Get Methods
public int getData() { //get Node value
return this.data;
}
public Node getNext() { //get next Node value
return this.next;
}
//Display the Node Value
public void displayNode() {
System.out.println(data + "urgh"); //display value as a string
}
}
Linked List Class:
import Question1.Node;
//basic set-up of a FIFO singly linked list
public class SLList{
protected Node head; //head of SLList
protected Node tail; //tail of SLList
int n; //number of elements in SLList
//SLList constructor
public SLList() {
head = null;
n = 0;
}
//check if list is empty
public boolean isEmpty() {
return head == null;
}
//return the size of the list
public int size() {
return n;
}
//add a new node to the end of the list
public boolean insert(int x){
Node y = new Node(x);
if (head == null){ //if head is null, thus an empty list
head = y; //assign head as y
}
else{ //if there is already a tail node
tail.next = y; //assign the tail's pointer to the new node
}
tail = y; //assign tail to y
this.n++; //increment the queue's size
return true; //show action has taken place
}
//remove and return node from head of list
public Node remove(){
if (n == 0){ //if the list is of size 0, and thus empty
return null; //do nothing
}
else{ //if there are node(s) in the list
Node pointer = head; //assign pointer to the head
head = head.next; //reassign head as next node,
n--; //decrement list size
return pointer; //return the pointer
}
}
//display SLList as string
public void displayList() {
Node pointer = head;
while (pointer != null) {
pointer.displayNode();
pointer = pointer.next;
}
System.out.println(" ");
}
}
Priority Queue Class:
import Question1.Node;
import Question1.SLList;
public class PriorityQueue extends SLList {
private SLList list; //SLList variable
public PriorityQueue(){ //create the official SLList
list = new SLList();
}
//add a new node; new add method that ensures the first element is sorted to be the "priority"
public boolean add(int x){
Node y = new Node(x);
if (n == 0){ //if there are 0 elements, thus an empty list
head = y; //assign head as y
}
else if (y.data < head.data){ //if new node y is the smallest element, thus highest priority
y.next = head; //assign y's next to be current head of queue
head = y; //reassign head to be actual new head of queue (y)
}
else{ //if there is already a tail node
tail.next = y; //assign the tail's pointer to the new node
}
tail = y; //assign tail to y
n++; //increment the queue's size
return true; //show action has taken place
}
//delete the minimim value (highest priority value) from the queue and return its value
public Node deleteMin(){
return list.remove(); //the list is sorted such that the element being removed in indeed the min
}
//return the size of the queue
public int size() {
return n;
}
//display Queue as string
public void displayQueue() {
System.out.println("->");
list.displayList();
}
}
Test Cases (so far, the delete one wasn't working so it's commented out):
import Question1.PriorityQueue;
public class TestQ1 { //Test code
public static void main(String[] args){
PriorityQueue PQueue1 = new PriorityQueue();
PQueue1.add(3);
PQueue1.add(2);
PQueue1.add(8);
PQueue1.add(4);
System.out.println("Test add(x): ");
PQueue1.displayQueue();
System.out.println("Test size(): " + PQueue1.size());
PriorityQueue PQueue2 = new PriorityQueue();
//Node node1 = PQueue1.deleteMin();
System.out.println("Test deleteMin():");
PQueue2.displayQueue();
System.out.println("Test size(): " + PQueue2.size());
}
}
Change list.displayList() to displayList(), and you'll see the expected output.
Why? Because your queue is already a list (that is, an instance of SLList). When a class A extends another class B, an instance of A is also an instance of B. This is inheritance.
You've also included an instance variable private SLList list within your PriorityQueue implementation, which is an example of composition. Generally you'll only do one or the other of these two options, depending on your situation. In this case it seems you're trying to use inheritance, so there's no reason to create a separate list instance variable. You're adding the data directly to the queue (using the fact that, intrinsically, it is a list in its own right).
You should remove the list instance variable, and all the usages of it should refer to the parent class' methods or variables.
I've been working through some standard coding interview questions from a book I recently bought, and I came across the following question and answer:
Implement an algorithm to find the nth to last element in a linked list.
Here's the provided answer:
public static LinkedListNode findNtoLast(LinkedListNode head, int n) { //changing LinkedListNode to ListNode<String>
if(head == null || n < 1) {
return null;
}
LinkedListNode p1 = head;
LinkedListNode p2 = head;
for(int j = 0; j < n-1; ++j) {
if(p2 == null) {
return null;
}
p2 = p2.next;
}
if(p2 == null) {
return null;
}
while(p2.next != null) {
p1 = p1.next;
p2 = p2.next;
}
return p1;
}
I understand the algorithm, how it works, and why the book lists this as its answer, but I'm confused about how to access the LinkedListNodes to send as an argument to the method. I know that I'd have to create a LinkedListNode class (since Java doesn't already have one), but I can't seem to figure out how to do that. It's frustrating because I feel like I should know how to do this. Here's something that I've been working on. I'd greatly appreciate any clarification. You can expand/comment on my code or offer your own alternatives. Thanks.
class ListNode<E> {
ListNode<E> next;
E data;
public ListNode(E value) {
data = value;
next = null;
}
public ListNode(E value, ListNode<E> n) {
data = value;
next = n;
}
public void setNext(ListNode<E> n) {
next = n;
}
}
public class MyLinkedList<E> extends LinkedList {
LinkedList<ListNode<E>> list;
ListNode<E> head;
ListNode<E> tail;
ListNode<E> current;
ListNode<E> prev;
public MyLinkedList() {
list = null;
head = null;
tail = null;
current = null;
prev = null;
}
public MyLinkedList(LinkedList<E> paramList) {
list = (LinkedList<ListNode<E>>) paramList; //or maybe create a loop assigning each ListNode a value and next ptr
head = list.getFirst();
tail = list.getLast(); //will need to update tail every time add new node
current = null;
prev = null;
}
public void addNode(E value) {
super.add(value);
//ListNode<E> temp = tail;
current = new ListNode<E>(value);
tail.setNext(current);
tail = current;
}
public LinkedList<ListNode<E>> getList() {
return list;
}
public ListNode<E> getHead() {
return head;
}
public ListNode<E> getTail() {
return tail;
}
public ListNode<E> getCurrent() {
return current;
}
public ListNode<E> getPrev() {
return prev;
}
}
How can the LinkedListNode head from a LinkedList?
Update: I think part of my confusion comes from what to put in the main method. Do I need to create a LinkedList of ListNode? If I do that, how would I connect the ListNodes to each other? How would I connect them without using a LinkedList collection object? If someone could show me how they would code the main method, I think that would put things into enough perspective for me to solve my issues. Here's my latest attempt at the main method:
public static void main(String args[]) {
LinkedList<ListNode<String>> list = new LinkedList<ListNode<String>>();
//MyLinkedList<ListNode<String>> list = new MyLinkedList(linkedList);
list.add(new ListNode<String>("Jeff"));
list.add(new ListNode<String>("Brian"));
list.add(new ListNode<String>("Negin"));
list.add(new ListNode<String>("Alex"));
list.add(new ListNode<String>("Alaina"));
int n = 3;
//ListIterator<String> itr1 = list.listIterator();
//ListIterator<String> itr2 = list.listIterator();
LinkedListNode<String> head = new LinkedListNode(list.getFirst(), null);
//String result = findNtoLast(itr1, itr2, n);
//System.out.println("The " + n + "th to the last value: " + result);
//LinkedListNode<String> nth = findNtoLast(list.getFirst(), n);
ListNode<String> nth = findNtoLast(list.getFirst(), n);
System.out.println("The " + n + "th to the last value: " + nth);
}
In an attempt to connect the nodes without using a custom linked list class, I have edited my ListNode class to the following:
class ListNode<E> {
ListNode<E> next;
ListNode<E> prev; //only used for linking nodes in singly linked list
ListNode<E> current; //also only used for linking nodes in singly linked list
E data;
private static int size = 0;
public ListNode() {
data = null;
next = null;
current = null;
if(size > 0) { //changed from prev != null because no code to make prev not null
prev.setNext(this);
}
size++;
}
public ListNode(E value) {
data = value;
next = null;
current = this;
System.out.println("current is " + current);
if(size > 0) {
prev.setNext(current);//this line causing npe
}
else
{
prev = current;
System.out.println("prev now set to " + prev);
}
size++;
System.out.println("after constructor, size is " + size);
}
public ListNode(E value, ListNode<E> n) {
data = value;
next = n;
current = this;
if(size > 0) {
prev.setNext(this);
}
size++;
}
public void setNext(ListNode<E> n) {
next = n;
}
}
As is right now, the program will run until it reaches prev.setNext(current); in the single argument constructor for ListNode. Neither current nor prev are null at the time this line is reached. Any advice would be greatly appreciated. Thanks.
You don't actually need a separate LinkedList class; the ListNode class is a linked list. Or, to state it differently, a reference to the head of the list is a reference to the list.
The use of head, tail, current, prev in the sample code you posted has come from a double-linked list which is a data type that has links in both directions. This is more efficient for certain types of applications (such as finding the nth last item).
So I would recommend renaming your ListNode class to LinkedList and renaming next to tail.
To add a new item to the list you need a method that creates a new list with the new item at it's head. Here is an example:
class LinkedList<E> {
...
private LinkedList(E value, LinkedList<E> tail) {
this.data = value;
this.tail = tail;
}
public LinkedList<E> prependItem(E item) {
return new LinkedList(item, this);
}
}
Then to add a new item i to list you use list = list.prependItem(i);
If for some reason you need to always add the items to the end, then:
private LinkedList(E value) {
this.data = value;
this.tail = null;
}
public void appendItem(E item) {
LinkedList<E> list = this;
while (list.tail != null)
list = list.tail;
list.tail = new LinkedList<>(item);
}
However this is obviously pretty inefficient for long lists. If you need to do this then either use a different data structure or just reverse the list when you have finished adding to it.
Incidentally, an interesting side effect of this is that a reference to any item in the list is a reference to a linked list. This makes recursion very easy. For example, here's a recursive solution for finding the length of a list:
public int getLength(LinkedList list) {
if (list == null) {
return 0;
} else {
return 1 + getLength(list.getTail());
}
}
And using this a simple (but very inefficient!) solution to the problem you provided - I've renamed the method to make its function more obvious:
public LinkedList getTailOfListOfLengthN(LinkedList list, int n) {
int length = getLength(list);
if (length < n) {
return null;
} else if (length == n) {
return list;
} else {
return getTailOfLengthN(list.getTail(), n);
}
}
And to reverse the list:
public LinkedList<E> reverse() {
if (tail == null) {
return this;
} else {
LinkedList<E> list = reverse(tail);
tail.tail = this;
tail = null;
return list;
}
}
As I hope you can see this makes the methods a lot more elegant than separating the node list classes.
Actually you have created a linked list with you class ListNode.
A linked list is made of a node and a reference to another linked list (see the recursion?).
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 + ">";
}
}
}
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)