Why each time we create new node p.next so we need to assign null to this.next? isn't always null any way? and which role does it play in LinkedList ?
if we try to print out this.next it will be null before we assign it to null.
System.out.println(this.next);
Result is null
Also if p.next point to the new node why we need to set p = p.next to point to the same node? if the purpose to set tail to p at last, can't we just set tail = p.next which is the last one after for loop is finished.
public class EnkeltLenketListe<T>{
private T value;
private Node<T> next;
private Node(T value, Node<T> next)
{
System.out.println(this.next);
this.next = next;
this.value = value;
}
}
private Node<T> head, tail;
public EnkeltLenketListe(T[] a)
{
this();
int i = 0; for (; i < a.length && a[i] == null; i++);
if (i < a.length)
{
head = new Node<>(a[i], null);
Node<T> p = head;
for (i++; i < a.length; i++)
{
if (a[i] != null)
{
p.next = new Node<>(a[i], null);
p = p.next;
}
}
tail = p;
}
}
Why each time we create new node p.next so we need to assign null to this.next?
while adding and removing a nodes, we have to make sure that nodes don't point to unintended nodes. they might have pointing to some nodes.
why we need to set p = p.next to point to the same node
to locate and maintain your position in the list while you are traversing the list, you start from head, and continue to remaining nodes. if p=p.next, how are going to traverse the list?
can't we just set tail = p.next which is the last one after for loop is finished.
No, we can not because in this case p.next is equivalent to p.p.next because p was set to p.next inside the loop. test it by adding the following before tail=p, you should get null
System.out.println(p.next);
Edited:
your list is singly linked list which means every node except the tail should have a pointer to next node, you started with
head = new Node<>(a[i], null);
Node<T> p = head;
in this case p and head are pointing Node 0 see image below. if the next NOde in the array is not null, let see what happens in the for loop
p.next = new Node<>(a[i], null);
p = p.next;
In this case p.next is pointing to Node 1 (see image below), where as p which were pointing to Node 0 is now set to point to Node 1. so both are pointing to 'Node 1`. the last one:
tail = p;
You said that why don't we just tail=p.next? No, we can not because in this case p.next is equivalent to p.p.next because p was set to p.next inside the loop.
read about singly linked list here
Try to use contradiction. If you didn't set p = p.next, in the next iteration of the loop, again you will set the new node to the next position of the previous node. Hence, all the time p is the head and you didn't move the p anymore!
Therefore, you need to move p in each iteration after setting p.next. Indeed, it is a pointer to the last element of the list.
Related
I was wondering if it is possible to traverse singly LinkedList from tail to head with only using the for-loop.
For Example, I can traverse from head to tail with given head.
LinkedList temp = head;
for (int i = 0; i < size-1; i++) {
temp = temp.getNext();
}
But it is possible to do below code for traversing from tail to head?
LinkedList temp = tail;
for (int i = 0; i < size -1; i++) {
temp = temp.getNext();
}
Well, the simplest answer is, use doubly linked list if you need to traverse back to head.
However, if you really want to do so with a singly linked list, and if you don't want to use any library, you should implement the class on your own and add a reverse method like this:
public void reverse () {
Node pointer = head;
Node previous = null, current = null;
while (pointer != null) {
current = pointer;
pointer = pointer.next;
current.next = previous;
previous = current;
head = current;
}
}
By this method you can reverse the current singly linked list, so you can traverse from the tail to head of original linked list.
Can someone explain why
temp.setNext(current.getNext()); has been used I am not understanding
public void add(Object data, int index)
// post: inserts the specified element at the specified position in this list.
{
Node temp = new Node(data);
Node current = head;
// crawl to the requested index or the last element in the list,
// whichever comes first
for(int i = 1; i < index && current.getNext() != null; i++)
{
current = current.getNext();
}
// set the new node's next-node reference to this node's next-node reference
temp.setNext(current.getNext());
// now set this node's next-node reference to the new node
current.setNext(temp);
listCount++;// increment the number of elements variable
}
You want the new Node (referenced by the temp variable) to be inserted before the node at the index position, which is referenced by current.getNext() after the while loop is done.
Therefore you first set the next Node of temp to current.getNext() (temp.setNext(current.getNext());) and then set the next Node of current to temp (current.setNext(temp);). This places temp between current and the original current.getNext().
before :
... -> current -> current.getNext() -> ...
after :
... -> current -> temp -> current.getNext() (the original current.getNext()) -> ...
So I'm attempting to quicksort a singly linked list. Since I can't traverse backward like the traditional quicksort, I made it traverse forward to partition the list... But, if anyone could tell me where I'm getting this StackOverflowError it would really be appreciated.
public static <E extends Comparable<E>> void quickSort(MyNode<E> first, MyNode<E> last) {
if(first != last) {
MyNode<E> pivot = first;
MyNode<E> currentNode = first.next;
MyNode<E> previousNode = first;
while(currentNode.next != last && currentNode.next != null) {
if (currentNode.element.compareTo(pivot.element) < 0) {
MyNode<E> temp = new MyNode<E>(currentNode.element);
previousNode.next = currentNode.next;
temp.next = first;
first = currentNode;
}
previousNode = previousNode.next;
currentNode = currentNode.next;
}
quickSort(first, pivot);
quickSort(pivot, last);
}
}
EDIT:
So thanks to your guys help I am a little bit closer I think... But I am still stuck. I have changed my code based on suggestions. But now it is just not sorting correctly.. The issue is when I try to move current to the front of the list... It seems to disconnect it from the list. So, when I print out the list all I get back is the pivot and the values greater than the pivot.. All of the lesser than elements have disappeared..
public static <E extends Comparable<E>> void quickSort(MyNode<E> first, MyNode<E> last) {
if(first != last && first != null) {
E pivot = first.element;
MyNode<E> current = first.next;
MyNode<E> previous = first;
while(previous != last && current != null) {
if (current.element.compareTo(pivot) < 0) {
previous.next = current.next;
first = current;
first.next = previous;
current = previous.next;
}
else {
previous = previous.next;
current = current.next;
}
//recursive calls will go here... Just want to get the logic right first
}
}
}
The main problem (the StackOverflowError you're getting) is, that you don't change pivot and hence the recursive call to quickSort(pivot, last); will be the same as quickSort(first, last); and thus first != last will always be true for any list of size > 1.
You should first set pivot to the middle element, then sort elements according to being greater or smaller than the pivot and then call quicksort recursively for the sublists. Here though, you shouldn't pass pivot twice, otherwise you'd still get a stack overflow.
Assume you end up with a sublist of only two elements and you pick one as the pivot. One recursive call would do nothing since first = last but the other would essentially be quicksort(first, last), would select the same pivot and repeat with the very same sublist.
So either pass pivot +/- 1 to one of the recursive calls (since it's a linked list I'd suggest quicksort(pivot.next, last) ) or check whether the sublist has more than 2 elements before doing the recursion.
From a quick glance... you are looping quickSort too many times and therefor you get that error.
example
private void countUp(int x){
System.out.println(x);
countUp(++x);
}
this will count about 10541 times for me... before throwing that error.
With that in mind... you might have an infinite loop somewhere OR your array are too large.
Completed my hw and I got it wrong. I do not understand why.
For my insert front I do the following.
head.next.prev = newNode;
newNode.next = head;
newNode.prev = null;
head.prev = newnode;
head.next.prev = head;
size++;
But instead the solution looks like this following
head.next.prev = newNode(item, head, head.next); // newNode(item,prev,next); So basically head.next.prev is pointing to a newnode here newnode.prev = head and newnode.next = head.next. Ok that make sense.
head.next = head.next.prev; // huh?
size++;
to me the solution doesn't make sense and my solution is perfectly logical. If you make head.next.prev = a new node, you should make head.next.prev = head, or else there will be a jump right? Also head.next = head.next.prev; doesn't make any sense. That line is basically saying head.prev is pointing to the head itself. Shouldn't it be head.next.prev = head;?
Can anyone point out what's going on? i know the format between the solutions is different but i'm more interested in the logic
The complete code is shown below
There's a lot of confusion. So here's how head is declared
public class DList {
/**
* head references the sentinel node.
* size is the number of items in the list. (The sentinel node does not
* store an item.)
*
* DO NOT CHANGE THE FOLLOWING FIELD DECLARATIONS.
*/
protected DListNode head;
protected int size;
/* DList invariants:
* 1) head != null.
* 2) For any DListNode x in a DList, x.next != null.
* 3) For any DListNode x in a DList, x.prev != null.
* 4) For any DListNode x in a DList, if x.next == y, then y.prev == x.
* 5) For any DListNode x in a DList, if x.prev == y, then y.next == x.
* 6) size is the number of DListNodes, NOT COUNTING the sentinel,
* that can be accessed from the sentinel (head) by a sequence of
* "next" references.
*/
/**
* newNode() calls the DListNode constructor. Use this class to allocate
* new DListNodes rather than calling the DListNode constructor directly.
* That way, only this method needs to be overridden if a subclass of DList
* wants to use a different kind of node.
* #param item the item to store in the node.
* #param prev the node previous to this node.
* #param next the node following this node.
*/
protected DListNode newNode(Object item, DListNode prev, DListNode next) {
return new DListNode(item, prev, next);
}
/**
* DList() constructor for an empty DList.
*/
public DList() {
head = newNode(null, head, head);
head.next = head;
head.prev = head;
size = 0;
}
public insertfront(Object item){
???????????}
//////////////////// below is the DlistNoe.java
public class DListNode {
/**
* item references the item stored in the current node.
* prev references the previous node in the DList.
* next references the next node in the DList.
*
* DO NOT CHANGE THE FOLLOWING FIELD DECLARATIONS.
*/
public Object item;
protected DListNode prev;
protected DListNode next;
/**
* DListNode() constructor.
* #param i the item to store in the node.
* #param p the node previous to this node.
* #param n the node following this node.
*/
DListNode(Object i, DListNode p, DListNode n) {
item = i;
prev = p;
next = n;
}
}
There's a lot wrong with your insertion code. Just read it in English:
head.next.prev = newNode;
Point the first node's "prev" to the new node (ok)
newNode.next = head;
Point the new node's "next" to the head (what?)
newNode.prev = null;
Point the new node's "prev" to null (it's the first node, so it should point to head)
head.prev = newnode;
Point the head's "prev" to null (you're inserting at the front so you shouldn't be touching this)
head.next.prev = head;
Point the first node's prev to head (undoing what you did in the first step)
So now you have a head that's still pointing to the old first element, and is not pointing back to the last element of the list anymore. And a new element that is not fully inserted (its "prev" is not pointing at anything, and its "next" is pointing at the wrong element).
Yeah, not really correct, I'd say. If you read the correct solution like the above, hopefully you'll see it makes more sense.
The trouble with structures like linked lists is that when you start modifying references, you lose which nodes are which.
So, let's name some nodes.
The linked list before insertion:
H -> A -> B -> C
H.next = A
H.prev = null
A.next = B
A.prev = H
And so on...
The Goal linked list:
H -> N -> A -> B -> C
H.next = N
H.prev = null (unchanged)
A.next = B (unchanged)
A.prev = N
N.next = A
N.prev = H
Based on the DList invariants and the given solution, there is a head node that does not hold a value that stays the head.
Then let's step through your code:
head.next.prev = newNode; // H.next -> A, A.prev = N. This seems fine.
newNode.next = head; // N.next = H. What? This doesn't match our goal.
newNode.prev = null; // N.prev = null. Also doesn't match our goal.
head.prev = newnode; // H.prev = n. Also doesn't match our goal.
head.next.prev = head; // H.next -> A, looks like you mean this to be N, but its still A.
// thus A.prev = H. Also doesn't match our goal.
size++;
Finally, let's look at the given solution.
head.next.prev = newNode(item, head, head.next);
// First the function, H.next -> A, so...
// N.prev = H. Matches goal.
// N.next = A. Also matches goal.
// Then the assignment:
// head.next -> A, A.prev = N. Matches goal.
head.next = head.next.prev;
// head.next -> A, A.prev -> N, H.next = N. Matches goal.
size++;
And thus, all 4 changed references have been set.
Consider:
Node reverse(Node head) {
Node previous = null;
Node current = head;
Node forward;
while (current != null) {
forward = current.next;
current.next = previous;
previous = current;
current = forward;
}
return previous;
}
How exactly is it reversing the list?
I get that it first sets the second node to forward. Then it says current.next is equal to a null node previous. Then it says previous is now current. Lastly current becomes forward?
I can't seem to grasp this and how it's reversing. Can someone please explain how this works?
You reverse the list iteratively and always have the list in the interval [head, previous] correctly reversed (so current is the first node that has its link not set correctly). On each step you do the following:
You remember the next node of current so that you can continue from it
You set the link of current to be pointing to previous, which is the correct direction if you think about it
You change previous to be current, because now current also has its link set correctly
You change the first node that does not have its link set correctly to be the one remembered in the first step
If you do that for all the nodes, you can prove (with induction for instance) that the list will be correctly reversed.
The code simply walks the list and inverts the links until it reaches the previous tail, which it returns as the new head.
Before:
Node 1 (Head) -> Node 2 -> Node 3 -> Node 4 (Tail) -> null
After:
null <- Node 1 (Tail) <- Node 2 <- Node 3 <- Node 4 (Head)
The easiest way to think about it is to think like this:
First add the head of the list to a new linked list.
Keep iterating through the original and keep adding the nodes before the head of the new linked list.
Diagram:
Initially:
Original List -> 1 2 3 4 5
New List -> null
1st Iteration
Original List -> 1 2 3 4 5
New List -> 1->null [head shifted to left, now newHead contains 1 and points to null]
2nd Iteration
Original List -> 1 2 3 4 5
New List -> 2-> 1->null [head shifted to left, now newHead contains 2 and points to next node which is 1]
3rd Iteration
Original List -> 1 2 3 4 5
New List ->3 -> 2-> 1->null [head shifted to left, now newHead contains 2 and points to next node which is 1]
Now it keeps looping through till the end. So finally the new list becomes:
New List-> 5 -> 4 -> 3 -> 2 -> 1 -> null
The code for the same should be like this (made it easy to understand):
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public ListNode reverseList(ListNode head) {
if(head == null) {
return null;
}
if(head.next == null) {
return head;
}
ListNode current = head;
ListNode previous = new ListNode(head.val);
previous.next = null;
while(current.next != null) {
current = current.next;
previous = addBeforeHead(current, previous);
}
return previous;
}
private ListNode addBeforeHead(ListNode node, ListNode head) {
if (node == null) return null;
ListNode temp = new ListNode(node.val);
temp.next = head;
head = temp;
return head;
}
public Node getLastNode()
{
if(next != null)
return next.getLastNode();
else
return this;
}
public Node reverse(Node source)
{
Node reversed = source.getLastNode();
Node cursor = source;
while(cursor != reversed)
{
reversed.addNodeAfter(cursor.getInfo());
cursor = cursor.getNodeAfter();
}
source = reversed;
return source;
}
I call it "cherry picking". The idea is to minimize the number of swaps. Swapping happens between a near and far index. It's a twp-pass algorithm.
(Odd length) A -> B -> C -> D -> E
(Even length) A -> B -> C -> D
Pre-Condition: N >= 2
Pass 1: Count N, the number of elements
Pass 2:
for(j=0 -> j<= (N/2 -1))
{
swap(j, (N-1)-j)
}
Example 1:
For above Odd length list, N = 5 and there will be two swaps
when j=0, swap(0, 4) // Post swap state: E B C D A
when j=1, swap(1, 3) // Post swap state: E D C B A
The mid point for odd length lists remains intact.
Example 2:
For above Even length list, N = 4 and there will be two swaps
when j=0, swap(0, 3) // Post swap state: D B C A
when j=1, swap(1, 2) // Post swap state: D C B A
Swapping applies to data only, not to pointers, and there might be any sanity checks missed, but you got the idea.
list_t *reverse(list_t *a)
{
list_t *progress = NULL;
while(a)
{
list_t *b; //b is only a temporary variable (don't bother focusing on it)
b = a->next;
a->next = progress; // Because a->next is assigned to another value,
// we must first save a->next to a different
// variable (to be able to use it later)
progress = a; // progress is initially NULL (so a->next = NULL
// (because it is the new last element in the list))
a = b; // We set a to b (the value we saved earlier, what
// a->next was before it became NULL)
/*
Now, at the next iteration, progress will equal a, and a will equal b.
So, when I assign a->next = progress, I really say, b->next = a.
and so what we get is: b->a->NULL.
Maybe that gives you an idea of the picture?
What is important here is:
progress = a
and
a = b
Because that determines what a->next will equal:
c->b->a->0
a's next is set to 0
b's next is set to a
c's next is set to b
*/
}
return progress;
}
The basic idea is to detach the head node from the first list and attach it to the head of a second list. Keep repeating until the first list is empty.
Pseudocode:
function reverseList(List X) RETURNS List
Y = null
WHILE X <> null
t = X.next
X.next = Y
Y = X
X = t
ENDWHILE
RETURN Y
ENDfunction
If you wish to leave the original list undisturbed then you can code a copying version recursively with the use of a helper function.
function reverseList(List X) RETURNS List
RETURN reverseListAux(X, null)
ENDfunction
function reverseListAux(List X, List Y) RETURNS List
IF X = null THEN
RETURN Y
ELSE
RETURN reverseListAux(X.next, makeNode(X.data, Y))
ENDfunction
Note that the helper function is tail recursive. This means that you can create a copying reversal using iteration.
function reverseList(List X) RETURNS List
Y = null
WHILE X <> null
Y = makeNode(x.data, Y)
X = X.next
ENDWHILE
RETURN Y
ENDfunction
Reversing a singly-linked list using iteration:
current = head // Point the current pointer to the head of the linked list
while(current != NULL)
{
forward = current->link; // Point to the next node
fforward = forward->link; // Point the next node to next node
fforward->link = forward; // 1->2->3,,,,,,,,,this will point node 3 to node 2
forward->link = current; // This will point node 2 to node 1
if(current == head)
current->link = NULL; // If the current pointer is the head pointer it should point to NULL while reversing
current = current->link; // Traversing the list
}
head = current; // Make the current pointer the head pointer
Implementation of a singly-linked list reversal function:
struct Node
{
int data;
struct Node* link;
}
Node* head = NULL;
void reverseList()
{
Node* previous, *current, *next;
previous = NULL;
current = head;
while(current != NULL)
{
next = current-> link;
current->link = previous;
previous = current;
current = next;
}
head = previous;
}
Here is a simple function to reverse a singly linked list
// Defining Node structure
public class Node {
int value;
Node next;
public Node(int val) {
this.value=val;
}
}
public LinkedList reverse(LinkedList list) {
if(list==null) {
return list;
}
Node current=list.head;
Node previous=null;
Node next;
while(current!=null) {
next=current.next;
current.next=previous;
previous=current;
current=next;
}
list.head=previous;
return list;
}
For better understanding, you can watch this video https://youtu.be/6SYVz-pnVwg
If you want to use recursion:
class Solution {
ListNode root=null;
ListNode helper(ListNode head)
{
if (head.next==null)
{ root= head;
return head;}
helper (head.next).next=head;
head.next=null;
return head;
}
public ListNode reverseList(ListNode head) {
if (head==null)
{
return head;
}
helper(head);
return root;
}
}
public void reverseOrder() {
if(head == null) {
System.out.println("list is empty");
}
else {
Node cn = head;
int count = 0;
while (cn != null) {
count++;
cn = cn.next;
}
Node temp;
for(int i = 1; i<=count; i++) {
temp = head;
for(int j = i; j<count; j++) {
temp = temp.next;
}
System.out.print(temp.data+" ->");
}
System.out.print("null");
}
}