Data Structure Lecture 5

Preview:

DESCRIPTION

Link list.

Citation preview

Linked Lists

If the size of the data is not known before hand

◦It means, at compile time or at the time of object creation

Then

◦Move towards dynamic implementation, the size can be increased or decreased at the run-time even as per need.

The linked list is a very flexible dynamic dynamic data structuredata structure: items may be added to it or deleted from it at will.

A programmer need not worry about how many items a program will have to accommodate.

This allows us to write robust programs which require much less maintenance.

A very common source of problems in program maintenance is the need to increase the capacity of a program to handle larger collections:

In a linked list, each item is allocated space as it is added to the list.

A link is kept with each item to the next item in the list.

Each node of the list has two elements

1. the item being stored in the list and

2. a pointer to the next item in the list

The last node in the list contains a NULL pointer to indicate that it is the end or tail of the list.

As items are added to a list, memory for a node is dynamically allocated.

Thus the number of items that may be added to a list is limited only by the amount of memory available.

Handle for the list The variable (or handle) which represents the

list is simply a pointer to the node at the head of the list.

This basic singly-linked list is inefficient in those cases This basic singly-linked list is inefficient in those cases when we wish to add elements to both ends of the list.when we wish to add elements to both ends of the list.

It is easy to add elements at the head of the list, It is easy to add elements at the head of the list, To add elements at the other end (the To add elements at the other end (the tailtail ) we need to  ) we need to

locate the last element.locate the last element. If the basic singly-linked list is used, the entire list needs to If the basic singly-linked list is used, the entire list needs to

be traversed in order to find its tail.be traversed in order to find its tail.

Following figure shows a way in which to make adding elements to the tail of a list more efficient.

The solution uses a second variable, The solution uses a second variable, tail tail , , which refers to the last element of the list. which refers to the last element of the list.

However, this time efficiency comes at the However, this time efficiency comes at the cost of the additional space used to store the cost of the additional space used to store the variable tail. variable tail.

The common operations on linked lists are:1. AddToHead(x) Inserts element x in front of the linked

list .2. AddToTail(x) Inserts element x at the end of the

linked list.3. DeleteFromHead() Deletes the first element of the

linked list.4. DeleteFromTail() Deletes the last element of the

linked list. 5. Delete(x) Deletes the node of value x from the linked

list.6. Find(x) Find the entry x in the linked list.7. print() prints the contents of the linked list.8. And so on i.e.as many operations as you

required

Two cases must be considered to add the node in front of the linked list.

1. Either we are creating the first node of the linked list or

1. We are inserting the node in front of the existing linked list.

First Case: Creating first node of a linked list.

We follow the following steps to create the first node of the linked list.

1. Check the value of the head of the list.If this value is null it means we are creating the first node of the linked list.

2. An empty node is created.

It is empty in the sense that the program performing insertion does not assign any values to the data members of the node.

3. The node's info member is initialized to a particular value.

7

4. Since it is the only node of the linked list therefore its next member will be initialized to null.

7 /

5. Since it is the only node of the linked list therefore both head and tail points to this node of the linked list.

7 /

head tail

Second Case: Inserting node in front of the existing linked list:

We follow the following steps to insert the node in front of the existing linked list.

1. Check the value of the head of the list.

If this value is not null it means we are inserting node in front of the existing linked list.

7 /

head tail

2. An empty node is created.

It is empty in the sense that the program performing insertion does not assign any values to the data members of the node.

7 /

head tail

3. The node's info member is initialized to a particular value.

7 /

head tail 8

4. Because the node is being included at the front of the list, the next member becomes a pointer to the first node on the list, i.e. the current value of head.

7 /

head tail 8

5. The new node precedes all the nodes on the list, but this fact has to be reflected in the value of head; otherwise the new node is not accessible. Therefore head is updated to become the pointer to the new node

7 /

tailhead 8

Two cases must be considered to add the node at the end of a linked list.

1. Either we are creating the first node of the linked list or

1. We are inserting the node at the end of an existing linked list.

The first case is exactly similar as we discussed in AddToHead(x) function.

Second Case: Inserting node at the end of an existing linked list.

We follow the following steps to insert the node at the end of an existing linked list.

1. Check the value of the head of the list.

If this value is not null it means linked list already exists and we insert the node at the end of an existing linked list.

7 /

tailhead 8

2. An empty node is created.

It is empty in the sense that the program performing insertion does not assign any values to the data members of the node.

7 /

tailhead 8

3. The node's info member is initialized to a particular value.

7 /

tailhead 8

4. Because the node is being included at the end of the list, the next member is set to null.

9 \

5. The node is now included in the list by making the next member of the last node of the list a pointer to the newly created node.

9 \ 7

tailhead 8

9

6. The new node follows all the nodes of the list, but this fact has to be reflected in the value of tail, which now becomes the pointer to the new node.

9 \ 7

head tail 8

Two cases must be considered to delete the node from the head of a linked list.

1. Either a linked list has only one node or

1. A linked list has more than one nodes.

First Case: Linked List has only one node:

We follow the following steps to handle this case:

1. Check the values of the pointer variables head and tail.

If both points to the same node, means linked list has only one node.

7 /

head tail2.2. Set both Set both headhead and and tail tail pointers to pointers to nullnull and return and return

back the memory occupied by the node to the back the memory occupied by the node to the system.system.

Second Case: Linked List has more than one nodes

We follow the following steps to handle this case:

1. Check the values of the pointer variables head and tail.

If both points to the different nodes, means linked list has more than one nodes.

9 \ 7

head tail 8

2. Set a temporary pointer variable tmp points to the head of a linked list.

9 \ 7

head tail 8

tmp

3.3. Since we delete a node from the head of a linked Since we delete a node from the head of a linked list, therefore move the list, therefore move the head head pointer to the node pointer to the node next to the head of an existing list.next to the head of an existing list.

9 \ 7

head tail 8

tmp

4. Delete a node pointed by the pointer variable tmp from a linked list.

9 \ 7

head tail 8

tmp

9 \ 7

head tail

Two cases must be considered to delete the node from the end of a linked list.

1. Either a linked list has only one node or

1. A linked list has more than one nodes. The first case is exactly similar as we

discussed in DeleteFromHead() function.

Second Case: Linked List has more than one nodes:

We follow the following steps to handle this case:

1. Check the values of the pointer variables head and tail.

If both points to the different nodes, means linked list has more than one nodes.

9 \ 7

head tail 8 4 5

2. After removing a node, tail should refer to the new tail of the list. i.e. tail has to be moved backward by one node. 9 \ 7

head tail 8 4 5

9 \ 7

head tail

8 4 5

But moving backward is impossible because But moving backward is impossible because there is no direct link from the last node to its there is no direct link from the last node to its predecessor.predecessor.

3. Hence, this predecessor has to be found by searching from the beginning of the list and stopping right before tail.

This is accomplished with a temporary variable tmp used to scan a list within the loop.

4. The variable tmp is initialized to the head of the list.

9 \ 7

head tail 8 4 5

tmp

5. In each iteration of the loop, the variable tmp is advanced to the next node of the linked list.

9 \ 7

head tail 8 4 5

tmp

After executing the assignment After executing the assignment tmp= tmp->next, tmp= tmp->next, tmp tmp refers to the second node.refers to the second node.

9 \ 7

head tail 8 4 5

tmp

After the second iteration and executing the same assignment, tmp refers to the third node. 9 \ 7

head tail 8 4 5

tmp tmptmp

After the third iteration and executing the same After the third iteration and executing the same assignment, assignment, tmp tmp refers to the forth node.refers to the forth node.

tmptmp

Because next to this node is a last node, i.e. this Because next to this node is a last node, i.e. this node is a predecessor of the last node, therefore node is a predecessor of the last node, therefore the loop is exited.the loop is exited.

6. Now delete the last node from the linked list.

9 \ 7

head tail 8 4 5

tmp7.7. Because Because tail tail is now pointing to non existing is now pointing to non existing

node therefore it is immediately set to point to node therefore it is immediately set to point to the node pointed by the node pointed by tmp.tmp.

7

head tail 8 4 / 5

tmp8.8. To mark the fact that To mark the fact that tailtail is now pointing to last is now pointing to last

node of the linked list, the next member of this node of the linked list, the next member of this node is set to node is set to nullnull..

Two cases must be considered to delete the node of value x from the linked list.

1. Either a linked list has only one node or

1. A linked list has more than one nodes. The first case is exactly similar as we

discussed in DeleteFromHead() function except

We first checks that the value of this single node matches with the value of variable x.

Second Case: Linked List has more than one nodes:

We follow the following steps to handle this case:1. First matches the value of variable x with the value

of first node of the linked list.

If the value matches, it means we want to delete first node of a linked list, therefore call the operation DeleteFromHead().

2. Otherwise, match the value of variable x with the value of last node of the linked list.If the value matches, it means we want to delete last node of a linked list, therefore call the operation DeleteFromTail().

3. If first two cases fails then locate the node whose value matches with the value of variable x.Such a node has to be found by searching from the beginning of the list and stopping at the node whose value matches with the value of variable x.This is accomplished with a temporary variable tmp used to scan a list within the loop.The variable tmp is initialized to the head of the linked list. 9 \ 7

head tail 8 4 5

tmp

In each iteration of the loop, the value of the node pointed by variable tmp will be compared with the value of variable x.If the value matches then we exited from loopOtherwise we advance the variable tmp to compare the value of the next node of linked list.Consider the following linked list. 9 \ 7

head tail 8 4 5

tmp

Suppose the value of the variable Suppose the value of the variable x x is is 4.4.

When we exited from the loop the variable tmp is pointing to the node containing 4. 9 \ 7

head tail 8 4 5

tmpWe can now remove a node pointed by variable We can now remove a node pointed by variable tmptmp by linking its predecessor to its successor. by linking its predecessor to its successor.

But because the list has only forward links the But because the list has only forward links the predecessor of a node is not reachable from the predecessor of a node is not reachable from the node.node.

To locate the predecessor we again scan the list To locate the predecessor we again scan the list from the beginning. from the beginning.

4. This is accomplished with a temporary variable pred used to scan a list within the loop.The variable pred is initialized to the head of the linked list.

9 \ 7

head tail 8 4 5

tmppred

After executing the assignment After executing the assignment pred=pred->next, pred=pred->next, pred pred refers to the second node.refers to the second node.

predpred predpred

After the second iteration and executing the same After the second iteration and executing the same assignment, assignment, pred pred refers to the third node.refers to the third node.

Because next to this node is a node pointed by the variable tmp, i.e. this node is a predecessor of the node pointed by variable tmp, therefore the loop is exited. 9 \ 7

head tail 8 4 5

tmppred

5.5. Now join the node pointed by variable Now join the node pointed by variable predpred to to the node next to the node pointed by the variable the node next to the node pointed by the variable tmp.tmp.

6. Now delete the node pointed by the variable tmp from linked list.

9 \ 7

head tail 8 4 5

tmppred

9 \ 7

head tail 8 5

pred

Every node of a linked list has two fields, an information field and a field which points to the next node of a list.

Therefore the class which for the node of a list has two data members I.e.

◦ A data member to hold information &

◦ A data member which stores the address of next node of a list

template<class T>class Node {public:

T info;Node *next;Node() {

next = 0;}Node(T el, Node *n = 0) {

info = el;next = n;

}};

Node *p = new Node(10);Node *p = new Node(10);

10

p

Node *q = new Node(8);

8

q

p->next = q;r = new Node(12);

12 /

r

q->next = r;As we see this is an inconvenient and cumbersome process.

Therefore

To implement the singly linked list we implement two classes i.e.

◦ One class for nodes of the list &

◦ Another class for access to the list

template<class T>class Node {public:

T info;Node *next;Node() {

next = 0;}Node(T el, Node *n = 0) {

info = el;next = n;

}};

template<class T>class SinglyLinkedList {

private:Node<T> *head; //pointer to first node of a //pointer to first node of a

listlistNode<T> *tail; //pointer to last node of a //pointer to last node of a

listlistpublic:

SinglyLinkedList() {head = tail = 0;

}~SinglyLinkedList();

Continue on next slide…

bool isEmpty() {if (head == 0) //list is empty//list is empty

return true;}void addToHead(T el); //inserts an element in front of list//inserts an element in front of listvoid addToTail(T el); //inserts an element at the end of list//inserts an element at the end of listvoid deleteFromHead(); //delete a node from the front //delete a node from the front

of a list anof a list anvoid deleteFromTail(); //delete a node form the end of a list //delete a node form the end of a list void Delete(T el); //delete a node form list whose //delete a node form list whose

value is elvalue is elNode *Find(T el); //Find the node from list whose //Find the node from list whose

value is el value is el //and returns its pointer.//and returns its pointer.void prints(); //prints the contents of a list//prints the contents of a list};

template<class T> void SinglyLinkedList<T> :: addToHead(T el)

{ Node *n = new Node<T>(e1, 0); //Creates new //Creates new nodenode

tail

head

if (isEmpty)if (isEmpty) //first node of a list//first node of a list

head = tail = n;head = tail = n;

elseelse // Insert node in front of the list// Insert node in front of the list{{

n

e ahead

b c d

tail

n

e

n->next = headn->next = head;head = n;head = n;

head

}

}

template<class T>void SinglyLinkedList<T>::addToTail(T el)

{ Node *n = new Node<T>(e1, 0); //Creates new node//Creates new node

n

e

tail

headif(isEmpty)if(isEmpty) //First node of a list//First node of a list

head = tail = n;head = tail = n;

elseelse //Insert node at the end of a list//Insert node at the end of a list

{{

n

eahead

b c d

tail

tail->next = n;tail->next = n;tail = n;tail = n;

tail

}

}

template<class T>void SinglyLinkedList<T>:: deleteFromHead()

{if(head != 0) //Non empty list//Non empty listNode *n = head;Node *n = head;

If(head == tail)If(head == tail) //if only one node in the list//if only one node in the list

n

d

tail

head

elseelse

ahead

b c d

tailn

head = head->next;head = head->next;

head delete n;delete n;

}

head = tail = 0;head = tail = 0;

template<class T>void SinglyLinkedList<T>:: deleteFromTail()

{ if(head != 0) //Non empty list//Non empty list if(head == tail) //Only one node in a list//Only one node in a list {

ahead

b c d

tailn

elseelse{{ Node *n = head;Node *n = head;

while(n->next != tail) n = n->next;while(n->next != tail) n = n->next;

n

tail = n;tail = n;

delete tail;delete tail;

tail->next = 0;

}

}

d

tail

headdelete head; head = tail = 0head = tail = 0}}

tail

template<class T>void SinglyLinkedList<T>:: Delete(T el)

{if(head != 0) //Non empty list//Non empty listif(el == head -> info)//we want to delete header //we want to delete header

node node deleteFromHead();

Continue on next slide…..

else if(el == tail->info) //we want to delete last node //we want to delete last node deleteFromTail();

else { //node we want to delete is not the header node and not the tail //node we want to delete is not the header node and not the tail //node//node

Node *tmp = head;while(tmp != 0 && tmp ->info != el)//Locate the node we want to delete//Locate the node we want to delete

tmp = tmp -> next;

a

head

b c d

tail

If(tmp != 0) { //Node of value el exists//Node of value el exists

pred->next = tmp->next;

pred

delete tmp; } }

tmp

Node *pred = head;while(pred ->next != tmp)//Locate the predecessor of node //Locate the predecessor of node

//pointed by tmp//pointed by tmppred=pred->next;pred=pred->next;

template<class T>void SinglyLinkedList<T> ::

~SinglyLinkedList(){

if(!isEmpty()) //List is not empty//List is not emptywhile(head != 0)

deleteFromHead();}

We can implement the stack dynamically using the linked list.Declaration of type Dynamic Stack is:

template<class T>class DynamicStack {

private:Node<T> *top //pointer to top node of //pointer to top node of

stackstackpublic:

DynamicStack() {top = 0;

}~DynamicStack();

s -> top

Empty Stack

DynamicStack *s = new DynamicStack();

Continue on next slide…..

void push(T e1); //push element in stack//push element in stackT pop(); //Pop element from stack//Pop element from stackbool isEmpty() //Check stack is empty or not//Check stack is empty or not{

if (top == 0)return true

elsereturn false

}T TopValue(); //Retruns top element of stack//Retruns top element of stack};

s -> top

Empty Stacknp

NewNodeNew

Node

s -> top

npNewNode

s -> tops -> top

npNewNode

NewNode

s -> top

NewNode

NewNode

NewNode

Continuing this way we get the following link list.

When we pop the stack then the node to which top points will be popped and top moves to the previous node.

But how top moves to previous node? A node has no pointer to a previous node,

it only points to the next node We can achieve this by placing the pointer

of previous node in a node, instead of placing the pointer of next node in a node.

s -> top

template<class T>class Node {public:

T info;Node *previous;Node() {

previous = 0;}Node(T el, Node *n = 0) {

info = el; previous = n;

}};

void template<class T> DynamicStack :: Push(T el)

{

top

Node *np = new Node<T>(e1);

np

np->previous = top; top = np;}

top

T template<class T> DynamicStack ::pop()

{

np

Node *np = top;

top

top = np -> previous; return np -> info;}

top

Reversing the stringvoid ReverseRead (void){ DynamicStack * stack = new DynamicStack(); //The stack //The stack stack stack is created is created

//and can hold elements of //and can hold elements of //type char //type charchar item;cin>>item;while (item ! = “\n”){ stack->Push (item); // push each character onto the stack // push each character onto the stack

cin>>item;}while(! stack->is_Empty() ){ item = stack->Pop (); //Pop an element from stack//Pop an element from stack

cout<<item;}

}

Recommended