You are on page 1of 28

UNIT-1:LINKED LISTS

Introduction to Data Structures:


Data structure is a representation of logical relationship existing between
individual elements of data. In other words, a data structure defines a way of organizing
all data items that considers not only the elements stored but also their relationship to
each other. The term data structure is used to describe the way data is stored.
To develop a program of an algorithm we should select an appropriate data structure for
that algorithm. Therefore, data structure is represented as:
Algorithm + Data structure = Program
A data structure is said to be linear if its elements form a sequence or a linear list.
The linear data structures like an array, stacks, queues and linked lists organize data in
linear order. A data structure is said to be non linear if its elements form a hierarchical
classification where, data items appear at various levels.

Trees and Graphs are widely used non-linear data structures. Tree and graph
structures represents hierarchial relationship between individual data elements. Graphs
are nothing but trees with certain restrictions removed.
Data structures are divided into two types:

• . Primitive data structures.


• Non-primitive data structures

Primitive Data Structures are the basic data structures that directly operate upon the
machine instructions. They have different representations on different computers.
Integers, floating point numbers, character constants, string constants and pointers
come under this category.

Non-primitive data structures are more complicated data structures and are derived
from primitive data structures. They emphan on grouping same or different data items
with relationship between each data item. Arrays, lists and files come under this
category.
ALGORITHM:
An algorithm is a finite sequence of instructions, each of which has a clear
meaning and can be performed with a finite amount of effort in a finite length of time.
No matter what the input values may be, an algorithm terminates after executing a finite
number of instructions. In addition every algorithm must satisfy the following criteria:

Input: there are zero or more quantities, which are externally supplied;
Output: at least one quantity is produced;
Definiteness: each instruction must be clear and unambiguous;
Finiteness: if we trace out the instructions of an algorithm, then for all cases the
algorithm will terminate after a finite number of steps;
Effectiveness: every instruction must be sufficiently basic that it can in principle be
carried out by a person using only pencil and paper. It is not enough that each operation
be definite, but it must also be feasible.

In formal computer science, one distinguishes between an algorithm, and a


program. A program does not necessarily satisfy the fourth condition. One important
example of such a program for a computer is its operating system, which never
terminates (except for system crashes) but continues in a wait loop until more jobs are
entered.
We represent an algorithm using pseudo language that is a combination of the
constructs of a programming language together with informal English statements.

LINEAR AND NON-LINEAR DATA STRUCTURES:


Linear Data Structure Vs Non-Linear Data Structure:

S.NO Linear Data Structure Non-linear Data Structure

In a linear data structure, data elements


are arranged in a linear order where each In a non-linear data structure,
and every elements are attached to its data elements are attached in
1. previous and next adjacent. hierarchically manner.

Whereas in non-linear data


In linear data structure, single level is structure, multiple levels are
2. involved. involved.

While its implementation is


Its implementation is easy in comparison complex in comparison to
3. to non-linear data structure. linear data structure.

While in non-linear data


structure, data elements can’t
In linear data structure, data elements be traversed in a single run
4. can be traversed in a single run only. only.

While in a non-linear data


structure, memory is utilized
In a linear data structure, memory is not in an efficient way.
5. utilized in an efficient way.

Its examples are: array, stack, queue, While its examples are: trees
6. linked list, etc. and graphs.

Applications of non-linear
Applications of linear data structures are data structures are in Artificial
mainly in application software Intelligence and image
7. development. processing.
LINKED LISTS:

L inked lists and arrays are similar since they both store collections of data. Array
is the most common data structure used to store collections of elements. Arrays
are convenient to declare and provide the easy syntax to access any element by
its pos Number.

Once the array is set up, access to any element is convenient and fast. The disadvantages
of arrays are:

1.The n of the array is fixed. Most often this n is specified at compile time. This makes
the programmers to allocate arrays, which seems "large enough" than required.

2. Inserting new elements at the front is potentially expensive because existing


elements need to be shifted over to make room.

3.Deleting an element from an array is not possible.

Linked lists have their own strengths and weaknesses, but they happen to be strong
where arrays are weak. Generally array's allocates the memory for all its elements in
one block whereas linked lists use an entirely different strategy. Linked lists allocate
memory for each element separately and only when necessary.

Advantages of linked lists:

Linked lists have many advantages. Some of the very important advantages are:
1. Linked lists are dynamic data structures. i.e., they can grow or shrink during the
execution of a program.
2. Linked lists have efficient memory utilization. Here, memory is not pre-
allocated. Memory is allocated whenever it is required and it is de-allocated
(removed) when it is no longer needed.
3. Insertion and Deletions are easier and efficient. Linked lists provide flexibility in
inserting a data item at a specified pos and deletion of the data item from the given
pos.
4. Many complex applications can be easily carried out with linked lists.

Disadvantages of linked lists:

1. It consumes more space because every node requires a additional pointer to


store address of the next node.
2. Searching a particular element in list is difficult and also time consuming.
3.2. Types of Linked Lists:
Basically we can put linked lists into the following four items:
1. Single Linked List.
2. Double Linked List.
3. Circular Linked List.
4. Circular Double Linked List.

1. Single Linked List:


A single linked list is one in which all nodes are linked together in some
sequential manner. Hence, it is also called as linear linked list.

The basic operations in a single linked list are:


• Creation.
• Insertion.
• Deletion.
• Traversing
CREATION:
Creating a node for Single Linked List:
public class Node {
int data;
int n=0;
Node head=null;
Node next;
Node(int data)
{
this.data=data;
this.next=null;
}
}

INSERTION:
One of the most primitive operations that can be done in a singly linked list is the
insertion of a node. Memory is to be allocated for the new node (in a similar way that is
done while creating a list) before reading the data. The new node will contain empty
data field and empty next field. The data field of the new node is then stored with the
information read from the user. The next field of the new node is assigned to NULL.
The new node can then be inserted at three different places namely:
• Inserting a node at the beginning.
• Inserting a node at the end.
• Inserting a node at intermediate pos.

1. Inserting a node at the beginning:


void insertatbegin(int data)
{
Node newnode=new Node(data);
n++;
newnode.next=head;
head=newnode;
}

2.Inserting a node at the end:


void insert(int data)
{
Node newnode=new Node(data);
n++;
if(head==null)
{
head=newnode;
}
else
{
Node t=head;
while(t.next!=null)
{
t=t.next;
}
t.next=newnode;
}
}
3.Inserting a node at intermediate pos:
void insertat(int pos,int data)
{
Node newnode=new Node(data);
Node t=head;
int c=1;
if(pos==1)
{
insertatbegin(data);
}
else if(pos>n)
{
insert(data);
}
else
{
while(c<pos-1)
{
t=t.next;
c++;
}
newnode.next=t.next;
t.next=newnode;
n++;
}
}
DELETION:
Another primitive operation that can be done in a singly linked list is the deletion of a
node. Memory is to be released for the node to be deleted. A node can be deleted from
the list from three different places namely.
• Deleting a node at the beginning.
• Deleting a node at the end.
• Deleting a node at intermediate pos.

1.Deleting a node at the beginning:


void delfrombeg()
{
if(head==null)
{
System.out.println("no dtata within a linked list");
}
else
{
head=head.next;
n--;
}
}

2.Deleting a node at the end:

void delfromend()
{
if(n<1)
{
System.out.println("no dtata within a linked list");
}
else if(n==1)
{
head=null;
n--;
}
else
{
Node t=head;
while(t.next.next!=null)
{
t=t.next;
}
t.next=null;
n--;
}
}
3.Deleting a node at intermediate pos:
void delfromspecifiedpos(int pos)
{
if(pos>n)
{
System.out.println("invalid pos");
}
else
{
int c=1;
Node t=head;
if(pos==n)
{
delfromend();
}
else if(pos==1)
{
delfrombeg();
}
else
{
while(c<pos-1)
{
t=t.next;
c++;
}
t.next=t.next.next;
n--;
}
}
}
TRAVERSING:
void disp()
{
Node t = new Node();
t = this.head;
if(t != null)
{
System.out.print("The list contains: ");
while(t != null) {
System.out.print(t.data + " ");
t = t.next;
}
System.out.println();
}
else
{
System.out.println("The list is empty.");
}
}

Source Code for the Implementation of Single Linked List:


public class Node {
int data;
Node next;
Node(int data)
{
this.data=data;
this.next=null;
}
}

public class Sllsample{


Node head=null;
int n=0;
void insertatbegin(int data)
{
Node newnode=new Node(data);
n++;
newnode.next=head;
head=newnode;
}
void insert(int data)
{
Node newnode=new Node(data);
n++;
if(head==null)
{
head=newnode;
}
else
{
Node t=head;
while(t.next!=null)
{
t=t.next;
}
t.next=newnode;
}
}
void insertat(int data)
{
Node newnode=new Node(data);
Node t=head;
int c=1;
if(pos==1)
{
insertatbegin(data);
}
else if(pos>n)
{
insert(data);
}
else
{
while(c<pos-1)
{
t=t.next;
c++;
}
newnode.next=t.next;
t.next=newnode;
n++;
}
}
}
void delfrombeg()
{
if(head==null)
{
System.out.println("no data within a linked list");
}
else
{
head=head.next;
n--;
}
}
void delfromend()
{
if(n<1)
{
System.out.println("no data within a linked list");
}
else if(n==1)
{
head=null;
n--;
}
else
{
Node t=head;
while(t.next.next!=null)
{
t=t.next;
}
t.next=null;
n--;
}
}

void delfromspecifiedpos(int pos)


{
if(pos>n)
{
System.out.println("invalid pos");
}
else
{
int c=1;
Node t=head;
if(pos==n)
{
delfromend();
}
else if(pos==1)
{
delfrombeg();
}
else
{
while(c<pos-1)
{
t=t.next;
c++;
}
t.next=t.next.next;
n--;
}
}
}

void disp()
{
Node t=head;
System.out.println("-------------------------------");
while(t!=null)
{
System.out.println(t.data);
t=t.next;
}
}

void dispcount()
{
System.out.println("number of nodes: "+n);
}
public static void main(String[] args) {
// TODO Auto-generated method Nodeb
Scanner s=new Scanner(System.in);
int data;
Sllsample l=new Sllsample();
System.out.println("Enter number of : ");
int x=s.nextInt();
for(int i=0;i<x;i++)
{
data=s.nextInt();
l.insert(data);
}
sl:
for(;;)
{
System.out.println("1. Insert at BEGIN \n 2. Insert at END \n 3. insert at Specified Pos
\n 4. Delete at BEGIN \n 5.Delete at END \n 6.Delete at Specified Pos \n 7. Display data \n 8. Display
no.of nodes \n 9. exit ");
int ch=s.nextInt();
switch(ch)
{
case 1:
System.out.println("Enter data: ");
data=s.nextInt();
l.insertatbegin(data);
break;
case 2:
System.out.println("Enter data: ");
data=s.nextInt();
l.insert(data);
break;
case 3:
System.out.println("Enter data: ");
data=s.nextInt();
System.out.println("Enter new node pos");
int pos=s.nextInt();
l.insertat(data, pos);
break;
case 4:
l.delfrombeg();
break;
case 5:
l.delfromend();
break;
case 6:
int y=s.nextInt();
l.delfromspecifiedpos(y);
break;
case 7:
l.disp();
break;
case 8:
l.dispcount();
break;
case 9:
break sl;
}
}
}

2. Double Linked List:


A double linked list is a two-way list in which all nodes will have two links. This
helps in accessing both successor node and predecessor node from the given node pos.
It provides bi-directional traversing. Each node contains three fields:
• Left link.
• Data.
• Right link.
The left link points to the predecessor node and the right link points to the successor
node. The data field stores the required data.
Many applications require searching forward and backward thru nodes of a list. For
example searching for a name in a telephone directory would need forward and
backward scanning thru a region of the whole list.
Advantages over singly linked list :
1. A DLL can be traversed in both forward and backward direction.
2. The delete operation in DLL is more efficient if pointer to the node to be deleted
is given.
3. We can quickly insert a new node before a given node.

Disadvantages over singly linked list:


1. Every node of DLL Require extra space for an previous pointer.
2. All operations require an extra pointer previous to be maintained.

The basic operations in a double linked list are:


• Creation.
• Insertion.
• Deletion.

CREATION:
Creating a node for Double Linked list:
public class Node {
int data;
int n;
Node head=null;
Node tail=null;
Node next;
Node(int data)
{
this.data=data;
this.prev=null;
this.next=null;
}
}
INSERTION:
The new node can then be inserted at three different places namely:
• Inserting a node at the beginning.
• Inserting a node at the end.
• Inserting a node at intermediate pos.

1.Inserting a node at the beginning:


public void insertatbeg(int data)
{
Node newnode = new Node(data);
newnode.next = head;
newnode.prev = null;
if (head != null)
head.prev = newnode;
head = newnode;
}
2.Inserting a node at the end:
void insert(int data)
{
Node newnode = new Node(data);
Node t = head;
newnode.next = null;
if (head == null)
{
newnode.prev = null;
head = newnode;
return;
}
while (t.next != null)
t= t.next;
t.next = newnode;
newnode.prev =t;
}
3.Inserting a node after a given node:
void insertatpos(int data, int pos)
{
if (pos>=1 && pos<=n)
{
Node newnode = new node(data);
Node t = head;
if (pos == 1) {
insertatbegin(data);
}
else if (pos == n)
{
insertatend(data);
}
else
{
int c=1;
while(c<pos-1)
{
t = t.next;
c++;
}
newnode.next = t;
t.prev.next = newnode;
newnode.prev = t.prev;
t.prev = newnode;
n++;
}
}
else
{
System.out.println("Index " + pos + " not valid for linked list of size " + n);
}
}

Deletion of a node:
Another primitive operation that can be done in a singly linked list is the deletion of a
node. Memory is to be released for the node to be deleted. A node can be deleted from
the list from three different places namely.
• Deleting a node at the beginning.
• Deleting a node at the end.
• Deleting a node at specified pos.

1. Deleting a node at the beginning:


void deletefrombegin()
{
if (head == null)
{
System.out.println("List is empty");
}
Node first = head;
if (head.next == null)
{
tail = null;
}
else
{
head.next.prev = null;
}
head = head.next;
n--;
}
2. Deleting a node at the end:
void deletefromend()
{
if (tail == null)
{
throw new RuntimeException("List is empty");
}
Node t = tail;
if (head.next == null)
{
head = null;
}
else
{
t.prev.next = null;
}
t = t.prev;
n--;
}

3. Deleting a node at specified pos:


void deleteatpos(int pos)
{
if (pos>=1 && pos <=n)
{
Node t = head;
if (pos == 1)
{
deletefrombegin();
}
else if (pos == n)
{
deletefromend();
}
else
{
int c=1;
while(c<pos-1)
{
t = t.next;
c++;
}
t.prev.next = t.next;
t.next.prev = t.prev;
n--;
}
}
else
{
System.out.println("Pos " + pos + " not valid for linked list of n " + n);
}
}

TRAVERSING:
1. To display from first to tail:
void displayHeadToTail()
{
Node t = head;
if(t!=null)
{
System.out.print("The doubly linked list is : ");
while (t != null)
{
System.out.println(+t.data);
t = t.next;
}
}
else
{
System.out.println(“The list is Empty”);
}
}

2. To display from tail to first:


void displayTailToHead()
{
Node t = tail;
if(t!=null)
{
System.out.print("The doubly linked list is : ");
while (t != null)
{
System.out.println(+t.data);
t = t.prev;
}
}
else
{
System.out.println(“The list is Empty”);
}
}
3. Circular Single Linked List:
It is just a single linked list in which the link field of the tail node points back to the
address of the first node. A circular linked list has no beginning and no end. It is
necessary to establish a special pointer called head pointer always pointing to the first
node of the list. Circular linked lists are frequently used instead of ordinary linked list
because many operations are much easier to implement. In circular linked list no null
pointers are used, hence all pointers contain valid address.
Advantages of a Circular Singly Linked List:

•The major advantage is that we can head from any node and still we can
traverse the entire list.
• We can maintain one pointer “tail” and get the first (head) node using the
next pointer of the tail node.
• We no longer need a NULL assignment unless the list itself is empty.
• It is very useful in CPU round robin scheduling.
Disadvantages of a Circular Singly Linked List

• The biggest disadvantage of this list is that if it is not programmed


correctly, you will end up in an infinite loop.
• Implementing a circular linked list is complex compared to singly linked
list.
• Reversing a circular linked list is complex, it is complex compared to
singly linked list.
The basic operations in a circular single linked list are:
• Creation.
• Insertion.
• Deletion.
• Traversing.
CREATION:
public class Node
{
int data;
int n=0;
Node head;
Node next;
Node(int data)
{
this.data = data;
}
}

INSERTION:
1. Insert the new node as the first node:
void insertatbegin(int data)
{
Node newnode = new Node(data);
if (head == null)
{
head = newnode;
tail = newnode;
newnode.next = head;
}
Else
{
Node t = head;
newnode.next = t;
head = newnode;
tail.next = head;
}
}
2. Insert at specified pos:
void insertatpos(int data, int pos)
{
Node t, newnode;
int i, count;
newnode = new Node();
Node t = head;
Int n=0;
if (t == null || n < pos)
System.out.println("Index is greater than n of the list");
else
{
newnode.data = data;
while(t.next!=null)
{
t = t.next;
}
newnode.next = t.next;
t.next = newnode;
}

3. Insert at the end:


void insertatend(int data)
{
Node newnode = new Node(data);
if (head == null)
{
head = newnode;
tail = newnode;
newnode.next = head;
}
else
{
tail.next = newnode;
tail = newnode;
tail.next = head;
}
}

DELETION:

1. Delete the First Node:


void deletefrombeg() {
if (head == null)
{
return;
}
else
{
if (head != tail) {
head = head.next;
tail.next = head;
}
else {
head = tail = null;
}
}
}
2. Delete at an index
void deleteat(int pos) {
Node nodeToDelete = head;
Node t = head;
int n = 0;
if(t != null) {
n++;
t=t.next;
}
while(t!=head) {
n++;
t=t.next;
}
if(pos<1||pos>n)
{
System.out.print("\nInvalid position.");
}
else if(pos==1)
{
if(head.next == head){
head = null;
}
else
{
while(t.next != head)
t=t.next;
head = head.next;
t.next = head;
nodeToDelete = null;
}
}
else
{
t=head;
while(t.next!=null)
t= t.next;
nodeToDelete = t.next;
t.next = t.next.next;
nodeToDelete = null;
}
}
3.Delete a node at the end:
void deleteatend() {
if (head == null)
return;
else
{
if (head != tail)
{
Node t = head;
while (t.next != tail)
{
t= t.next;
}
tail = t;
tail.next = head;
}
else{
head = tail = null;
}
}
}
TRAVERSING:
void disp()
{
Node t = head;
if (head != null) {
do
{
System.out.println(+ t.data);
t = t.next;
}while (t != head);
}
}

4.CIRCULAR DOUBLY LINKED LISTS:


A circular double linked list has both successor pointer and predecessor pointer
in circular manner. The objective behind considering circular double linked list is to
simplify the insertion and deletion operations performed on double linked list. In
Circular double linked list the right link of the right most node points back to the head
node and left link of the first node points to the tail node.

Advantages:
• List can be traversed from both directions i.e. from head to tail or from tail
to head.
• Jumping from head to tail or from tail to head is done in constant time
O(1).
• Circular Doubly Linked Lists are used for the implementation of advanced
data structures like Fibonacci Heap.
Disadvantages
• It takes slightly extra memory in each node to accommodate the previous
pointer.
• Lots of pointers involved while implementing or doing operations on a list.
So, pointers should be handled carefully otherwise data of the list may get
lost.

The basic operations in a circular single linked list are:


• Creation.
• Insertion.
• Deletion.
• Traversing.

CREATION:
class Node
{
int data;
Node next;
Node prev;
}
INSERTION:
1.Insertion at the end:
void insertatend(int value)
{
if (head == null)
{
Node newnode = new Node();
newnode.data = value;
newnode.next = newnode.prev = newnode;
head = newnode;
return;
}
Node tail = (head).prev;
Node newnode = new Node();
newnode.data = value;
newnode.next = head;
head.prev = newnode;
newnode.prev = tail;
tail.next = newnode;
}
2.Insertion at the beginning of the list:
void insertatbegin(int value)
{
Node tail = head.prev;
Node newnode = new Node();
newnode.data = value;
newnode.next = head;
newnode.prev = tail;
tail.next = head.prev = newnode;
head = newnode;
}
3.Insertion in between the nodes of the list:
void insertAt(int value1,int value2)
{
Node newnode = new Node();
newnode.data = value1;
Node t = head;
while (t.data != value2)
t = t.next;
Node next = t.next;
t.next = newnode;
newnode.prev = t;
newnode.next = next;
next.prev = newnode;
}

DELETION:

1. Delete the First Node:

void delfrombegin()
{
if(this.head != null)
{
if(this.head.next == this.head)
{
this.head = null;
}
else
{
Node t = this.head;
Node firstNode = this.head;
while(t.next != this.head)
{
t = t.next;
}
this.head = this.head.next;
this.head.prev = t;
t.next = this.head;
firstNode = null;
}
}
}

2.Delete the tail element:


void deletefromend()
{
if(this.head != null)
{
if(this.head.next == this.head)
this.head = null;
else
{
Node t = new Node();
t = this.head;
while(t.next.next != this.head)
t = t.next;
Node tailNode = t.next;
t.next = this.head;
this.head.prev = t;
tailNode = null;
}
}
}
3.Delete at an index

void deleteat(int pos)


{
Node nodeToDelete = head;
Node t = head;
int n= 0;
if(t != null)
{
n++;
t = t.next;
}
while(t != head)
{
n++;
t = t.next;
}
if(pos < 1 || pos > n)
{
System.out.print("\nInvalid pos.");
}
else if (pos == 1)
{
if(head.next == head)
{
head = null;
}
else
{
while(t.next != head)
t = t.next;
head = head.next;
t.next = head;
head.prev = t;
nodeToDelete = null;
}
}
else
{
t = head;
for(int i = 1; i < pos-1; i++)
t = t.next;
nodeToDelete = t.next;
t.next = t.next.next;
t.next.prev = t;
nodeToDelete = null;
}
}

TRAVERSING:
void PrintList()
{
Node t = new Node();
t = this.head;
if(t != null)
{
System.out.print("The list contains: ");
while(true)
{
System.out.print(t.data + " ");
t = t.next;
if(t == this.head)
break;
}
System.out.println();
}
else
{
System.out.println("The list is empty.");
}
}

You might also like