Você está na página 1de 63

DATA STRUCTURES

1. INTRODUCTION
It is important for every Computer Science student to understand the concept of Information and how it is

organized or how it can be utilized.


What is Information? 1.

Processed data If a set of data is processed by performing some operation(s), it will yield OR

information;
2.

If we arrange a set of data in an appropriate sequence, it forms a structure and gives us a meaning.

This meaning is called information.


What is Data Structure? 1.

It is a systematic way of organizing and accessing data. OR

It is a method of representing a logical relationship among individual data elements, related to the solution of a given problem.
2. 3.

A data structure Usually has more than one piece of data. Should define legal operations on the data. When we define a data structure, we are in fact creating a new data type of our own, using

predefined types or previously user defined types.


Why Data Structure? 1.

Data structures study how data are stored in a computer so that operations can be implemented Data structures are especially important when we have a large amount of data to be manipulated. Data structures define conceptual and concrete ways to organize data for efficient storage and

efficiently.
2.

3.

manipulation.
Abstract Data Type (ADT)

1.
2.

Abstract Data Type is a model used to understand the design of a data structure. Abstract implies that we give an implementation-independent view of the data structure. ADT specifies the type of data stored and the operations that support the data. Viewing a data structure as an ADT allows a programmer to focus on an idealized model of the data

3. 4.

and its operations.


1
M.Tech.

R.SIVA

E.g. Stack ADT- contains data variables such as top and operations that are performed on stack are push and pop.

2. CLASSIFICATION OF DATA STRUCTURES Data Structures can be classified as follows:


DATA STRUCTURE LINEAR DATA STRUCTURE NON-LINEAR DATA STRUCTURE

ARRAY

LINKED LIST

STACK

QUEU E

(HIERARCHIC AL) TREE

(NETWORK) GRAPH

1.

Linear data structure: A data structure is said to be linear, if its elements form a sequence or a

linear list. In this data structure, each element has exactly two neighboring elements (previous and next) to which it is connected. E.g. Arrays, Linked Lists, Stacks, Queues.
2.

Non-Linear data structure: A data structure is said to be non-linear, if its elements do not form a

linear list. In this data structure, one element can be connected to more than two neighboring elements. E.g. Trees, Graphs.

2
M.Tech.

R.SIVA

3. STACK (A Pile of Elements)


There are certain frequent situations in computer science when one wants to restrict insertions and deletions

so that they can take place only at the beginning or at the end of the list, not in the middle. Two of the Data Structures that are useful in such situations are Stacks and Queues.
A stack is a linear data structure in which elements are inserted and deleted at only one end called the top.

This means, in particular, the elements are removed from a stack in the reverse order of insertion.
Top is a pointer / index (subscript), which refers to the topmost element in the stack. Hence the operational semantic1/ strategy / principle followed by a stack is LIFO (Last In First Out) or

FILO (First In Last Out).

Semantic = meaning;

3
M.Tech.

R.SIVA

Special terminology is used for two basic operations associated with stack:

PUSH: insertion of an element at the top of the stack. POP: deletion (removal) of the element at the top of the stack.

Uses of top:

To perform all operations (push and pop) on the stack. To verify whether the stack is empty / full. To count the number of elements in the stack. To verify current stack position.

Examples: 1. Practical daily life: a pile of heavy books kept in a vertical box, dishes kept one on top of another. 2. In computer world: In processing of subroutine (function) calls and returns, there is an explicit use of

stack of return addresses. Also in evaluation of arithmetic expressions, stack is used.


Representation (Implementation) of a Stack

1. Static representation using arrays. 2. Dynamic representation using pointers (linked lists).

Static Representation of a Stack using Arrays


Stack can be represented using a one-dimensional array. Allocate a block of memory required to accommodate the full capacity of the stack, and the elements of a stack are stored in a sequential manner from the first location of the memory block. 4
M.Tech.

R.SIVA

Static representation of a Stack of size N using an array.

push

pop

top

N-1 ---2 1 0

66 44 22

top == -1 top == SIZE-1 top++ top--

Stack is empty (stack underflow); In this situation, it is impossible to pop an element from the stack. Stack is full (stack overflow); In this situation, it is impossible to push an element onto the stack. top value is incremented by 1 just before an element is pushed onto stack top value is decremented by 1 just after an element is popped from stack

PUSH operation Algorithm: push( ) // stack is an array of size N // initially top = -1


1. if (top == N-1)

// verify whether stack is full

a) Print stack is full and unable to push an element b) return.

2. else
a) Read the element (item) to be pushed b) top = top+1 c) stack[top] = item

4 3 2 1 0
5
M.Tech.

R.SIVA

4 3 4 3 2 1 0 2 2 1 0 5 2 4 3 2 1 0 6 5 2 4 3 2 1 0 7 6 5 2 4 3 2 1 0 77 7 6 5 2

4 3 2 1 0

77 7 6 5 2

top= -1

top=0

top=1

top=2

top=3

top=4

stack overflow

(a) Empty stack

(b) push 2

(c) push 5

(d) push 6

(e) push 7

(f) push 77

(g) push 11

POP operation Algorithm: pop( ) // stack is an array of size N


1. if (top == -1)

// verify whether stack is empty

a) Print stack is empty and unable to pop an element b) return.

2. else
a) item = stack[top] b) top = top-1 c) Print the popped element 4 77 3 7 2 6 1 5 0 2 6
M.Tech.

R.SIVA

4 3 4 3 7 2 6 1 5 0 2 2 6 1 5 0 2 4 3 2 1 5 0 2 4 3 2 1 0 2 4 3 2 1 0

4 3 2 1 0

top= 4

top=3

top=2

top=1

top=0

top= -1

stack underflow

(a) full stack

(b) pop 77

(c) pop 7

(d) pop 6

(e) pop 5

(f) pop 2

(g) pop 11

Advantages with static implementation

Simple method

Disadvantages with static implementation

Size is fixed as it is an array. Unable to expand or compress the amount of memory. Insufficient memory allocation technique.

Stack ADT:

PUSH( ) inserts an element onto a stack POP( ) removes an element from the stack IsEmpty( ) tests whether a stack is empty
7
M.Tech.

R.SIVA

IsFull( ) tests whether a stack is full

8
M.Tech.

R.SIVA

4. QUEUE
A queue is a linear data structure in which elements are inserted at one end, called rear and deleted at

another end, called front.


This means, in particular, the order in which elements enter in a queue is the order in which they leave.

Hence the operational semantic / strategy / principle followed by a queue is FIFO (First In First Out) or LILO (Last In Last Out).
Special terminology is used for two basic operations associated with queue:

ENQUEUE: insertion of an element at rear of the queue. DEQUEUE: deletion (removal) of the element at front of the queue.

The main difference between a queue and a stack is that elements in a queue are put at the bottom and taken

off from the top whereas in a stack, elements put at the top and taken off from the top.
Examples: 1. Practical daily life: The people waiting in a line at Railway Ticket Counter form a queue, where the first

person in a line is the first person to be left.


2. In computer world: In timesharing system, the programs with the same priority form a queue while waiting

to be executed. Types of Queues 1. 2. 3. 4. Linear Queue Circular Queue Priority Queue Double Ended Queue (DEQue) a) b) Input restricted deque Output restricted deque

9
M.Tech.

R.SIVA

4.1 Linear Queue


A queue, in which the elements can be accessed in a linear fashion, is called a linear queue. Representation (Implementation) of a Linear Queue

1. Static representation using arrays. 2. Dynamic representation using pointers (linked list). Static Representation of a Linear Queue using Arrays
Queue can be represented statically using a one-dimensional array. The following is the static representation

of a Queue of size N.

front end (delete)

rear end (insert)

front == rear == -1

rear == SIZE-1 rear++

Queue is empty; In this situation, it is impossible to dequeue an element from the queue. Queue is full; In this situation, it is impossible to enqueue an element into the queue. rear value is incremented by 1, just before an element is enqueued into queue at rear.
10
M.Tech.

R.SIVA

front++
front == rear

front value is also incremented by 1, just after an element at front is dequeued from queue. Queue has only one element Queue has more than one element

but not equal to -1


front != rear

ENQUEUE operation Algorithm: enqueue( ) // queue is an array of size N // initially front = rear = -1
1. if (rear == N-1)

// verify whether queue is full

a) Print queue is full and unable to enqueue an element b) return.

2. else
a) Read the element (item) to be enqueued b) if (rear == -1) front = rear = 0. c) else rear = rear+1 d) queue[rear] = item

// if queue is empty

DEQUEUE operation Algorithm: dequeue( ) // queue is an array of size N


1. if (front == -1)

// verify whether queue is empty

a) Print queue is empty and unable to dequeue an element b) return.

2. else
a) item = queue[front] b) if (front == rear) front = rear = -1 c) else front = front+1 d) Print the dequeued element

Initial empty queue. front= rear=-1

11
M.Tech.

R.SIVA

insert 10 10 front=0 rear=0 insert 20 10 20

Before inserting the first element 10 set both front & rear values to 0.

Before inserting 20, rear value is incremented by 1.

front=0 rear=1 insert 30 10 front=0 insert 40 10 front=0 insert 50 10 front=0 delete 20 front=1 delete 30 front=2 delete 40 50 30 40 50 20 30 40 50 20 30 40 20 30 rear=2 Before inserting 40, rear value is incremented by 1. Before inserting 30, rear value is incremented by 1.

rear=3 Before inserting 50, rear value is incremented by 1. Here rear=4 that means queue is full and we cant insert any more elements onto the queue.

rear=4 After deleting 10 front value is incremented

rear=4 After deleting 20 front value is incremented

rear=4 40 50 After deleting 30 front value is incremented

front=3 rear=4 delete 50 After deleting 40 front value is incremented. Now front = rear but not equal to -1. Hence, Queue has only one element.
12
M.Tech.

R.SIVA

front=4 rear=4 front= rear=-1


After deleting 50, the queue will be empty. So set front = rear = -1

Advantages with static implementation

Simple method

Disadvantages with static implementation

Size is fixed as it is an array. Unable to expand or compress the amount of memory. Insufficient memory allocation technique.

Queue ADT:

ENQUEUE( ) inserts an element into the queue at rear DEQUEUE( ) removes an element from the queue at front IsEmpty( ) tests whether a queue is empty IsFull( ) tests whether a queue is full

4.2 Circular Queue


A queue, in which the elements can be accessed in a circular fashion, is called a circular queue. Representation (Implementation) of a Circular Queue

1. Static representation using arrays. 2. Dynamic representation using pointers (linked list).
13
M.Tech.

R.SIVA

Static Representation of a Circular Queue using Arrays


Static representation of a Queue of size N using an array.

The shortcoming of array representation of a linear queue is that once rear points to n which is the maximum size of the queue, we cannot insert any more elements even if there is empty space in the queue. This limitation of linear queue is prevailed over by a circular queue to utilize the memory more efficient.
front == rear == -1

Queue is empty; In this situation, it is impossible to dequeue an element from the queue. Queue is full; In this situation, it is impossible to enqueue an element into the queue. rear is moved to next empty position, just before an element is enqueued into queue at rear. front is moved to next position, just after an element at front is dequeued from queue. Queue has only one element Queue has more than one element

rear == (front+1) mod SIZE rear = (rear+1) mod SIZE front = (front+1) mod SIZE
front == rear

but not equal to -1


front != rear

ENQUEUE operation Algorithm: enqueue( ) // queue is an array of size N // initially front = rear = 1
14
M.Tech.

R.SIVA

1. if (rear == (front+1) mod N)

// verify whether queue is full

a) Print queue is full and unable to enqueue an element b) return.

2. else
a) Read the element (item) to be enqueued b) if (rear == 1) front = rear = 0. c) else rear = (rear+1) mod N d) queue[rear] = item

// if queue is empty

DEQUEUE operation Algorithm: dequeue( ) // queue is an array of size N


1. if (front == 1)

// verify whether queue is empty

a) Print queue is empty and unable to dequeue an element b) return.

2. else
a) item = queue[front] b) if (front == rear) front = rear = 1// if queue has only one element c) else front = (front+1) mod N d) Print the dequeued element

Initial empty queue. front = rear = 1

insert 10

Before inserting the first element 10 set both front & rear values to 0.

15
M.Tech.

R.SIVA

insert 20

Before inserting 20, rear moves to 1.

insert 30

Before inserting 30, rear moves to 2.

insert 40, 50, 60, 70, and 80

After insertion of 40, 50, 60, 70, and 80, rear is currently at 7. Since rear is at highest index of the queue, we cant insert more elements in it.

delete

After deleting 10, front moves to next index 1.

16
M.Tech.

R.SIVA

delete

After deleting 20, front moves to next index 2.

delete 4 consecutive elements

After deleting 30, 40, 50, and 60, front moves to index 6.

insert 90

Since there is some empty space in the queue, we can insert elements in it by moving rear to next position.

delete 2 consecutive elements

After deleting 70 and 80, front moves to index 0.

17
M.Tech.

R.SIVA

delete

After deleting the single element from the queue, since the queue is empty, make front = rear = -1.

Advantages with static implementation

Simple method

Disadvantages with static implementation

Size is fixed as it is an array. Unable to expand or compress the amount of memory. Insufficient memory allocation technique.

CirQueue ADT:

ENQUEUE( ) inserts an element into the queue at rear DEQUEUE( ) removes an element from the queue at front IsEmpty( ) tests whether a queue is empty IsFull( ) tests whether a queue is full

18
M.Tech.

R.SIVA

4.3 Priority Queue Often the items added to a queue have a priority associated with them; this priority determines the order in which they exit the queue - highest priority items are removed first. 4.4 Double Ended Queue (DEQue) It is pronounced as deck. This is another type of queue in which insertions and deletions can be performed on both sides (front and rear) of the queue. A deque is the general form of both stack and queue representation, i.e. the deque can be used as a stack or a queue.
Static representation of a deque of size N using an array.

insert delete Front Rear

insert delete

Deques are of two types: 1) 2) Input restricted deque When insertion of elements into the deque is restricted to only one end and deletion can be done in Output restricted deque When deletion of elements into the deque is restricted to only one end and insertion can be done in both directions, such a deque is called output restricted deque.
19
M.Tech.

both directions, such a deque is called input restricted deque.

R.SIVA

Commonly deques are implemented using circular arrays. Deque ADT:


ENQUEUE_Front ( ) inserts an element into the queue at front ENQUEUE_Rear ( ) inserts an element into the queue at rear DEQUEUE_Front ( ) removes an element from the queue at front DEQUEUE_Rear ( ) removes an element from the queue at rear IsEmpty( ) tests whether a deque is empty IsFull( ) tests whether a deque is full

5. LINKED LIST
Linked list is a special list (chain) of elements (nodes) each of which contains arbitrary data fields and one

or two references/links/pointers to the next and/or previous elements. A linked list is a self-referential data type because it contains a link to another data of the same type. Linked lists permit insertion and removal of nodes at any point in the list in constant time, but do not allow random access.
Linked lists are of 2 types:

1. Linear-Linked List

Singly-Linear-Linked List / Singly Linked List Doubly-Linear-Linked List / Doubly Linked List Singly-Circular-Linked List Doubly-Circular-Linked List

2. Circular-Linked List

Advantages: 1. They are dynamic data structures- able to grow and shrink while executing the program. 2. Efficient memory utilization- memory is allocated and de-allocated whenever it is required. 3. Insertions and deletions at specific positions are easier and efficient.
20
M.Tech.

R.SIVA

4. Many complex applications can be easily carried out with Linked lists. Disadvantages:
1. More memory- each node must have at least two fields, one to hold data and another to hold a pointer. If

the nodes are more, more memory space is needed.


2. Access to an arbitrary data item is little bit cumbersome and also time consuming, since linked list does

not allow random access (rather it allows sequential access).


A Linked list with header / list with header / header linked list / header list is a linked list which always contains

a special node called the header node at the beginning of the list. It is an extra node kept at the front of the list. Such a node does not represent an item in the list. The information portion might be unused. There are two types of header lists
1. Grounded header list is a header list where the last node contains the NULL pointer. 2. Circular header list is a header list where the last node points back to the header node.

More often, the information portion of such a node could be used to keep global information about the entire list such as:

Number of nodes (not including the header) in the list. Count in the header node must be adjusted after adding or deleting a node in the list. Pointer to the current node in the list. It eliminates the need of an external pointer during traversal.

A Linked List without header is a list in which the first node (having information portion used) itself acts as the

header.

The operations performed on a singly linked list are as follows:

1) Traversing (visiting each node only once) 2) Searching 3) Sorting


21
M.Tech.

R.SIVA

4) Insertion 5) Deletion 6) Merging (two or more linked lists together)

5.1 Singly Linked List


A Singly Linked list is one in which every node has only one link to connect to next (or previous) node in some

sequential manner. Representation (Implementation) of singly linked list 1. Static representation using arrays. 2. Dynamic representation using pointers. Static Representation of Singly Linked list using Arrays
The linked list is maintained by two linear arrays one is used for data and the other for links. Let DATA and LINK be two arrays, DATA contains the data part and their corresponding pointers to the next nodes are stored in the array LINK. A pointer variable HEAD is used to store the first location of the linked list and a NULL pointer is used to denote the end of the list. Since, array subscripts are positive integers, NULL is represented by 0. Static representation of a Linked list using two one-dimensional arrays. 22
M.Tech.

R.SIVA

DATA 0 1 2 3 4 5 6 7 8 9 10 11 S L I T

LINK 10 7 1 NULL (0)

Head 4

Each node of the list in above figure contains a single character. The required string can be obtained as follows: HEAD = 4, so DATA[4] = L is the first character. The corresponding link of DATA[4] is stored in LINK[4]. LINK[4] = 7 shows that 7th element of DATA holds the next element, i.e. DATA[7] = I, the second character. LINK[7] = 1 shows that 1st element of DATA holds the next element, i.e. DATA[1] = S, the third character. LINK[1] = 10 shows that 10th element of DATA holds the next element, i.e. DATA[10] = T, the fourth character. LINK[10] = NULL shows that string is terminated. Hence, LIST is the required string.

Dynamic Representation of Singly Linked list using Pointers In this representation, a memory bank that is a collection of free memory space and memory manager program is used.
When a new node is to be created, the memory management searches the memory bank for the required memory

and if it is found, allocates memory to the new node and whenever a node is of no use, a program called garbage collector is invoked to return the unused node to the memory bank. This type of memory management is called Dynamic Memory Management.
A node in the list can be created by using self referential structures.

Self-referential structures
23
M.Tech.

R.SIVA

1. Structure that contains a pointer to a structure of the same type


2. It can be used to implement useful data structures such as lists, queues, stacks, trees and graphs.

struct s { int data; struct s *next; } Here next points to an object of type struct s, hence is called self referential pointer and the structure is called self referential structure.
30 NULL

Head

10

20

Linked list with header

10

20

30 NULL

Linked list without header

In above singly linked list representations, each node has the following structure having two fields:
nex t

data

1. data stores the data 2. next pointer/address/reference to the next node In first representation, head holds the address of the first node and each node contains the address of the next

node. The next field of last node contains NULL value which represents there are no further nodes.
24
M.Tech.

R.SIVA

Inserting a node at the beginning of the list Algorithm: insert_front ( ) // head beginning node in the list having no data // ins node to be inserted // item value to be inserted as the data portion of ins // headnext == NULL list is empty
1. Read the item to be inserted 2. Create a new node ins 3. insdata = item; 4. if headnext == NULL, then // if the list is empty i. headnext = ins; ii. insnext = NULL; 5. else i. insnext = headnext; ii. headnext = ins;

//if the list is non-empty

25
M.Tech.

R.SIVA

Inserting a node at the end of the list Algorithm: insert_end ( ) // head beginning node in the list having no data // ins node to be inserted // item value to be inserted as the data portion of ins // temp node used temporarily to traverse the list // headnext == NULL list is empty
1. Read the item to be inserted 2. Create a new node ins 3. insdata = item; 4. if headnext == NULL, then // if the list is empty i. headnext = ins; ii. insnext = NULL; 5. else

//if the list is non-empty

i. Traverse the list to reach the last node and make last node as temp ii. tempnext = ins; iii. insnext = NULL;

26
M.Tech.

R.SIVA

Inserting a node at a specific position in the list Algorithm: insert_any ( ) // head beginning node in the list having no data // ins node to be inserted // item value to be inserted as the data portion of ins // key item after which desired item is to be inserted // temp node used temporarily to traverse the list // headnext == NULL list is empty
1. if headnext == NULL, then // if the list is empty i. Write List is empty; Insert either at front or end

ii. return 2. else

// if the list is non-empty

i. Read key after which desired item is to be inserted ii. Search the list for the presence of the key 27
M.Tech.

R.SIVA

iii. if key not found, then

//if key not found

a) Write key not found; Insertion is not possible iv. else

// if key found

a) Read item to be inserted b) Create a new node ins c) insdata = item d) insnext = tempnext e) tempnext = ins

Deleting a node at the beginning of the list Algorithm: delete_front ( ) // head beginning node in the list having no data // del node to be deleted // headnext == NULL list is empty
1. if headnext == NULL, then // if the list is empty i. Write List is empty 28
M.Tech.

R.SIVA

ii. return 2. else i. del = headnext ii. headnext = delnext iii. Write deldata iv. delete node del

//if the list is non-empty // make the first node as del

29
M.Tech.

R.SIVA

Deleting a node at the end of the list Algorithm: delete_end ( ) // head beginning node in the list having no data // del node to be deleted // temp node used temporarily to traverse the list // headnext == NULL list is empty
1. if headnext == NULL, then // if the list is empty i. Write List is empty ii. return 2. else

//if the list is non-empty

i. Traverse the list to reach the last node; make last node as del and its previous node as temp ii. Write deldata iii. tempnext = NULL iv. delete node del

30
M.Tech.

R.SIVA

Deleting a specific node in the list Algorithm: delete_any ( ) // head beginning node in the list having no data // del node to be deleted // temp node used temporarily to traverse the list // key item to be deleted // headnext == NULL list is empty
1. if headnext == NULL, then // if the list is empty i. Write List is empty ii. return 2. else i. Read the key to be deleted ii. Search the list for the presence of the key iii. if key not found, then write key not found

//if the list is non-empty

iv. else

// if key found

a) make the node having key as del and its previous node as temp b) tempnext = delnext c) delete node del 31
M.Tech.

R.SIVA

Searching a node in the list Algorithm: search ( ) // head beginning node in the list having no data // temp node used temporarily to traverse the list // key item to be searched // headnext == NULL list is empty
1. if headnext == NULL, then // if the list is empty i. Write List is empty ii. return 2. else i. Read the key to be searched ii. temp = headnext

// if the list is non-empty // make the first node as temp


32
M.Tech.

R.SIVA

iii. Repeat until temp == NULL or tempdata == key a) temp = tempnext iv. if temp == NULL, then write key not found v. else write key found

// Search the list for the presence of the key

// if key not found // if key found i.e. tempdata == key

Dynamic Representation of a Stack using Pointers (Linked list)


Representing a stack using arrays (static implementation) is easy and convenient. However, it is useful for fixed sized stacks. Sometimes, during execution of a program, the size of the stack may be required to increase. This is possible when a stack is created dynamically. Using a linked list, a stack can be dynamically created. A singly linked list is used to represent a stack.

33
M.Tech.

R.SIVA

Dynamic representation of a Stack using linked list is as follows:

The first node in the list is the top of the stack and the last node is the bottom of the stack.

top == NULL top = topnext

Stack is empty (stack underflow); In this situation, it is impossible to pop a node from the stack. top refers to next node in the list.

PUSH operation Algorithm: push ( ) // top pointer to the topmost (first) node // initially top == NULL // ins node to be pushed // item value to be inserted as the data portion of ins
1. Read the item to be pushed 2. insdata = item 3. insnext = top 4. top = ins

//store the item in the node ins //make a link between ins and top //make ins as top

34
M.Tech.

R.SIVA

POP operation Algorithm: pop ( ) // top pointer to the topmost (first) node // initially top == NULL // del node to be popped
1. if top == NULL, then i. Write "stack is empty"

// if stack is empty

ii. return 2. else


i. Write topdata ii. del = top iii. top = topnext iv. delete node del

// if stack is non-empty // make top as del // make top pointer refer to next node

Advantages with dynamic implementation The stack may be expanded or compressed, since memory is allocated and de-allocated during runtime. Hence there is no limit on the size of the stack.
Disadvantages with dynamic implementation

More memory is required as each node in the stack maintains a pointer additionally. PUSH( ) inserts an element onto a stack POP( ) removes an element from the stack IsEmpty( ) tests whether a stack is empty
35
M.Tech.

Stack ADT:

R.SIVA

Dynamic Representation of a Linear Queue using Pointers (Linked list)


Using linked list, queue is created dynamically by which the size of the queue can be increased as per the necessity in the program, whereas using arrays the size of the queue is fixed. Dynamic representation of a Queue using linked list is as follows:

36
M.Tech.

R.SIVA

The first node in the list is the front of the queue and the last node is the rear of the queue. front == rear == NULL front = frontnext rearnext == NULL front == rear but not equal to NULL
front != rear

Queue is empty; In this situation, it is impossible to dequeue a node from the queue. front refers to next node in the list. rear is the last node in the list, there are no nodes further. Queue has only one node Queue has more than one node

ENQUEUE operation Algorithm: enqueue( ) // front pointer to the first node // rear pointer to the last node // front == rear == NULL queue is empty // ins node to be enqueued // item value to be inserted as the data portion of ins
1. Read the item to be inserted 2. insdata = item 3. insnext = NULL

//store the item in the node ins //since ins will be rear //if queue is empty //if queue is not empty

4. if front == NULL, then front = rear = ins 5. else i. rearnext = ins ii. rear = ins

37
M.Tech.

R.SIVA

DEQUEUE operation Algorithm: dequeue( ) // front pointer to the first node // rear pointer to the last node // front == rear == NULL queue is empty // del node to be dequeued
1. if front == NULL, then i. Write queue is empty"

//if queue is empty

ii. return
2. else i. Write frontdata

//if queue is not empty

ii. del = front


iii. front = frontnext iv. delete node del

38
M.Tech.

R.SIVA

Advantages with dynamic implementation

The queue may be expanded or compressed, since memory is allocated and de-allocated during runtime. Hence there is no limit on the size of the queue.

Disadvantages with dynamic implementation

More memory is required as each node in the queue maintains a pointer additionally.

Queue ADT:

ENQUEUE( ) inserts an element into the queue at rear DEQUEUE( ) removes an element from the queue at front IsEmpty( ) tests whether a queue is empty

39
M.Tech.

R.SIVA

5.2 Doubly Linked List


Doubly linked list is like singly linked list, in which for each node there are two pointers one to the previous

node, and one to the next node.


Hence,

We can traverse a doubly linked list forward and backward. We can insert a node anywhere in the list easily. This includes inserting before a node, after a node, at the front of the list, and at the end of the list. We can delete nodes very easily.

Doubly linked lists may or may not contain a header node.

5.3 Circular Linked List (Singly and Doubly circular linked lists) Circular linked lists are like linear linked lists, except that the last node contains a pointer back to the first node rather than the NULL pointer. In circular linked list, it is possible to reach any node from any node. If we begin at a given node and travel the entire list, we ultimately end up at the starting node.
Note that a circular list does not have a natural "first or "last" node. Therefore, we must establish a first and last

node by convention suppose external pointer points to the last node, then the following node will be the first node.
Circular (singly or doubly) linked lists may or may not contain a header node.

40
M.Tech.

R.SIVA

Differences between Arrays and Linked lists Array 1. Type of data stored 2. Insertion operation Homogeneous data It may require some of the other elements to move downwards It may require subsequent elements to move upwards to fill up the vacancy Random access Contiguous memory locations are allocated Not required Fast Static. Even if the array size is dynamically allocated, an estimate of maximum size is required. Linked List Arbitrary types of data It is a constant time operation

3. Deletion operation 4. Data accessing method 5. Memory allocation 6. Addition storage requirement 7. Data accessing speed

It is a constant time operation. Sequential access Contiguous memory locations are not allocated Required to store references to previous and/or next nodes Slow Dynamic. There is no limit on the size (number of nodes) of the list.

8. Nature

41
M.Tech.

R.SIVA

APPLICATIONS OF STACKS Stacks have a wide range of applications. The following are some of the applications. 1. Expression Conversion and Evaluation 2. Checking validity of an expression (Balancing of the matching parentheses/braces/brackets in an expression) 3. Function Calls and Recursion 4. Towers of Hanoi problem 1. Expression Conversion and Evaluation
Arithmetic expressions are expressed as combinations of

1. Operands 2. Operators (Arithmetic, Boolean, Relational, Logical operators) various rules have been formulated to specify the order of evaluation of operators in any expression. The arithmetic expressions are expressed in 3 different notations: 1. Infix (Standard form):

In this if the operator is binary; the operator is between the two operands.
Operand1 Operator Operand2

If the operator is unary, it precedes the operand.


Operator Operand

Ex:

a+b a+b*r (a+b)/c (ab)/(a+b+7)

2. Prefix (Polish form):

In this notation, for the case of binary operators, the operator precedes both the operands.
Operator Operand1 Operand2

Ex: +a*bc *+abc

+ab

*+abcd 3. Postfix (Suffix / Reverse Polish):

42
M.Tech.

R.SIVA

In this notation, for the case of binary operators, the operator is after both the corresponding
Operand1 Operand2 Operator

operands.

Ex:

ab+ abc*+ ab+c*

Note: Always remember that the order of appearance of operands does not change in any notation. What changes is the position of operators working on those operands.
A method of writing all operators either before or after their operands is called Polish notation. When the operators are written before their operands, it is called the Polish / Prefix form. When the

operators come after their operands, it is called Reverse Polish / Postfix / Suffix form. The polish notation offers certain computational advantages over the traditional infix form.
An infix expression can be interpreted in many different ways if the parentheses are not mentioned in the

expression. Therefore, to give a unique meaning, the precedence and associativity rules are used. But still it is difficult to evaluate an expression properly by a computer in its present form (infix form). Hence to get it evaluated properly, the operators are rearranged in postfix and prefix forms according to the rules of precedence and associativity of operators. All the parentheses are omitted in the polish notations i.e. prefix and postfix forms of expressions are completely parentheses free.
Points to remember while converting an expression from one notation to another notation:

High precedence operators are first processed followed by the remaining. If the expression has operators having same precedence, conversion is done according to their If there are nested brackets in the expression, conversion is done from innermost brackets to

associativity rules. outermost brackets. Convert given infix expression into equivalent prefix and postfix expressions.
1. Infix: a + ( b / d ) * ( e ^ f )

Prefix: a + /bd * ( e ^ f ) a + /bd * ^ef a + */bd^ef +a*/bd^ef Postfix: a + bd/ * ( e ^ f )


43
M.Tech.

R.SIVA

a + bd/ * ef^ a + bd/ef^* abd/ef^*+

2. Infix: L M / ( N * O ^ P )

Prefix: L M / ( *NO ^ P ) L M / ^*NOP L /M^*NOP L/M^*NOP Postfix: L M / ( NO* ^ P ) L M / NO*P^ L MNO*P^/ LMNO*P^/ The following algorithm translates an infix expression into its equivalent postfix form. Algorithm: Infix to Postfix Conversion // stack an array of characters. It always contains only left parentheses and/or operators. // top position/subscript/index of newly pushed element. // topstack element at the top of the stack // I infix expression/string/notation // P postfix expression/string/notation // ch character scanned from I.
1. Create an empty stack. 2. Push ( onto stack and append ) to the end of I. 3. Start scanning I from left to right and repeat steps 4 to 7 for each ch of I, until the stack is empty 4. If ch is an operand, append ch to P. 5. If ch is ( push it into the stack. 6. If ch is an operator and i.

If topstack is (, push ch into stack.


a) If topstack has higher or equal precedence over ch, then pop topstack and append it to P. 44
M.Tech.

ii. If topstack is an operator, compare the precedence of topstack with ch.

R.SIVA

b) If topstack has lower precedence over ch, then push ch into the stack.

Repeat step 6 until ch is pushed into stack.


7. If ch is ) then i.

Repeatedly pop topstack from stack and append it to P, until a ( is encountered.

ii. Pop (. iii. Do not append ( to P. 8. Print P. Ex: A+B*CD, (A+B^D)/(EF)+G


Ex: I: A+B*CD)

ch A + B * C D )

topstack ( ( + + * * * + ( empty

stack ( ( (+ (+ (+* (+* (+* (+ (+ empty

Postfix (P) A A AB AB ABC ABC* ABC* ABC* D ABC* D+

operation Initially push ( on to stack and append ) to I Here ch is an operand, append ch to P Here ch is an operator and topstack is (, push ch into stack Here ch is an operand, append ch to P Compare + with * (low precedence) , push ch into the stack Here ch is an operand, append ch to P Compare * with - (high precedence), pop topstack and append it to P Compare + with (equal precedence), pop topstack and append it to P Here ch is an operand, append ch to P Repeatedly pop topstack from stack and append it to P, until a (is encountered. Pop (.Do not append ( to P

45
M.Tech.

R.SIVA

Algorithm: Evaluation of Postfix Expression // stack an array of characters // top position/subscript/index of newly pushed element. // P postfix expression/string/notation // ch character scanned from P. //result result of an operation.
1. Create an empty stack. 2. Start scanning P from left to right and repeat steps 3 and 4 for each ch of P while ch != NULL 3. If ch is an operand, push it into the stack. 4. If ch is an operator, i.

Pop the required number of operands (one for unary, two for binary) from stack, and store the first popped element in temp1and second one in temp2.

ii. Evaluate result = temp2 ch temp1. (ch is an operator now) iii. Push the result back into stack. 5. Pop the result from stack.

Eg: a) 2, 3, 5, *, 3, , + b) 2, 3, 4, +, *, 21, 7, /, ch 2 3 5 stack 2 2, 3 2, 3, 5 Result ------------operation ch is an operand, push it into the stack ch is an operand, push it into the stack ch is an operand, push it into the stack
46
M.Tech.

R.SIVA

* 3 + NULL

2, 15 2, 15, 3 2, 12 14

3*5=15 ----15-3=12 2+12=14 14

Pop 3 & 5 and perform 5*3 and push the result back to stack ch is an operand, push it into the stack Pop 3 &15 and perform 15-3 and push the result back to stack Pop 12 &2 and perform 2+12 and push the result back to stack Pop the final result from the stack

2. Checking validity of an Infix Expression (Balancing of the matching parentheses/braces/brackets in an infix expression)
Compilers check programs for syntax errors, but frequently a lack of one symbol, such as a missing brace or

comment starter, will cause the compiler to spill out a hundred lines of diagnostics without identifying the real error.
A useful tool in this situation is a program that checks whether everything is balanced. Thus, every right

brace, bracket, and parenthesis2 must correspond to their left counterparts. The sequence [ ( ) ] is legal, but [ ( ] ) is wrong. Obviously, it is not worthwhile writing a huge program for this, but it turns out3 that it is easy to check these things. An expression is said to be valid, when i. There is an equal number of left and right parentheses/braces/brackets and ii. Every right parenthesis/brace/bracket is preceded by a matching left parenthesis/ brace/bracket. [A+(B*C)], {X*Y+(Z-5)}, {A+B-C}, [(A+B)-(C+D)] are valid expressions. [A+(B*C))] and {X*Y+(Z-5} are invalid and violate condition (i). {)A+B(-C} and [(A+B))-(C+D] are invalid and violate condition (ii). A stack is used to check for matching left and right parentheses/braces/brackets in an expression. For simplicity, we will just check for balancing of parentheses, brackets, and braces and ignore any other character that appears.

2 3

Parentheses ( ); Braces { }; Brackets [ ]; Turn out = To be found to be, as after experience or trial;

47

R.SIVA
M.Tech.

Algorithm: Checking Validity of an Expression


(Balancing of the matching parentheses4/braces/brackets in an expression)

// stack an array of characters. Here, stack contains only left parentheses/braces/brackets // ch character scanned from an expression. Here, we are concerned about the parentheses/ braces / brackets // valid integer variable, initially equal to 1 (TRUE). To make it FALSE, set valid to 0.
1. Create an empty stack. 2. Scan the expression character by character. Repeat steps 3 and 4, while ch != NULL. 3. If ch is a (, {, or [, then push it into stack. 4. If ch is a ), }, or ], then check for matching with (, {, or [ at top in stack. a) If stack is empty, then valid = 0. b) Else, pop one item from stack. If popped item doesnt match with ch, then valid = 0. 5. If stack is not empty, then valid = 0. 6. If valid == 1, then print Expression is valid.

7. Else, print Expression is invalid.

Parenthesis singular; parentheses plural;

48
M.Tech.

R.SIVA

Ex: [A+25*{Y*(B+C-X)-K}/D*(E+13)+M] top [ top { top (

{ top {

[ top [

[ top [ top= -1

top (

49
M.Tech.

R.SIVA

3. Function Calls and Recursion Stacks are an important application to the run-time environments of modern procedural languages, such as C, C++, and Java.
During the execution of a program, the run-time environment maintains a stack, called method stack, whose

elements are descriptors of the currently active (non-terminated) invocations of methods. These descriptors are called as stack frames / frames / activation records.
A stack frame is a collection of the following information:

Formal Parameters Local Variables Return Address

When a function calls other function, the stack frame of the caller/calling function is saved on the stack

including the address of instruction just next to the call instruction (available from program counter register). This is done so that after the execution of callee/called function, the execution control can come back from where it is sent to the callee/called function. Saving the stack frame on the stack is compulsory, since otherwise the new function (callee/called function) will overwrite the memory registers used by the calling methods variables. After saving, the control is transferred to the new function, which is free to replace the registers with its values. If it makes other function calls, it follows the same procedure. The stack frame for each method call will be different. For example, the stack frame for a method having no parameters and no local variables will contain just a return address.
At the top of the stack is the frame of the running method, that is, the method that currently has control of

execution. The remaining elements of the stack are frames of the suspended methods, i.e. methods that have invoked another method and are currently waiting for it to return control to them upon its termination. The order of the elements in the stack corresponds to the chain of invocations of the currently active methods. When a new method is invoked, a frame for this method is generated on the stack. When it terminates,
50
M.Tech.

R.SIVA

its frame is popped from the stack and the computer resumes the processing of the previously suspended method.
The method stack also performs parameter passing to methods. Specifically, many languages, such as C and

Java, use the call-by-value parameter passing protocol using the method stack. This means, that the current value of a variable / expression is passed as an argument to a callee/called method. In the case of a variable x, of type int or float, the current value of x is simply the number that is associated with x. When such a value is passed to the callee/called method; it is assigned to a local variable in the callee/called methods frame. Note that if the callee/called method changes the value of this local variable, the method will not change the value of the variable in the calling method.

f2:

10

m=7 PC = address next to 30

main( ){ int i=5; . . f1( i ); . . } f1( int j){ int k=7; . . f2( k ); . . } f2( int m){ .
. }

f1:

j=5 k=7 PC = address next to 20

20

main:

i=5 PC = address next to 10

30

51
M.Tech.

R.SIVA

Recursion One of the benefits of using a stack to implement function invocation is that it allows programs to use recursion.
A function calling itself either directly or indirectly is said to be Recursive function. A function may call itself directly within its definition. This is called Direct Recursion. A function may call another function, which in turn calls the first function. This is called Indirect Recursion. Many algorithms have both iterative and recursive formulation. But, recursion is more elegant 5 and requires

fewer variables to make the same calculation. The following is a function to compute the factorial of n, recursively and iteratively.
// recursive int fact(int n){ int f; if(n==0) f=1; else f = n*fact(n-1); return f; } } // iterative int fact(int n){ int i,f=1; for(i=n;i>0;i--) f = f*i; return f;

A recursive function is said to be Well-defined, if it satisfies the following two properties: 1. There must be certain arguments, called base values, for which the function doesnt refer to itself (stopping

condition).
2. Each time when the function refers to itself, the argument of the function must be closer to a base value.
5

Elegant = tasteful;

52
M.Tech.

R.SIVA

The following strategy is followed in recursion:


1.

Each time when a recursive call is made in the program, caller/calling methods stack frame is saved When the execution of callee/called method is complete (at deeper level), its stack frame is popped

on the stack and a new frame of callee/called method is created on the stack.
2.

and execution of caller/calling method is resumed (at higher level) at the point indicated by the return address popped from the stack frame of caller/calling method. 3. This process is continued, until there are no return addresses in stack.

The following program is an example of tail recursion. Tail recursion refers to a recursive call at the last

line. Example:
// recursive int fact(int n){ int f; if(n==0) f=1; else f = n*fact(n-1); return f; } void main(){ int num=5,factorial; factorial = fact(num); cout<<factorial of 5=<<fact(5); } The depth of the recursion is the maximum degree of nesting of the function calls over the course of the

computation. Generally, the depth will depend on the input. When using a recursive program, we need to take into account that the programming environment has to maintain a stack of size proportional to the depth of the recursion. Example: The depth of recursion in computing factorial 4 is 5. In above program,
53
M.Tech.

R.SIVA

1. 2. 3. 4. 5.

main() calls fact(4) fact(4)calls fact(3) fact(3) calls fact(2) fact(2) calls fact(1) fact(1) calls fact(0)

Since fact(0) does not call itself during its execution, recursion terminates with it.

APPLICATIONS OF QUEUES In general, Queues are often used as waiting lines. A few examples where queues are used are as follows: 1. There are several algorithms that use queues to give efficient running times. Several of these are found in graph theory. 2. There are many computer network setups of personal computers in which the disk is attached to one machine, known as the file server. Users on other machines are given access to files on a first-come firstserved basis, so the data structure is a queue. 3. When jobs are submitted to a printer, they are arranged and placed in order of arrival on a queue. These jobs are accomplished on a first-come first-served basis. 4. Operating systems often maintain a queue of processes that are ready to execute or that are waiting for a particular event to occur. 5. Computer systems must often provide a holding area for messages between two processes, two programs or even two systems. This holding area is usually called a buffer and is often implemented as a queue. 6. Queue is used in the implementation of priority queues, which are required to be maintained by the scheduler of an operating system. A priority queue is a special type of queue in which each element has a priority value and the elements are required to be inserted in the queue in decreasing order of priority, so that the element with the highest priority can be dequeued and processed first.
54
M.Tech.

R.SIVA

7. In Time Sharing Systems to achieve Multiprogramming, queues are used. Multiprogramming allows multiple tasks or programs to run at the same time even on a computer that has only one CPU.

Multiprogramming in Time sharing systems


Multiprogramming is a way of achieving a limited form of parallelism, even on a computer with only one

CPU. Multiprogramming allows multiple processes/threads to run at the same time, with each process/thread being responsible for some specific computation. Multiprogramming is useful in graphical applications. For example, one thread can be responsible for catching mouse clicks while several others are responsible for moving parts of an animation around in a screen canvas. Even if the computer has only one CPU, these different computational threads can all seem to be running at the same time because: 1. 2. The CPU is so fast relative to our perception of time. The operating system is providing each thread with a different slice of the CPUs time.

When designing a program that uses multiple threads, we must be careful not to allow an individual thread to

monopolize6 the CPU. Such CPU monopolization can lead to an application hanging.
In some operating systems, CPU monopolization by threads is not an issue. These operating systems utilize a

queue to allocate CPU time to the runnable threads in the round-robin protocol.
6

Monopolize = To dominate by excluding others;

55
M.Tech.

R.SIVA

The main idea of round-robin protocol is to store all runnable threads in a queue Q on priority based. When the CPU is ready to provide a time slice to a thread, it performs a dequeue operation on the Before the CPU actually begins executing instructions for T, it starts a timer running in hardware set The CPU now continues processing until either
a) Thread T blocks itself or

queue Q to get the next available runnable thread T. to expire a fixed amount of time later.

b) The timer expires. In the latter case, the CPU stops the execution of T and performs an enqueue operation to place T at the end of the queue of currently runnable threads.

In either case, the CPU saves the stack frame of T at the top of the method stack and processes the In this way, the CPU ensures that each runnable thread is given its fair share of time. Thus, by using a simple queue data structure and a hardware stopwatch, the operating system can

next available runnable thread by extracting it from Q with a dequeue operation.

avoid CPU monopolization.

APPLICATIONS OF LINKED LISTS Linked lists have a wide range of applications. The following are some of the applications. 1. Polynomial Representation and Manipulation 2. Sparse Matrix Representation and Manipulation 3. In Dynamic Memory Management (In allocation and de-allocation (releasing) memory at runtime) 4. In Symbol Table (An important aspect of any compiler is the construction and maintenance of a dictionary containing names and their associated values. Such a dictionary is also called as a symbol table.) 1. Polynomial Representation and Manipulation Polynomials in terms of x
A polynomial in terms of x can be represented in an array or in a linked list by simply viewing the

polynomial as a list of (coefficient, exponent) pairs. For example, the polynomial 3x2+2x+4 can be viewed as a list of the following pairs (3,2), (2,1), (4,0) It often doesnt matter whether the polynomial is in x or y or z.
Therefore, we can use a linked list in which each node will have three fields as shown in the following

figure.
56
M.Tech.

R.SIVA

COEFFICIENT

EXPONENT

LINK

Hence, the above polynomial 3x2+2x+4 can be represented as shown below:

In general, an nth degree polynomial can have a maximum of (n+1) terms. But, in a polynomial all the terms

may not be present, especially if it is going to be a very high-degree polynomial. For example, the polynomial 10x4 + 5x2 + 1 of degree 4, has only 3 terms instead of 5 which can be represented as shown below:

The linked list representation is easier to deal with the following common operations on polynomials. i. Four basic arithmetic operations (addition, subtraction, multiplication, division) ii. Integration iii. Differentiation

Addition of Two Polynomials in terms of x Start with the highest power in any polynomial. If there is no item having the same exponent, simply append the term to the new list and continue with the process. Wherever matching of the exponents is found, check whether the terms get cancelled. If not, simply add the coefficients and then store the resultant term in the new list. If one polynomial gets exhausted earlier and the other list still contains some lower-degree terms, then simply append the remaining terms to the new list. Algorithm: Addition of two polynomials in terms of x // polynomial-1 & polynomial-2 Given polynomials in descending order of exponents // polynomial-3 Resultant polynomial (also in descending order of exponents) // A term in the polynomial is represented by a node in the list // t1 temporary node in polynomial-1
57
M.Tech.

R.SIVA

// t2 temporary node in polynomial-2 // t3 temporary node in polynomial-3 // phead1 head node (beginning node) in polynomial-1 // phead2 head node (beginning node) in polynomial-2 // phead3 head node (beginning node) in polynomial-3 // coeff coefficient of a term (node) // exp exponent of a term (node) // next link to next term (node)
1. Read polynomial-1 and polynomial-2 in descending order of exponents. 2. Set t1=phead1; and t2=phead2; 3. Create a new node t3 to build the third polynomial. 4. Set phead3=t3; (making t3 as the beginning node phead3 in polynomial-3) 5. Compare the coefficients of t1 and t2. Repeat steps 6 through 9 until one polynomial gets exhausted. (until

either t1==NULL or t2==NULL)


6. if t1->exp > t2->exp, then

i. t3->coeff = t1->coeff; ii. t3->exp = t1->exp; iii. t1 = t1->next;


7. else, if t1->exp < t2->exp, then

i. t3->coeff = t2->coeff; ii. t3->exp = t2->exp; iii. t2 = t2->next;


8. else a)

// i.e. if t1->exp == t2->exp if t1->coeff != -t2->coeff, then i. t3->coeff = t1->coeff + t2->coeff;

ii. t3->exp = t1->exp;

// or t3->exp = t2->exp;

iii. t1 = t1->next; iv. t2 = t2->next;


b)

if t1->coeff == -t2->coeff, then i. t1 = t1->next; ii. t2 = t2->next;


iii. Go to step 6

9. Create a new node, append it to the last node t3 of polynomial-3, and make it t3 finally. 58
M.Tech.

R.SIVA

10. If t1==NULL, repeat the following until t2==NULL.

i. t3->coeff = t2->coeff; ii. t3->exp = t2->exp; iii. t2 = t2->next;


iv. Create a new node, append it to the last node t3 of polynomial-3, and make it t3 finally. 11. Else, repeat the following until t1==NULL.

i. t3->coeff = t1->coeff; ii. t3->exp = t1->exp; iii. t1 = t1->next;


iv. Create a new node, append it to the last node t3 of polynomial-3, and make it t3 finally. 12. t3 = NULL; // making the last empty node NULL in the resultant polynomial 13. Print polynomial-3.

Ex: Polynomial-1: 5x12+2x9+4x7+8x6+x3 Polynomial-2: 7x8+2x7-8x6+6x4+2x2-3x-40

Polynomials in terms of x and y


A polynomial in two variables x and y can be represented by a linked list in which each node represents a

term of a polynomial and contains coefficient, and the exponents of x and y of that term.
Therefore, we can use a linked list in which each node will have four fields as shown in the following figure.

COEFFICIENT Polynomials in terms of x, y, and z

EXPONENT of X

EXPONENT of Y

LINK

A polynomial in three variables x, y and z can be represented by a linked list in which each node represents a

term of a polynomial and contains coefficient, and the exponents of x, y and z of that term.
Therefore, we can use a linked list in which each node will have five fields as shown in the following figure.

COEFFICIENT

EXPONENT of X

EXPONENT of Y
59

EXPONENT of Z
M.Tech.

LINK
R.SIVA

2. Sparse Matrix Representation and Manipulation


A matrix is a two-dimensional data object made of m rows and n columns, hence having mn values. When

m=n, we call it a Square Matrix.


The most natural representation is to use two-dimensional array A[m][n] and access the element of ith row

and jth column as A[i][j].


An mn matrix is said to be Sparse Matrix if a large number of elements of the matrix are zero. A matrix

that is not sparse is Dense7. The boundary between a dense and a sparse matrix is not precisely defined.

Dense in this matrix a few elements are zero;

60
M.Tech.

R.SIVA

Sparse matrices are commonly used in scientific applications and contain hundreds or even thousands of rows and columns.
Representing a sparse matrix by using a two-dimensional array leads to the wastage of a substantial amount

of space. Therefore, an alternative representation must be used for sparse matrices. One such representation is to store only non-zero elements along with their row positions and column positions. That means representing every non-zero element by using triples (i,j,value), where i is a row position and j is a column position, and store these triples in a linear list. It is possible to arrange these triples in the increasing order of row indices, and for the same row index in the increasing order of column indices. Each triple (i,j,value) can be represented by using a node having four fields as shown below:

So a sparse matrix can be represented using a list of such nodes, one per nonzero element of the matrix. For example, consider the sparse matrix shown below.

This matrix can be represented using the linked list shown below.

Addition of Sparse Matrices using Linked List In order to add two sparse matrices represented using the sorted linked lists, the lists are traversed until the end of one of the lists is reached. In the process of traversal, the row indices stored in the nodes of these lists are compared. If they don't match, a new node is created and inserted into the resultant list by copying the contents of a node with a lower value of row index. The pointer in the list, containing a node with a lower value of row index, is advanced to make it point to the next node.
61
M.Tech.

R.SIVA

If the row indices match, column indices for the corresponding row positions are compared. If they don't match, a new node is created and inserted into the resultant list by copying the contents of a node with a lower value of column index. The pointer in the list, containing a node with a lower value of column index, is advanced to make it point to the next node. If the column indices match, a new node is created and inserted into the resultant list by copying the row and column indices from any of the nodes and the value equal to the sum of the values in the two nodes. After this, the pointers in both the lists are advanced to make them point to the next nodes in the respective lists. This process is repeated in each iteration. After reaching the end of any one of the lists, the iterations come to an end and the remaining nodes in the list whose end has not been reached are copied into the resultant list. Example Consider the following sparse matrices:

The result of addition is shown below:

The above resultant list represents the matrix shown below:

62
M.Tech.

R.SIVA

This matrix is an addition of the matrices a and b, respectively.

63
M.Tech.

R.SIVA

Você também pode gostar