CS3353 Unit3
CS3353 Unit3
CS3353 Unit3
INTRODUCTION
Definition
Data structure is a particular way of organizing, storing and retrieving data, so that it can be used efficiently. It is the
structural representation of logical relationships between elements of data.
Primitive Data Structure - Primitive data structures are predefined types of data, which are supported by the
programming language. These are the basic data structures and are directly operated upon by the machine
instructions, which is in a primitive level.
Non-Primitive Data Structure - Non-primitive data structures are not defined by the programming language, but are
instead created by the programmer. It is a more sophisticated data structure emphasizing on structuring of a group
of homogeneous (same type) or heterogeneous (different type) data items.
Linear data structure- only two elements are adjacent to each other. (Each node/element has a single successor)
o Restricted list (Addition and deletion of data are restricted to the ends of the list)
Stack (addition and deletion at top end)
Queue (addition at rear end and deletion from front end)
o General list (Data can be inserted or deleted anywhere in the list: at the beginning, in the middle or at the end)
Non-linear data structure- One element can be connected to more than two adjacent elements.(Each node/element
can have more than one successor)
o Tree (Each node could have multiple successors but just one predecessor)
o Graph (Each node may have multiple successors as well as multiple predecessors)
Note - Array and Linked list are the two basic structures for implementing all other ADTs.
1
Unit III– Linear Structures-List
MODULARITY
Module- A module is a self-contained component of a larger software system.Each module is a logical unit and does
a specific job. Its size kept small by calling other modules.
Modularity is the degree to which a system's components may be separated and recombined. Modularity refers to
breaking down software into different parts called modules.
Advantages of modularity
o It is easier to debug small routines than large routines.
o Modules are easy to modify and to maintain.
o Modules can be tested independently.
o Modularity provides reusability.
o It is easier for several people to work on a modular program simultaneously.
2
Unit III– Linear Structures-List
Benefits of using ADTs or Why ADTs
o Code is easier to understand. Provides modularity and reusability.
o Implementations of ADTs can be changed without requiring changes to the program that uses the ADTs.
LIST ADT
List is a linear collection of ordered elements. The general form of the list of size N is: A0, A1, …, AN-1
o Where A1 - First element
AN - Last element
N - Size of the list
o If the element at position 'i' is Ai then its successor is Ai+1 and its predecessor is Ai-1.
Various operations performed on a List ADT
o Insert (X,5) - Insert the element X after the position 5.
o Delete (X) - The element X is deleted.
o Find (X) - Returns the position of X
o Next (i) - Returns the position of its successor element i+1.
o Previous (i) - Returns the position of its Predecessor element i-1.
o PrintList - Displays the List contents.
o MakeEmpty - Makes the List empty.
Deleting an item
Unit III– Linear Structures-List
Type Declarations
#define Max 10
int A[Max],N;
Routine to insert an Element in the specified position
void insert(int x, int p, int A[], int N)
{
int i;
If(p==N)
printf(“Array Overflow”);
else
{
for(i=N-1;i>=p-1;i--)
A[i+1]=A[i];
A[p-1]=x;
N=N+1;
}
}
Find Routine
void Find (int X)
{
int i,f=0;
for(i=0;i<N;i++)
if(a[i]==x)
{
f=1;
break;
}
if (f==1)
printf(“Element found”);
else
printf(“Element not found”);
}
Unit III– Linear Structures-List
STACK
Definition
Stack is alinear list in which elements are added and removed from only one end, called the top.It is a "last in,
first out" (LIFO) data structure. At the logical level, a stack is an ordered group ofhomogeneous items or
elements.Because items are added and removed only from the top of the stack, the last element to be added is the first
to be removed. Stacks are also referred as "piles" and "push-down lists".
Operations on stacks
Push - Inserts new item to the top of the stack. After the push, the new item becomes the top.
Pop - Deletes top item from the stack. The next older item in the stack becomes the top.
Top - Returns a copy of the top item on the stack, but does not delete it.
MakeEmpty - Sets stack to an empty state.
Boolean IsEmpty - Determines whether the stack is empty. IsEmpty should compare top with -1.
Boolean IsFull - Determines whether the stack is full. IsFull should compare top with MAX_ITEMS - 1.
Conditions
Stack overflow - The condition resulting from trying to push an element onto a full stack.
Stack underflow - The condition resulting from trying to pop an element from an empty stack.
APPLICATIONS OF STACKS
Recursion - Example, Factorial, Tower of Hanoi.
Balancing Symbols, i.e., finding the unmatched/missing parenthesis. For example, ((A+B)/C and (A+B)/C). Compilers
often use stacks to perform syntax analysis of language statements.
Conversion of infix expression to postfix expression and decimal number to binary number.
Evaluation of postfix expression.
Backtracking- For example, 8-Queens problem.
Function calls - When a call is made to a new function, all the variables local to the calling routine need to be saved
by the system, since otherwise the new function will overwrite the calling routine's variables. Similarly the current
location in the routine must be saved so that the new function knows where to go after it is done. For example, the
main program calls operation A, which in turn calls operation B, which in turn calls operation C. When C finishes,
control returns to B; when B finishes, control returns to A; and so on. The call-and-return sequence is essentially a
LIFO sequence, so a stack is the perfect structure for tracking it.
Implementations of stack
1. Array implementation of stack
2. Linked list implementation of stack
void push();
void pop();
void display();
int stack[MAX], top=-1, item;
void push()
{
if(top == MAX-1)
printf("Stack is full");
else
{
printf("Enter item: ");
scanf("%d",&item);
top++;
stack[top] = item;
printf("Item pushed = %d", item);
}
}
void pop()
{
if(top == -1)
printf("Stack is empty");
else
{
item = stack[top];
top--;
printf("Item popped = %d", item);
}
}
void display()
{
int i;
if(top == -1)
printf("Stack is empty");
else
{
for(i=top; i>=0; i--)
printf("\n %d", stack[i]);
}
}
Unit III– Linear Structures-List
Types of Queues
There are three major variations in a simple queue. They are
Linear queue
Circular queue
Double ended queue (Deque)
o Input restricted deque
o Output restricted deque
Priority queue
Operations on Queue
Enqueue -Insertsan itemat the rear end of the queue.
Dequeue- Deletesan item at the front end of the queue and returns.
Conditions
Queue overflow - The condition resulting from trying to enqueue an element onto a full Queue.
Queue underflow - The condition resulting from trying to dequeue an element from an empty Queue.
Implementation of Queue
1. Array implementation
2. Linked list implementation
o Array and linked list implementations give fast O(1) running times for every operation
0 1 2 3 4
Empty Queue F = R = -1
10
0 1 2 3 4
^^
Unit III– Linear Structures-List
FR
After Enqueue (10)
10 3
0 1 2 3 4
^ ^
F R
After Enqueue (3)
10 3 41
0 1 2 3 4
^ ^
F R
After Enqueue (41)
3 41
0 1 2 3 4
^ ^
F R
After Dequeue ()
3 41 76
0 1 2 3 4
^ ^
F R
After Enqueue (76)
3 41 76 66
0 1 2 3 4
^ ^
F R
After Enqueue (66)
41 76 66
0 1 2 3 4
^ ^
F R
After Dequeue ()
There is one potential problem with array implementation. From the above queue, now if we attempt to add more
elements, even though 2 queue cells are free, the elements cannot be inserted. Because in a queue, elements are
Unit III– Linear Structures-List
always inserted at the rear end and hence rear points to last location of the queue array Q[4]. That is queue is full
(overflow condition) though it is empty.
The simple solution is that whenever front or rear gets to the end of the array, it is wrapped around to the
beginning. This is known as a circular array implementation.
Array implementation of Linear Queue
#include <stdio.h>
#include<conio.h>
#define MAX 3
void enqueue();
void dequeue();
void display();
void enqueue()
{
if(rear == MAX-1)
printf("Queue is full");
else
{
printf("Enter item : ");
scanf("%d", &item);
if (rear == -1 && front == -1)
rear = front = 0;
else
rear = rear + 1;
queue[rear] = item;
printf("Item enqueued : %d", item);
}
}
void dequeue()
{
if(front == -1)
printf("Queue is empty");
else
{
item = queue[front];
if (front == rear)
front = rear = -1;
else
front = front + 1;
printf("Item dequeued : %d", item);
}
}
void display()
{ int i;
if(front == -1)
Unit III– Linear Structures-List
printf("Queue is empty");
else
for(i=front; i<=rear; i++)
printf("%d ", queue[i]);
}
Circular Queue
In circular queues the elements Q[0],Q[1],Q[2] ...... Q[n – 1] is represented in a circular fashion with Q[1] following
Q[n]. A circular queue is one in which the insertion of a new element is done at the very first location of the queue
ifthe last location at the queue is full.
Initially Front = Rear = -1. That is, front and rear are at the same position.
At any time the position of the element to be inserted will be calculated by the relation: Rear = (Rear + 1) % SIZE
After deleting an element from circular queue the position of the front end is calculated by the relation:
Front=(Front + 1) % SIZE.
After locating the position of the new element to be inserted, rear, compare it with front. If Rear = Front, the
queueis full and cannot be inserted anymore.
No of elements in a queue = (Rear – Front + 1) % N
Deque - Double Ended QUEeue
Definition
A deque is a homogeneous list in which inserted and deleted operations are performed at either ends of the
queue. That is, we can add a new element at the rear or front end and also we can remove an element from both front
and rear end. Hence it is called double ended queue. The most common ways of representing deque are: doubly linked
list, circular list.
Types of deques
1. Input restricted deque
2. Output restricted deque
An input restricted deque is a deque, which allows insertion at only 1 end, rear end, but allows deletion at both
ends, rear and front end of the lists.
An output-restricted deque is a deque, which allows deletion at only one end, front end, but allows insertion at
both ends, rear and front ends, of the lists.
Unit III– Linear Structures-List
Priority Queue
Definition
Priority Queue is a queue where each element is assigned a priority. The priority may implicit (decided by its value)
or explicit (assigned). In priority queue, the elements are deleted and processed by following rules.
o An element of higher priority is processed before any element of lower priority.
o Two elements with the same priority are processed according to the order in which they were inserted to
the queue.
Example for priority queue:
o In a telephone answering system, calls are answered in the order in which they are received;
o Hospital emergency rooms see patients in priority queue order; the patient with the most severe injuries
sees the doctor first.
A node in the priority queue will contain Data, Priority and Next field. Data field will store the actual information;
Priority field will store its corresponding priority of the data and Next will store the address of the next node.
When an element is inserted into the priority queue, it will check the priority of the element with the element(s)
present in the linked list to find the suitable position to insert. The node will be inserted in such a way that the data
in the priority field(s) is in ascending order. We do not use rear pointer when it is implemented using linked list,
because the new nodes are not always inserted at the rear end.
Applications of queue
When jobs are submitted to a printer, they are arranged in order of arrival. Thus, essentially, jobs sent to a line
printer are placed on a queue.
Virtually every real-life line is (supposed to be) a queue. For instance, lines at ticket counters are queues, because
service is first-come first-served.
Another example concerns computer networks. There are many 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 first-served basis, so the data structure is a queue.
Calls to large companies are generally placed on a queue when all operators are busy.
There are several algorithms that use queues to solve problems easily. For example, BFS, Binary tree traversal etc.
Round robin techniques for processor scheduling is implemented using queue.
LINKED LIST
Definition
Linked list is adynamic data structure which is an ordered collection of
homogeneous dataelements called nodes, in which each element contains two parts:
data or Info and one or more links. The data holds the application data to be
processed. The link contains (the pointer) the address of the next element in the list.
12
Unit III– Linear Structures-List
SentinelNode
It is also called as Header nodeor Dummy node.
Advantages
o Sentinel node is used to solve the following problems
First, there is no really obvious way to insert at the front of the list from the definitions given.
Second, deleting from the front of the list is a special case, because it changes the start of the list; careless
coding will lose the list.
A third problem concerns deletion in general. Although the pointer moves above are simple, the deletion
algorithm requires us to keep track of the cell before the one that we want to delete.
Disadvantages
o It consumes extra space.
Insertion
a. Creating a newnode from empty List
Deletion
a. Inserting a node to the front of list
Find Routine
/* Returns the position of X in L; NULL if not found */Position Find (int X)
{
position p;
P = head->next;
while( (p!= NULL) && (p->data != X) )p = p->next;
return P;
}
FindPrevious Routine
/* Returns the previous position of X in L */
Unit III– Linear Structures-List
position FindPrevious
position FindPrevious (int X)
{
position P;
P = head;
while( (P->Next!= NULL) && (P->Next->data != X) )P = P->Next;
return P;
}
FindNext Routine
/* Returns the position of X in L; NULL if not found */Position Find (int X)
{
position p;
P = head->next;
while( (p!= NULL) && (p->data != X) )p = p->next;
return P->next;
}
void traversal ()
{
position p;
P = head->next;while( p!= NULL)
{
printf(p->data);p = p->next;
}
}
Insertion
Inserting a node to the front of list
Insert at Beginning
void Insert_beg (int X)
{
position NewNode;
NewNode = malloc (sizeof(struct Node));
Unit III– Linear Structures-List
if(NewNode != NULL)
{
NewNode->data = X;
NewNode->next = L->Next;
head->next = NewNode;
}
}
Insertion at Middle
/* Insert element X after position P */
void Insert_mid (int X, position P)
{
position NewNode;
NewNode = malloc (sizeof(struct Node));
if(NeWNode != NULL)
{
NewNode->data = X;
NewNode->next = P->next;
P->next = NewNode;
}
}
c.Inserting a node to the end of list
Insert at Last
void Insert_last (int X)
{
position NewNode,P;
NewNode = malloc (sizeof(struct Node));
if(NewNode != NULL)
{
while(P->next!=NULL)
P = P->next;
NewNode->data = X;
NewNode->next = NULL;
P->next = NewNode;
}
Unit III– Linear Structures-List
}
Deletion
Deleting a node to the front of list
Delete at Beginning
void Delete_beg ()
{
position TempCell;
if(head->next!=NULL)
{
TempCell = head->next;
head->next = TempCell ->next;
free(TempCell);
}
Deleting the middle node
Delete at Last
void Delete_last ()
{
position TempCell,P;
while(P->next->next!=NULL)
Unit III– Linear Structures-List
P = P->next;
TempCell = P->next;
P->next = NULL;
free(TempCell);
}
Disadvantages
The circular linked list requires extra care to detect the end of the list. It may be possible to get into an infinite loop.
So it needs a header node to indicate the start or end of the list.
Definition
A circular linked list is one, which has no beginning and no end. Circular linked list is a list in which every node has a
successor; the "last" element is succeeded by the "first" element. We can start at any node in the list and traverse
the entire list.
Advantages
Traversing in reverse is possible.
Deletion operation is easier, since it has pointers to its predecessor and successor.
Unit III– Linear Structures-List
Finding the predecessor and successor of a node is easier.
Disadvantages
A doubly linked list needs more operations while inserting or deleting and it needs more space (to store the extra
pointer). There are more pointers to keep track of in a doubly linked list. For example, to insert a new node after a
given node, in a singly linked list, we need to change two pointers. The same operation on a doubly linked list
requires four pointer changes.
Definition
A circular linked list is one, which has no beginning and no end. A doubly circular linked list is a doubly linked list with
circular structure in which the last node points to the first node and the first node points to the last node and there are
two links between the nodes of the linked list. In doubly circular linked list, the left link of the leftmost node contains the
address of the rightmost node and the right link of the rightmost node contains the address of the leftmost node.
Push operation
Pop operation
struct node
{
int data;
struct node *next;
} *top = NULL;
void push(int x)
{
position p;
p =(struct node *)malloc(sizeof(struct node));
if (p == NULL)
printf("Memory allocation error \n");
else
{
if (top == NULL)
{
top =(struct node *)malloc(sizeof(struct node));
p->data=x;
p->next = NULL;
top->next = p;
}
else
{
p->data=x;
p->next = top->next;
top->next=p;
}
}
}
Unit III– Linear Structures-List
void pop()
{
position p;
p = top->next;
if (top == NULL)
printf("Stack is empty");
else
{
top->next= top->next->next;
printf("\n Popped value : %d\n", p->data);
free(p);
}
}
void display()
{
struct node *p;
if (top == NULL)
printf("Stack is empty");
else
{
p = top;
while(p != NULL)
{
printf("\n%d", p->data);
p = p->next;
}
}
}
struct node
{
int data;
struct node *next;
} *top = NULL;
void dequeue()
{
position p;
p = front->next;
if (front == NULL)
printf("Queue is empty\n");
else
{
printf("\n Dequeued value : %d\n", p->data);
front->next=front->next->next;
free(p);
}
void display()
{
position p;
p = front->next;
if (front == NULL)
printf("Queue is empty\n");
else
{
printf("Queue elements are : \n");
while (p != NULL)
{
Unit III– Linear Structures-List
printf("%d ",p->data);
p = p->next;
}
}
APPLICATIONS OF STACKS
Recursion - Example, Factorial, Tower of Hanoi.
Balancing Symbols, i.e., finding the unmatched/missing parenthesis. For example, ((A+B)/C and (A+B)/C). Compilers
often use stacks to perform syntax analysis of language statements.
Conversion of infix expression to postfix expression and decimal number to binary number.
Evaluation of postfix expression.
Backtracking- For example, 8-Queens problem.
Function calls - When a call is made to a new function, all the variables local to the calling routine need to be saved
by the system, since otherwise the new function will overwrite the calling routine's variables. Similarly the current
location in the routine must be saved so that the new function knows where to go after it is done. For example, the
main program calls operation A, which in turn calls operation B, which in turn calls operation C. When C finishes,
control returns to B; when B finishes, control returns to A; and so on. The call-and-return sequence is essentially a
LIFO sequence, so a stack is the perfect structure for tracking it.
Operator precedence
( Highest
^ -
*, / -
+, - Least
25
Unit III– Linear Structures-List
Balancing parenthesis
One common programming problem is unmatched parenthesis in an algebraic expression. When
parentheses areunmatched, two types of errors can occur:
o Opening parenthesis can be missing. For example, [A+B]/C}.
o Closing parenthesis can be missing. For example, {(A+B)/C.
The steps involved in checking the validity of an arithmetic expression
1. Scan the arithmetic expression from left to right.
2. If an opening parenthesis is encountered, push it onto the stack.
3. If a closing parenthesis is encountered, the stack is examined.
a. If the stack is empty, the closing parenthesis does not have an opening parenthesis. So the
expression isinvalid.
b. If the stack is not empty, pop from the stack and check whether the popped item corresponds to
the closing parenthesis. If a match occurs, continue. Otherwise, the expression is invalid.
4. When the end of the expression is reached, the stack must be empty; otherwise one or more opening
parenthesis does not have corresponding closing parenthesis. So the expression is invalid.
Unit III– Linear Structures-List
Polynomial ADT
Polynomials are expressions containing terms with non-zero coefficients and exponents. Linked list is generally used to
represent and manipulate single variable polynomials. Different operations, such as addition, subtraction, division and
multiplication of polynomials can be performed using linked list. In this representation, each term/element is referred as
a node. Each node contains three fields namely,
1. Coefficient - Holds value of the coefficient of a term.
2. Exponent - Holds exponent value of a term.
3. Link - Holds the address of the next term.
For example,
Unit III– Linear Structures-List
Multi-list
Multi-list is the most complicated applications of linked list. It is useful to maintain student registration in a
university, employee involvement in different projects etc. The student registration contains two reports. The first
report lists the registration for each class (C) and the second report lists, by student, the classes that each student (S) is
registered for. In this implementation, we have combined two lists into one. All lists use a header and are circular.
Circular list saves space but does so at the expense of time.
Polynomial Addition
Type Declaration:
struct node
{
int coeff;
int pow;
struct node *next;
}*poly1=NULL,*poly2=NULL,*poly=NULL;
poly->pow=poly1->pow;
poly->coeff=poly1->coeff;
poly1=poly1->next;
}
while(poly2->next!=NULL)
{
poly->pow=poly2->pow;
poly->coeff=poly2->coeff;
poly2=poly2->next;
}
}
PART A
1. Why do we need ADT for implementing data structures? Or Benefits of ADT.
Code is easier to understand.
Provides modularity and reusability.
Implementations of ADTs can be changed without requiring changes to the program that uses the ADTs.
2. What is an ADT? What are all concerned and not concerned in an ADT? Give example.
ADT is a mathematical specification of the data, a list of operations that can be carried out on that data. It includes
the specification of what it does, but excludes the specification of how it does. Operations on set ADT: Union,
Intersection, Size and Complement.
Examples of ADT: Stack, Queue, List, Trees, Heap, Graph, etc.
6. What is the advantage linked list over arrays?. Mention their relative advantages and disadvantages?
Advantages of Array
o Searching an array for an individual element can be very efficient,
Advantages of Linked List
o Linked list are dynamic data structures - The size is not fixed. They can grow or shrink during the execution of a
program.
o Efficient memory utilization - memory is not pre-allocated. Memory is allocated, whenever it is required and it is
de-allocated whenever it is not needed. Data are stored in non-continuous memory blocks.
o Insertion and deletion of elements are easier and efficient. Provides flexibility. No need to shift elements of a
linked list to make room for a new element or to delete an element.
Disadvantages of Linked List
o More memory - Needs space for pointer (link field).
o Accessing arbitrary element is time consuming. Only sequential search is supported not binary search.
7. What are the advantages of doubly linked list over singly linked list?
In singly linked list, it is difficult to perform traversing the list in reverse. To delete a node, we need find its
predecessor of that node.
9. What are the two important features present in a pointer implementation of linked list?
The two important features present in a pointer implementation of linked list are as follows:
Unit III– Linear Structures-List
1. The data are stored in a collection of structures. Each structure contains data and a pointer to the next
structure.
2. A new structure contains data from the system’s global memory by a call to malloc and released by a call to free.
11. What are the conditions that followed in the array implementation of stack?
Stack overflow - The condition resulting from trying to push an element onto a full stack.
Stack underflow - The condition resulting from trying to pop an element from an empty stack.
PART B
1. Explain the array and linked list implementation of stack.
2. Explain the array and linked list implementation of queue.
3. Explain how stack is applied for evaluating an arithmetic expression.
4. Explain the applications of stack, queue and linked list.
5. Explain polynomial addition using Linked list.