LinkedListNode in Java - java

I am trying to convert a C# code to Java. I have almost converted every thing except the three lines within if condition.
the C# code
LinkedList<T> buk = new LinkedList();
LinkedListNode<T> current = buk.First;
LinkedListNode<T> previous = null;
if (fooCondition) {
previous = current.Previous;
} else {
previous = current;
current = current.Next;
}
The equivalent Java code
LinkedList<T> buk = new LinkedList<>();
T current = buckets.getFirst();
T previous = null;
if (fooCondition) {
? //previous = current.Previous;
} else {
? //previous = current;
? //current = current.Next;
}
As there is no LinkedListNode class in the Java, can any one suggest what would be the equivalent code in Java?
EDIT
It seems like the full code is important to get help. Here is the C# function from the link
protected void MergeBuckets()
{
LinkedListNode<Bucket> current = buckets.First;
LinkedListNode<Bucket> previous = null;
int k = (int)Math.Ceiling(1 / epsilon); // k=1/eps as integer
int kDiv2Add2 = (int)(Math.Ceiling(0.5 * k) + 2); // k/2 as integer
// at this point 1/k <= eps, k >= 2, hence requires eps >= 0.5
// number of concecutive buckets with same count causing a
// merge of the oldest two of those buckets
int numberOfSameCount = 0;
// traverse buckets from first to last, hence in order of
// descending timestamp and ascending count
while (current != null)
{
// previous and current bucket have same count, increment counter
if (previous != null && previous.Value.Count == current.Value.Count)
numberOfSameCount++;
// current is first with that count, reset counter to 1
else
numberOfSameCount = 1;
// detect need for a merge
if (numberOfSameCount == kDiv2Add2)
{
// merge buckets into current and remove previous
current.Value.Timestamp = previous.Value.Timestamp; // take most recent timestamp
current.Value.Count = previous.Value.Count + current.Value.Count; // sum the counts of the buckets,
// i.e. next power of two
buckets.Remove(previous);
// note that a merged bucket might cause a cascade of merges due to its new count,
// hence the new current node should point to the merged bucket otherwise the
// cascade might go unnoticed, temporarily violating the invariant!
previous = current.Previous; // merged bucket's previous, since old previous is removed
//current = current; // trivial, merged bucket is new current
// at this iteration, the traversal stays in place
}
// no merge required, continue normally
else
{
previous = current; // old current bucket or merged bucket
current = current.Next; // current's or merged's next
// at this iteration, the traversal moves to the next (older) bucket
}
}
}

can't you use the listIterator provided by the LinkedList and use its provided methods to browse the Linked list
ListIterator<T> listIterator = linkedListNode.listIterator(0);
if(yourCondition && listIterator.hasNext()){
T next = listIterator.next();
}
else if (listIterator.hasPrevious()){
T previous = listIterator.previous();
}
Hope it helps

The Java class java.util.LinkedList has an inner class LinkedList.Node which is private. The Nodes in a LinkedList cannot be acccessed directly. Instead, refer to methods like List.indexOf(E) and List.add(E, int) or a ListIterator in order to insert elements at specific positions.
final LinkedList<T> list = new LinkedList<>();
list.add(object1);
if (cond) {
list.add(object2, list.indexOf(object1));
} else {
list.addFirst(object2);
}
A frequently used idiom for dealing with LinkedList in Java is to create the LinkedList but primarily operate on it using a ListIterator.
final LinkedList<T> list = new LinkedList<>();
final ListIterator<T> iterator = list.listIterator();
if (!cond && list.hasNext()) {
list.next();
}
list.add(object2);

You can't make a LinkedList without nodes for it. Your code doesn't make sense, unfortunately.
A LinkedList node (in this case doubly linked) consists of the next node, the previous one, and the data in the node, as well as accessor methods. It's pretty simple to implement as it's simply a data storage structure.
class LinkedListNode<T> {
LinkedListNode prevNode, nextNode;
T data;
public LinkedListNode getNext() {
return nextNode;
}
public LinkedListNode getPrev() {
return prevNode;
}
public T getValue() {
return data;
}
public void setNext( LinkedListNode n ) {
nextNode = n;
}
public void setPrev( LinkedListNode n ) {
prevNode = n;
}
public void setValue( T data ) {
data = n;
}
}

You can write the own version of LinkedListNode class which contains the previous and next as it's property/field. For example -
class LinkedListNode{
LinkedListNode previous;
LinkedListNode next;
}
Then add some getter and setter method to access the property/field. You may add another property/field to store the value of the node. This is the basic structure.This might help you.You may have a look at this link also.
Thanks

LinkedList<T> buk=new LinkedList<T>();
//make list
T current=buk.getFirst();
T previous=null;
if (fooCondition) {
previous = current.previous;
} else {
previous = current;
current = current.next;
}
and the structure of T :
Class T{
public T previous;
public T next;
//rest
}

Related

Sort a linked linked list by name and date of birth

I have ran into some difficulties. I want to adapt this piece of code below to sort a singly linked list of type Person. for example, I have:
class Person{
private String fn = "NN";
private String ln = "NN";
private Date dob = new Date(1, 1, 1970);
}
I would like to sort the linked list of Persons by firstname, last name and date of birth. At the same time I have been given a piece of code to adapt it but, I can't seem to find a way around it. Any help will be highly appreciated. Here is the code to adapt below:
public void sort() {
TextIO.putln("sorting...");
if (head == null)
return;
Node max, t, out = null, h = new Node();
h.next = head;
while (h.next != null) {
// display();
TextIO.putln("max=" + (max = findmax(h)).next);
t = max.next;
max.next = t.next;
t.next = out;
out = t;
}
head = out;
}
private Node findmax(Node h) {
char max = '\0';
Node maxNode = h;
for (Node tmp = h; tmp.next != null; tmp = tmp.next) {
if (tmp.next.data.c >= max) {
max = tmp.next.data.c;
maxNode = tmp;
}
}
return maxNode;
}
If not, a detailed advice will be highly helpful thanks. Mind you, I cannot use collection.sort or any other ready function, it has to be implemented.
Thanks
First of all I would like you to look at this link. It will give you idea of how Node class is implemented and generally how to implement list.
Assuming you read content from the link here are some comments;
public void sort() {
//this method does ascending sort of the list
TextIO.putln("sorting...");
if (head == null)
return;
Node max, t, out = null, h = new Node();
h.next=head; //make new list node let him point to beginning of the list(head)
while (h.next != null) { //until we get to the end of the list
// display();
TextIO.putln("max="+(max = findmax(h)).next);
//after findmax is finished we know reference
//to the node that contains max value
//and we need to bring that node to the beginning of the list
//that requires some reference rewiring
//first set t to point to next node from max
t = max.next;
//than max node will point to the next node from t
//this way max node becomes detached from list
max.next = t.next;
// now max node will point to some node that will represent new list head
// not new list just new list head
t.next = out;
out = t;
}
//after we complete sorting just point list head to the sorted list
head = out;
}
//find node that contains max value starting from some node
private Node findmax(Node h) {
//declare that max is null char
char max = '\0';
// set maxNode to be current node
Node maxNode = h;
//go through all nodes starting from current which is h
for (Node tmp = h; tmp.next != null; tmp = tmp.next) {
//if the data of some node in the list is bigger then our max value
if (tmp.next.data.c >= max) {
//then we are going to set that new value to be max
max = tmp.next.data.c;
// and set maxNode to be the node that has max value
maxNode = tmp;
}
}
return maxNode;
}
My advice is to look at provided link and start using good old pen an paper. That is the best way to understand what is going on with list pointers and nodes.
But if you do not want pen and paper you could go to this link that will show you animation of basic list operations.

Insertion sort using Linked Integer Nodes

Hey there I have been trying to get an insertion sort method to work for a class I'm taking and we have been told to use insertion sort to sort a linked list of integers without using the linked list class already in the Java libraries.
Here is my inner Node class I have made it only singly linked as i don't fully grasp the circular doubly linked list concept yet
public class IntNode
{
public int value;
public IntNode next;
}
And here is my insertion sort method in the IntList class
public IntList Insertion()
{
IntNode current = head;
while(current != null)
{
for(IntNode next = current; next.next != null; next = next.next)
{
if(next.value <= next.next.value)
{
int temp = next.value;
next.value = next.next.value;
next.next.value = temp;
}
}
current = current.next;
}
return this;
}
The problem I am having is it doesn't sort at all it runs through the loops fine but doesn't manipulate the values in the list at all can someone please explain to me what I have done wrong I am a beginner.
you need to start each time from the first Node in your list, and the loop should end with the tail of your list -1
like this
public static IntList Insertion()
{
IntNode current = head;
IntNode tail = null;
while(current != null&& tail != head )
{
IntNode next = current;
for( ; next.next != tail; next = next.next)
{
if(next.value <= next.next.value)
{
int temp = next.value;
next.value = next.next.value;
next.next.value = temp;
}
}
tail = next;
current = head;
}
return this;
}
The insertion operation only works if the list being inserted into is already sorted - otherwise you're just randomly swapping elements. To start out, remove an element from the original list and construct a new list out of it - this list only has one element, hence it is sorted. Now proceed to remove the remaining elements from the original list, inserting them into the new list as you go. At the end the original list will be empty and the new list will be sorted.
I agree with the Zim-Zam opinion also.
The loop invariant of insertion sort also specifies this: "the subarray which is in sorted order".
Below is the code, I implemented for insertion sorting in which I created another linked list that contains the element in sorted order:
Node newList=new Node();
Node p = newList;
Node temp=newList;
newList.data=head.data;
head=head.node;
while(head!=null)
{
if(head.data<newList.data)
{
Node newTemp = new Node();
newTemp.data=head.data;
newTemp.node=newList;
newList=newTemp;
p=newList;
}
else
{
while(newList!=null && head.data>newList.data)
{
temp=newList;
newList=newList.node;
}
Node newTemp = new Node();
newTemp.data=head.data;
temp.node=newTemp;
newTemp.node=newList;
newList=p;
}
head=head.node;
}

Regarding finding the middle element of linked list

I am following the below approach to calculate the middle element from the linked list , but I want is there any built in method or any other approach which can also find the same easily , the approach that I am following is shown bellow..
import test.LinkedList.Node;
public class LinkedListTest {
public static void main(String args[]) {
//creating LinkedList with 5 elements including head
LinkedList linkedList = new LinkedList();
LinkedList.Node head = linkedList.head();
linkedList.add( new LinkedList.Node("1"));
linkedList.add( new LinkedList.Node("2"));
linkedList.add( new LinkedList.Node("3"));
linkedList.add( new LinkedList.Node("4"));
//finding middle element of LinkedList in single pass
LinkedList.Node current = head;
int length = 0;
LinkedList.Node middle = head;
while(current.next() != null){
length++;
if(length%2 ==0){
middle = middle.next();
}
current = current.next();
}
if(length%2 == 1){
middle = middle.next();
}
System.out.println("length of LinkedList: " + length);
System.out.println("middle element of LinkedList : " + middle);
}
}
class LinkedList{
private Node head;
private Node tail;
public LinkedList(){
this.head = new Node("head");
tail = head;
}
public Node head(){
return head;
}
public void add(Node node){
tail.next = node;
tail = node;
}
public static class Node{
private Node next;
private String data;
public Node(String data){
this.data = data;
}
public String data() {
return data;
}
public void setData(String data) {
this.data = data;
}
public Node next() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
public String toString(){
return this.data;
}
}
}
Output:-
length of LinkedList: 4
middle element of LinkedList : 2
The basic algorithm would be
Take two pointers
Make both pointing to first node
Increment first with two nodes and second with one, at a time.
Loop until the 1st loop reaches the end. At this point, the 2nd will be at the middle.
Example:-
while ( p2.next != null ) {
p2 = p2.next;
if (p2.next != null) {
p2 = p2.next;
p1 = p1.next;
}
}
It will definitely work in odd case, for even case you need to check one more condition if first point is allowed to move next but not next to next then both pointers will be at middle you need to decide which to take as middle.
I would recommend using the Java built in
LinkedList<Object e>
It gives you all the functionality you need like getting the length: list.size(), and the middle object:
list.get((list.size())/2);
Options:
Have a double linked-list and go from the back and front at the same time until you get to a common point.
Store the size of the list and simply stop when you've reached this half this size (similar to what the standard API's LinkedList does).
Other than that I don't think you can do better than your algorithm.
public Node getMiddleElement(Node head) {
Node slow_pointer=head;
Node fast_pointer=head;
while(fast_pointer.next!=null && fast_pointer.next.next!=null)
{
slow_pointer=slow_pointer.next;
fast_pointer=fast_pointer.next.next;
}
return slow_pointer;
}
Node mid_elem=PrintMiddleElement(head);
System.out.println(mid_elem.data);
I/P:5 10 15 25 35 25 40 O/P:25
Solution for this question:
Use two indexes, first and second, both initialized to 0
Increment first by 1 and second by 2 * first
Set value of first to middle
Loop will execute until value of second is less than list size
Here is code snippet for getting middle element of list or linked list:
private int getMiddle(LinkedList<String> list) {
int middle = 0;
int size = list.size();
for (int i = 0, j = 0; j < size; j = i * 2) {
middle = i++;
}
return middle;
}
LinkedList<String> list = new LinkedList<>();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
list.add("5");
list.add("6");
list.add("7");
int middle = getMiddle(list);
System.out.println(list.get(middle));

Duplicate a LinkedList with a pointer to a random node apart from the next node

Q: Every node of the linked list has a random pointer (in addition to the next pointer) which could randomly point to another node or be null. How would you duplicate such a linkedlist?
A: Here's what I have, I just wanted to ratify if this was the optimal way of doing it.
Since there's no space constraints specified, I'm going to use a LinkedHashSet and a LinkedHashMap (I can imagine people nodding their head in disagreement already ;) )
First Iteration: Do the obvious - read each node from the list to be copied and create nodes on the new list. Then, read the random node like so: this.random.data and insert into the LinkedHashSet.
Second Iteration: Iterate through the new list and add each node's data as the first column and the node itself as the second column into the LinkedHashMap (doesn't have to be Linked, but I'm just going with the flow).
Third Iteration: Iterate over the LinkedHashSet (this is the reason why this needs to be Linked - predictable ordering) and the new list simultaneously. For the first node, read the first entry of the LinkedHashSet, look up the corresponding object in the LinkedHashMap and add as the random node to the current node in the new list.
3 iterations does seem a little crazy, but the attempt was to keep the complexity as O(N). Any solution that improves on the O(3N) space requirement and O(3N) runtime complexity would be great. Thanks!
Edit: The entry from the LinkedHashSet can be removed when making an entry into the LinkedHashMap, so this would only take O(2N) space.
As pointed out by MahlerFive, I think you can do this with O(2N) runtime complexity, and O(N) space complexity.
Let's assume you have
public class Node {
private Node next;
private Node random;
private String data;
// getters and setters omitted for the sake of brevity
}
I would do a deep copy of a linked list of Nodes as:
private Node deepCopy(Node original) {
// We use the following map to associate newly created instances
// of Node with the instances of Node in the original list
Map<Node, Node> map = new HashMap<Node, Node>();
// We scan the original list and for each Node x we create a new
// Node y whose data is a copy of x's data, then we store the
// couple (x,y) in map using x as a key. Note that during this
// scan we set y.next and y.random to null: we'll fix them in
// the next scan
Node x = original;
while (x != null) {
Node y = new Node();
y.setData(new String(x.getData()));
y.setNext(null);
y.setRandom(null);
map.put(x, y);
x = x.getNext();
}
// Now for each Node x in the original list we have a copy y
// stored in our map. We scan again the original list and
// we set the pointers buildings the new list
x = original;
while (x != null) {
// we get the node y corresponding to x from the map
Node y = map.get(x);
// let x' = x.next; y' = map.get(x') is the new node
// corresponding to x'; so we can set y.next = y'
y.setNext(map.get(x.getNext()));
// let x'' = x.random; y'' = map.get(x'') is the new
// node corresponding to x''; so we can set y.random = y''
y.setRandom(map.get(x.getRandom()));
x = x.getNext();
}
// finally we return the head of the new list, that is the Node y
// in the map corresponding to the Node original
return map.get(original);
}
Edit: I found that this question is a duplicate of the one asked here: there you find an answer that shows how to solve this problem in O(3N) runtime complexity with no extra space: very ingenious! But it uses a trick with C pointers, and I'm not sure how to do the same in java.
You can do this with 2N steps and a map with N elements.
Walk the old list following the 'next' pointers. For each node you visit, add a node to your new list, connect the previous node in your new list to the new node, store the old node random pointer in the new new node, then store a mapping of the old node pointer to the new node pointer in a map.
Walk the new list, and for each random pointer, look it up in the map to find the associated node in the new list to replace it with.
I too was asked this question in interview recently.
Here is what i proposed.
Create a map of original list nodes where addreess of each node will be key and the offset of random pointer will be the value.
Now create a new linked list with random pointer =null from the original map.
In the end, iterate through the original list , with the help of map get offset of original pointer and use that offset to link random pointer in newly created map.
Interviewer was not happy in the end.May be looking for some better approach or he had the set answer in his mind and unable to grasp new way of solving it.
in O(n) time and with constant space
public class CloneLinkedListWithRandomPointer {
public static void main(String[] args) throws Exception {
SpecialLink link = new SpecialLink(1);
SpecialLink two = new SpecialLink(2);
SpecialLink three = new SpecialLink(3);
SpecialLink four = new SpecialLink(4);
SpecialLink five = new SpecialLink(5);
link.next = two;
two.next = three;
three.next = four;
four.next = five;
link.random = four;
two.random = five;
three.random = null;
four.random = five;
five.random=link;
SpecialLink copy = cloneSpecialLinkedList(link);
System.out.println(link);
System.out.println(copy);
}
public static SpecialLink cloneSpecialLinkedList(SpecialLink link) throws Exception{
SpecialLink temp = link;
while(temp != null){
temp.next = (SpecialLink) temp.clone();
temp = temp.next==null?temp.next:temp.next.next;
}
temp = link;
while(temp != null){
temp.next.random = temp.random!=null?temp.random.next:null;
temp = temp.next==null?temp.next:temp.next.next;
}
SpecialLink copy = link.next;
temp = link;
SpecialLink copyTemp = copy;
while(temp.next!= null && copyTemp.next != null){
temp.next = temp.next.next;
copyTemp.next = copyTemp.next.next;
temp = temp.next;
copyTemp = copyTemp.next;
}
return copy;
}
}
class SpecialLink implements Cloneable{
enum Type{
ORIGINAL,COPY
}
int val;
SpecialLink next;
SpecialLink random;
Type type;
public void setValue(int value){
this.val = value;
}
public SpecialLink addNode(int value){
return next = new SpecialLink(value);
}
public SpecialLink(int value) {
super();
this.val = value;
this.type = Type.ORIGINAL;
}
#Override
public String toString() {
SpecialLink temp = this;
StringBuilder builder = new StringBuilder();
while(temp != null){
builder.append(temp.val).append("--").append(temp.type.toString()).append("->").append(temp.random == null? null:temp.random.val).append("--").append(temp.random == null? null:temp.random.type);
builder.append(", ");
temp = temp.next;
}
return builder.toString();
}
#Override
public Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
SpecialLink clone = (SpecialLink) super.clone();
clone.type = Type.COPY;
return clone;
}
}
Walk the list and use clone()?
I wrote code for #MahlerFive 's solution, which works without mapping.
Here's the code:
private static class Node {
private String item;
private Node next;
private Node random;
}
public static Node cloneLinkedStructure(Node head) {
// make holes after each original node
for (Node p = head; p != null;) {
Node pnext = p.next;
Node hole = new Node();
hole.item = ".";
p.next = hole;
hole.next = pnext;
p = pnext;
}
Node fakeHead = new Node(); // fake new head
Node q = fakeHead;
Node p = head;
while (p != null) {
// build the new linked structure
Node oldq = q;
q = new Node();
q.item = p.item;
oldq.next = q;
q.random = p.random.next; // link to a hole
Node hole = p.next;
hole.random = q; // use link RANDOM as a backward link to new node
p = hole.next;
}
q.next = null;
Node newHead = fakeHead.next; // throw fake head
// build random links for the new linked structure
for (q = newHead; q != null; q = q.next)
q.random = q.random.random;
// delete holes to restore original linked structure
for (p = head; p != null; p = p.next)
p.next = p.next.next;
return newHead;
}
1) Create the copy of node 1 and insert it between node 1 & node 2 in original Linked List, create the copy of 2 and insert it between 2 & 3.. Continue in this fashion, add the copy of N afte the Nth node
2) Now copy the arbitrary link in this fashion
original->next->arbitrary = original->arbitrary->next; /*TRAVERSE TWO NODES*/
This works because original->next is nothing but copy of original and Original->arbitrary-> next is nothing but copy of arbitrary.
3) Now restore the original and copy linked lists in this fashion in a single loop.
original->next = original->next->next;
copy->next = copy->next->next;
4) Make sure that last element of original->next is NULL.
Time Complexity: O(n)
Auxiliary Space: O(1)
source
Here is the Java implementation:
public static <T> RandomLinearNode<T> clone(RandomLinearNode<T> head) {
if (head == null) {
return head;
}
RandomLinearNode<T> itr = head, temp;
// insert copy nodes after each original nodes
while (itr != null) {
temp = new RandomLinearNode<T>(itr.getElement());
temp.next(itr.next());
itr.next(temp);
itr = temp.next();
}
// copy the random pointer
itr = head;
while (itr != null && itr.next() != null) {
if (itr.random() != null) {
itr.next().random(itr.random().next());
}
itr = itr.next().next();
}
// break the list into two
RandomLinearNode<T> newHead = head.next();
itr = head;
while (itr != null && itr.next() != null) {
temp = itr.next();
itr.next(temp.next());
itr = temp.next();
}
return newHead;
}
Here is the unit tests
#Test
public void cloneLinkeListWithRandomPointerTest() {
RandomLinearNode<Integer> one = new RandomLinearNode<Integer>(1, null, null);
RandomLinearNode<Integer> two = new RandomLinearNode<Integer>(2, one, null);
RandomLinearNode<Integer> three = new RandomLinearNode<Integer>(3, two, null);
RandomLinearNode<Integer> four = new RandomLinearNode<Integer>(4, three, null);
RandomLinearNode<Integer> five = new RandomLinearNode<Integer>(5, four, four);
RandomLinearNode<Integer> six = new RandomLinearNode<Integer>(6, five, two);
RandomLinearNode<Integer> seven = new RandomLinearNode<Integer>(7, six, three);
RandomLinearNode<Integer> eight = new RandomLinearNode<Integer>(8, seven, one);
RandomLinearNode<Integer> newHead = LinkedListUtil.clone(eight);
assertThat(eight, not(sameInstance(newHead)));
assertThat(newHead.getElement(), equalTo(eight.getElement()));
assertThat(newHead.random().getElement(), equalTo(eight.random().getElement()));
assertThat(newHead.next().getElement(), equalTo(eight.next().getElement()));
assertThat(newHead.next().random().getElement(), equalTo(eight.next().random().getElement()));
assertThat(newHead.next().next().getElement(), equalTo(eight.next().next().getElement()));
assertThat(newHead.next().next().random().getElement(), equalTo(eight.next().next().random().getElement()));
assertThat(newHead.next().next().next().getElement(), equalTo(eight.next().next().next().getElement()));
assertThat(newHead.next().next().next().random().getElement(), equalTo(eight.next().next().next().random().getElement()));
}

Invert linear linked list

a linear linked list is a set of nodes. This is how a node is defined (to keep it easy we do not distinguish between node an list):
class Node{
Object data;
Node link;
public Node(Object pData, Node pLink){
this.data = pData;
this.link = pLink;
}
public String toString(){
if(this.link != null){
return this.data.toString() + this.link.toString();
}else{
return this.data.toString() ;
}
}
public void inc(){
this.data = new Integer((Integer)this.data + 1);
}
public void lappend(Node list){
Node child = this.link;
while(child != null){
child = child.link;
}
child.link = list;
}
public Node copy(){
if(this.link != null){
return new Node(new Integer((Integer)this.data), this.link.copy());
}else{
return new Node(new Integer((Integer)this.data), null);
}
}
public Node invert(){
Node child = this.link;
while(child != null){
child = child.link;
}
child.link = this;....
}
}
I am able to make a deep copy of the list. Now I want to invert the list so that the first node is the last and the last the first. The inverted list has to be a deep copy.
I started developing the invert function but I am not sure. Any Ideas?
Update: Maybe there is a recursive way since the linear linked list is a recursive data structure.
I would take the first element, iterate through the list until I get to a node that has no child and append the first element, I would repeat this for the second, third....
I sometimes ask this question in interviews...
I would not recommend using a recursive solution, or using a stack to solve this. There's no point in allocating O(n) memory for such a task.
Here's a simple O(1) solution (I didn't run it right now, so I apologize if it needs some correction).
Node reverse (Node current) {
Node prev = null;
while (current != null) {
Node nextNode = current.next;
current.next = prev;
prev = current;
current = nextNode;
}
return prev;
}
BTW: Does the lappend method works? It seems like it would always throw a NullReferenceException.
There's a great recursive solution to this problem based on the following observations:
The reverse of the empty list is the empty list.
The reverse of a singleton list is itself.
The reverse of a list of a node N followed by a list L is the reverse of the list L followed by the node N.
You can therefore implement the reverse function using pseudocode along these lines:
void reverseList(Node node) {
if (node == null) return; // Reverse of empty list is itself.
if (node.next == null) return; // Reverse of singleton list is itself.
reverseList(node.next); // Reverse the rest of the list
appendNodeToList(node, node.next); // Append the new value.
}
A naive implementation of this algorithm runs in O(n2), since each reversal requires an append, which requires an O(n) scan over the rest of the list. However, you can actually get this working in O(n) using a clever observation. Suppose that you have a linked list that looks like this:
n1 --> n2 --> [rest of the list]
If you reverse the list beginning at n2, then you end up with this setup:
n1 [reverse of rest of the list] --> n2
| ^
+------------------------------------------+
So you can append n1 to the reverse of the rest of the list by setting n1.next.next = n1, which changes n2, the new end of the reverse list, to point at n1:
[reverse of the rest of the list] --> n2 --> n1
And you're golden! Again more pseudocode:
void reverseList(Node node) {
if (node == null) return; // Reverse of empty list is itself.
if (node.next == null) return; // Reverse of singleton list is itself.
reverseList(node.next); // Reverse the rest of the list
node.next.next = node; // Append the new value.
}
EDIT: As Ran pointed out, this uses the call stack for its storage space and thus risks a stack overflow. If you want to use an explicit stack instead, you can do so like this:
void reverseList(Node node) {
/* Make a stack of the reverse of the nodes. */
Stack<Node> s = new Stack<Node>();
for (Node curr = node; node != null; node = node.next)
s.push(curr);
/* Start unwinding it. */
Node curr = null;
while (!s.empty()) {
Node top = s.pop();
/* If there is no node in the list yet, set it to the current node. */
if (curr == null)
curr = top;
/* Otherwise, have the current node point to this next node. */
else
curr.next = top;
/* Update the current pointer to be this new node. */
curr = top;
}
}
I believe that this similarly inverts the linked list elements.
I would treat the current list as a stack (here's my pseudo code):
Node x = copyOf(list.head);
x.link = null;
foreach(node in list){
Node temp = copyOf(list.head);
temp.link = x;
x = temp;
}
At the end x will be the head of the reversed list.
I more fammiliar whit C, but still let me try. ( I just do not sure if this runs in Java, but it should)
node n = (well first one)
node prev = NULL;
node t;
while(n != NULL)
{
t = n.next;
n.next = prev;
prev = n;
n = t;
}
Reversing a single-linked list is sort of a classic question. It's answered here as well (and well answered), it does not requires recursion nor extra memory, besides a register (or 2) for reference keeping.
However to the OP, I guess it's a school project/homework and some piece of advice, if you ever get to use single linked list for some real data storage, consider using a tail node as well. (as of now single linked lists are almost extinct, HashMap buckets comes to mind, though).
Unless you have to check all the nodes for some condition during 'add', tail is quite an improvement. Below there is some code that features the reverse method and a tail node.
package t1;
public class SList {
Node head = new Node();
Node tail = head;
private static class Node{
Node link;
int data;
}
void add(int i){
Node n = new Node();
n.data = i;
tail = tail.link =n;
}
void reverse(){
tail = head;
head = reverse(head);
tail.link = null;//former head still links back, so clear it
}
private static Node reverse(Node head){
for (Node n=head.link, link; n!=null; n=link){//essentially replace head w/ the next and relink
link = n.link;
n.link = head;
head = n;
}
return head;
}
void print(){
for (Node n=head; n!=null;n=n.link){
System.out.println(n.data);
}
}
public static void main(String[] args) {
SList l = new SList();
l.add(1);l.add(2);l.add(3);l.add(4);
l.print();
System.out.println("==");
l.reverse();
l.print();
}
}
I was wondering something like that(I didnt test it, so):
invert(){
m(firstNode, null);
}
m(Node v, Node bef){
if(v.link != null)
m(v.link,v);
else
v.link=bef;
}
Without much testing,
Node head = this;
Node middle = null;
Node trail = null;
while (head != null) {
trail = middle;
middle = head;
head = head.link;
middle.link = trail;
}
head = middle;
return head;
public ListNode Reverse(ListNode list)
{
if (list == null) return null;
if (list.next == null) return list;
ListNode secondElem = list.next;
ListNode reverseRest = Reverse(secondElem);
secondElem.Next = list;
return reverseRest;
}
Hope this helps.

Categories