In reading the LinkedList doc, I am a little puzzled by the uses of "header". Normally, the header is the first node in a linkedList. But here it looks like the 'header' is a dummy node in the list and it points to the first and last nodes of the list, thus making the LinkedList a circular one. Is that true?
private transient Entry<E> header = new Entry<E>(null, null, null);
public LinkedList() {
header.next = header.previous = header;
}
public E getFirst() {
if (size==0)
throw new NoSuchElementException();
return header.next.element;
}
public E getLast() {
if (size==0)
throw new NoSuchElementException();
return header.previous.element;
}
public E removeFirst() {
return remove(header.next);
}
But here it looks like the 'header' is a dummy node in the list and it points to the first and last nodes of the list
That much is true
thus making the LinkedList a circular one.
That's not exactly true: structurally, the list is indeed circular, because the header "loops" it around. That is only an implementation detail, a common trick that lets you avoid declaring two things (header and tailPiece) instead of one. The fact that the same entry is used for both ends by itself is insufficient to make the list circular: there is no way for you to loop around the last node "from the outside", because the count prevents you from doing so.
You're right. header stores references to both the head and tail of the list. This helps in reducing cost of operations involving delete/add/view for both the ends of the list.
With the availability of references to both the ends, operations like getFirst, getLast, removeFirst, removeLast, addFirst, addLast etc. don't require list traversal.
A circular list is a cheap way to avoid storing both head and tail pointers in the top-level structure. I don't know about Java's LinkedList implementation, but this is certainly a trick pulled in e.g. the GCC implementation of std::list.
The implementation of LinkedList is using what's called s sentinel node. They've chosen to use one sentinel for both head and tail; other implmentations will use two separate sentinels.
In either case, the use of sentinels allow the rest of the implementation code to not deal with the null case. For example, consider adding a node. Without a sentinel:
Node newNode = ...;
if (header == null) {
header = newNode;
tail = newNode;
} else {
newNode.previous = tail;
tail.next = newNode;
tail = newNode;
}
With the sentinel:
Node newNode = ...;
newNode.previous = sentinel.previous;
newNode.next = sentinel;
sentinel.previous = newNode;
Here's the Wikipedia article on Sentinel Nodes.
Related
I have this Code for adding new node to my linked list, I want to add the new node at the beginning of the list ,I wrote this code on the insert function ,
Node insert(Node start, int x){
Node newNode = new Node(x);
if(start == null) {
return start = newNode;
} else {
newNode.next = start;
start = newNode;
}
return start;
}
And this is my main class ,Is there any other way to do it more efficiently ?
LinkedList list=new LinkedList();
Node startPoint=new Node(20);
Node newNode=list.insert(startPoint, 16);
Node newNode1=list.insert(newNode, 22);
Node newNode2=list.insert(newNode1, 2);
Node newNode3=list.insert(newNode2, 5);
Node newNode4=list.insert(newNode3, 44);
Node newNode5=list.insert(newNode4, 77);
And this is my main class ,Is there any other way to do it more efficiently ?
There is not.
This is the classical solution to this problem.
The reason why you can't do any better that this, is because this implementation of this operation takes O(1) time. Which is really cool and sexy, because the time to perform it does not depend on the size of the input, which is a really cool property to have on large data sets.
You can continue exercising your DS skills by implementing more complex operations with linked lists, such as insertion into an arbitrary position in the list or reversal of a linked list.
The efficiency is fine, but you can make it more elegant.
First of all, your main program should not have to know about nodes. It should just have to create the linked list instance, and add integers to it. Your main code now maintains some state (like startPoint) that actually the linked list instance should manage for you. It should maintain a reference to the first node in its list (which starts as null): often this is called head.
Since you write that you "...want to add the new node at the beginning of the list", you would not need to pass a node as argument to insert. The linked instance can use its head member to do the insertion just before it, and then update its head to refer to that new node. The insert method should also not need to return the newly created node. The caller should not have to worry about such implementation details.
Finally, you could add a Node constructor overload that accepts a reference for its next member. This would help to make your insert method very concise.
So, make your Node constructors like this (I assume the value member is called value, if you used a different name, like data, adapt as needed):
class Node {
private final int value;
private Node next;
public Node(int value) {
this.value = value;
this.next = null;
}
public Node(int value, Node next) {
this.value = value;
this.next = next;
}
/* ... other methods */
}
Then in your linked list class, make sure you have a head member, and define your insert method such that it only takes a value argument:
public class LinkedList {
private Node head;
public LinkedList() {
this.head = null;
}
void insert(int x) {
head = new Node(x, head);
}
/* other methods ... */
}
And then your main program could do:
LinkedList list = new LinkedList();
list.insert(20);
list.insert(16);
list.insert(22);
list.insert(2);
/* ...etc... */
Of course, you would need to add methods that allow you to retrieve values from the list, and perform other interesting actions on it.
You are given a doubly linked list which in addition to the next and previous pointers, it could have a child pointer, which may or may not point to a separate doubly linked list. These child lists may have one or more children of their own, and so on, to produce a multilevel data structure, as shown in the example below.
Flatten the list so that all the nodes appear in a single-level, doubly linked list. You are given the head of the first level of the list.
class Solution {
/*Global variable pre to track the last node we visited */
Node pre = null;
public Node flatten(Node head) {
if (head == null) {
return null;
}
/*Connect last visted node with current node */
if (pre != null) {
pre.next = head;
head.prev = pre;
}
pre = head;
/*Store head.next in a next pointer in case recursive call to flatten head.child overrides head.next*/
Node next = head.next;
flatten(head.child);
head.child = null;
flatten(next);
return head;
}
}
For the question, the above leetcode solution works. But I don't understand this:
/*Store head.next in a next pointer in case recursive call to flatten head.child overrides head.next*/
Node next = head.next;
Can anyone explain this part? How does the head.child override head.next?
flatten(head.child) may change head.next due to the part where we connect last visited node with the current node:
if (pre != null) {
pre.next = head;
head.prev = pre;
}
At this stage, pre represents older head and head represents head.child. So we actually connect our head with its child. But if we do so, we will lose our connection to the actual head.next, therefore we have to keep it in an extra variable called next. That's why we keep it before calling the flatten() function.
Having trouble understanding linked lists. This is in java. I am writing some methods, add, remove, find. But wondering here, is Head, which is defined as a type Node the actual first Node? does it contain data and a next Node reference? Or does it somehow tell what the data is of the first?
Thanks
The head node is the first node in the list. The tail node is the last node in the list.
There's nothing special about either of them.
In your LinkedList class you might have references to head and tail, but the nodes themselves are just nodes.
Generally, not limited to Java, all list nodes are the same, and the "head" node is the first one on the list. This, "head", is usually a variable that is a reference (or a pointer) to the first list node.
A simple singly-linked-list node may look like
class ListNode
{
Object data; // The data added to the list
ListNode next; // Reference to the next item in the list
}
Then "head" would just be
ListNode head;
that is, a variable named "head" that holds (a reference to) a ListNode.
The issue gets somewhat confused in Java because everything (except primitives like int) is a reference — so this looks like "head is a ListNode" when it's actually "head is a reference to a list node".
Pictorially, this is like the following, where I've put the "data" in parens and show "next" pointing to something.
head -> ListNode("foo")next -> ListNode("bar")next -> ListNode("baz")next -> null
The end of the list is found when next holds the null value. You would have to also have a ListNode tail; which would be updated to point to the last thing added to the list.
Here's an extremely simple (and untested) example of the concepts. Java's own java.util.LinkedList is much more complicated, and is parameterized with generics.
class List
{
ListNode head = null;
ListNode tail = null;
public add(Object o)
{
ListNode node = new ListNode(o);
if (head == null) head = node; // if there's no head yet this is the head
if (tail != null) tail.next = node; // if there's a tail point tail at this new node
tail = node; // and this is the new tail
}
// need remove() etc other methods
}
I'm fairly new to JAVA and OOP and I'm currently following an academic course where I'm learning data structures and algorithms in java.
As I was learning about implementation of linked lists I've ran into a small problem of not understanding the code how to create a node when implementing a linked list(I'm familiar with constructors and bit of recursion ).
Code of the Node class as follows
public class Node {
public int info;
public Node next, prev;
public Node (int el) {
this (el,null,null);
}
public Node (int el,Node n,Node p){
info = el; next =n; prev=p;
}
}
I need to know what's happening behind the scene when the code executes(especially how the line3 works)and code of the List class is as follows
public class List {
private Node head, tail;
public List ( ){
head = tail = null;
}
public boolean isEmpty( ){
return head == null;
}
public void addToTail (int el) {
if (!isEmpty ( )) {
tail = new Node (el, null, tail);
tail.prev.next = tail;
}
else head = tail = new Node(el);
}
public int removeFromTail ( ){
int el = tail.info;
if (head == tail)
head = tail =null;
else
{
tail = tail.prev; tail.next = null;
}
return el;
}
}
(This example is given by the academy where I'm learning and I want to know how it works)
Please explain how the Node class works.
Ok let's start from the Node Class
public Node next, prev;
public Node (int el) {
this (el,null,null);
}
Here the objects next and prev are references to the next and previous nodes to the current node (which is your current object (this))
this (el,null,null);
It means you are creating a node which has no previous or next node. as you pass null, null for next and previous. Its similar to creating a head as head doesn't have next and previous nodes.
When you create the head you will never change it but you will change the next of the head the time when you create the second element in your list
When you create a tail of the linked list
public void addToTail (int el) {
if (!isEmpty ( )) {
tail = new Node (el, null, tail);
tail.prev.next = tail;
}
else head = tail = new Node(el);
}
here you first create a tail Node by tail = new Node (el, null, tail);
And then get the previous of tail and set the next element of the prev as the tail by doing tail.prev.next = tail;
Every time you add a new Node to the list you are calling addToTail(int e1) which updates the tail and updates the next of the old tail.
Let's suppose the entry point of your code is a call to:
List list = new List();
list.addToTail(1);
list.addToTail(2);
list.removeFromTail();
The first line of code execute the constructor into the list class, which simply set head and tail equal to null.
The second line of code add the method addToTail, and set the variable head and tail equal to new Node(1), which invoke the constructor having one parameter only in the Node class.
The third line of code add the method addToTail, but this time the list is not empty, so the script enters in the if statement and the node that you save with Node(2, null, tail). If you check this Node constructor with three parameters, tail (the node you added before which value was 1) will be set as the prev (previous) node associated with the current one.
The last line of code remove the 2nd node with the code tail = tail.prev; tail.next = null; and return the element you just removed.
firstly node in java its a specific type of variable, which can do the normal work of a variable and have an other information allow her to point on an other node in your case is public Node next, prev;
usually node are used in list ,think like train this is why you have addtootail here or removefromtail .
in this link you find a pretty quite explanation about that.
http://www.vias.org/javacourse/chap14_02.html
The Node class encapsulates the data, in this case an integer value named info.
Also, the List is implemented as a sequence of Nodes.
The reason for the next and prev values in Node is so that the node can be linked to its previous and next nodes in the list sequence. The only way to access a node in the list is to traverse the list, either forwards using the next reference, or backwards using the prev reference.
Note that lists do not support random access like an array would. To get to an element, you need to traverse the list in some direction.
I need to know what's happening behind the scene when the code executes(especially how the line3 works).
Please explain how the Node class works.
public Node next, prev;
Java variables that refer to object types are references, not values. The fields next and prev are not Node objects. No Node object contains other Nodes. Instead, next and prev reference Node objects stored separately.
If you're coming from C or C++, you can think of these references somewhat like pointers.
EDIT:
If you're instead asking about the construction of linked lists in general, your Node class represents a single node, containing a single item, in a doubly linked list. In a doubly linked list, each node refers to the node before and the node after.
See this illustration of a doubly linked list in this related wikipedia article.
The List is like a train. A Node is like a car in the train. The links are references between Nodes, which are similar to the coupling between train cars. The next and prev fields that you ask about are the links between nodes.
Logically, the List contains the entire train. Physically, your List references the head and tail of the train, so that it can travel over the Nodes from front-to-back, or back-to-front.
I've got to write a very short bit of code on a deque, however I'm not sure how to write the code for the methods, if someone could help me with one of the methods, (eg. a method to add an object to the from of the deque) then that would get me started. I'm sure I could manage the rest of the methods, just at the moment I'm pretty stumped.
Deques are usually implemented as doubly linked lists. You implement a doubly linked list by keeping track of the first and last element in the list and letting each element keep track of its predecessor and successor.
public class Deque<T> {
private class Node {
Node(T value) {
this.value = value;
}
T value;
Node next, prev;
}
private Node first, last;
public void addFront(T value) {
Node oldFirst = first;
first = new Node(value);
// The old first item is now the second item, so its the successor of
// the new first item
first.next = oldFirst;
// if first was null before, that means the deque was empty
// so first and last should both point to the new item
if(oldFirst == null) {
last = first;
} else {
// If there previously was a first element, this element is
// now the second element and its prev field should point to
// the new first item
oldFirst.prev = first;
}
}
}
I'm not sure exactly what you're after, but the available methods for the Deque are listed in the Javadoc