MODULE_1
MODULE_1
DATA STRUCTURES
BASIC TERMINOLOGY
DATA: Values or set of values
DATA ITEM:
• Single unit of values
• That are divided into sub items called
GROUP items
• Collection of data are frequently organized
into hierarchy of fields ,record and files
Entity ,Attribute and entity set
• Entity is something that has certain properties
(attributes) which may be assigned values.
Ex: Employee entity
name age emp_id attributes
Rohit 34 e567
• Entities with similar attributes form an entity
set
Data Structures
• Logical or mathematical model of a particular
organization of data
• The choice of a particular model depends on 2
consideration
1. Rich enough in structure to mirror the actual
relationships of data in the real world
2. Simple enough that one can effectively
process the data when necessary
Classification of Data Structure
1.Primitive Data Structures: These are basic
structures that directly operate on machine-
level instructions.
Examples: Integer, Float, Char, Pointer
2. Non-Primitive Data Structures: These are
more complex structures built using primitive
data types
Arrays
• Linear array is a list of finite number n similar
data elements referenced respectively by a
set of n consecutive numbers.
STUDENT,SALES
Linked List
• A linked list is a linear data structure that
includes a series of connected nodes.
• each node stores the data and the address of
the next node.
• STACK: A Stack, also called a last-in-first-out ( LIFO )
system. It is a linear list in which insertions and
deletions cam take place only at one end called the top.
• QUEUE : A queue, also called a first-in-first out
(FIFO)system, is a linear list in which deletions
can take place only at one end of the list. The
“front” of the list, and insertions can take
place only at the other end of the list, the
“rear” of the tag.
TREES
• Reflects the hierarchical relationship between
various elements
Ex:Employee(e_id,name,address,age,sal)
• GRAPH : Data sometimes contain a
relationship between pairs of elements which
is not necessary hierarchical in nature.
DATA STRUCTURE OPERATIONS
• TRAVERSING : Accessing each record exactly once so
that certain items in the record may be processed.
• .
malloc() Allocates a single block
of requested memory.
calloc() Allocates multiple
blocks of requested
memory
realloc() Reallocates the memory
occupied by malloc() or
calloc() functions
free() Frees the dynamically
allocated memory
malloc()
• used to dynamically allocate a single large block of memory
with the specified size.
• It returns a pointer of type void which can be cast into a
pointer of any form
Syntax :
ptr = (cast-type*) malloc(byte-size)
• doesn't initialize memory at execution time, so it has garbage
value initially.
• It returns NULL if memory is not sufficient.
• ptr holds the address of the first byte in the allocated memory
Example:
ptr = (int*) malloc(3 * sizeof(int));
calloc()
• allocate the specified number of blocks of
memory of the specified type
Syntax
ptr = (cast-type*)calloc(n, element-size);
• n is the no. of elements
• element-size is the size of each element
Example:
Ptr
= (float*) calloc(8, sizeof(float));
#include<stdio.h>
void main()
{
int *ptr, i,n;
printf(“enter value for n\n”);
scanf(“%d”,&n);
ptr=(int*)calloc(n,sizeof(int));
printf(“ enter n values\n”);
for (i=0;i<n;i++)
{
scanf(“%d”,ptr+i);
sum=sum+ *(ptr+i);
}
printf( “ The n values are\n”);
for(i=0;i<n;i++)
printf(“ %d\t”,*(ptr+i));
printf(“ sum=%d\n”,sum);
}
realloc() method
struct structure_name
{
data_type member1;
data_type member2;
.
.
data_type memeberN;
};
Example:
struct person
{
char name[20];
int age;
float salary
};
Declaring structure variable
struct structure_name
{
data_type member1;
data_type member2;
.
.
data_type memeberN;
};
struct structure_name var1,var2,…….,varN;
Accessing members of the structure
a) Tree
b) Array
c) Linked list
d) Queue
Ans: a
Queue data structure works on the
principle of ____________
Ans:c
If malloc() and calloc() are not type casted, the default return
type is _____
(a)void*
(b)void**
(c)int*
(d)char*
Ans: void*
Which of the following functions allocates multiple blocks of memory, each block of
the same size?
(a)malloc()
(b)realloc()
(c)calloc()
(d)free()
Ans: c
What is functionality of realloc() function
then:
• A(x) + B(x) = Σ (ai + bi) xi
Polynomial Representation
}
starta++;
startb++;
break;
case -1:
attach(terms[startb].coef, terms[startb].expon);
startb++;
break;
case 1:
attach(terms[starta].coef, terms[starta].expon);
starta++;
break;
}
}
for (; starta <= finisha; starta++)
{
attach(terms[starta].coef, terms[starta].expon);
}
for (; startb <= finishb; startb++)
{
attach(terms[startb].coef, terms[startb].expon);
}
*finishd = avail - 1;
}
void attach(float coefficient, int exponent)
{
if (avail >=MAX_TERMS)
{
printf( "Too many terms in the polynomial\n");
}
terms[avail].coef = coefficient;
terms[avail++].expon = exponent;
}
Sparse Matrix
• a matrix that contains a few non-zero
elements
Sparse matrix representation
• we can characterize uniquely any element
within a matrix by using the triple
<row,col,value>
• An array of triples is used to represent a
sparse matrix
• Sparsematrix create(maxrows,maxcol)::=
typdef struct
{
int row,
int col,
int value
}term;
term a[max_terms];
Transposing a Matrix
• each element in a[i][j] in the original matrix
becomes element b[j][i] the transpose matrix
• algorithm for transposing a matrix:
Algorithm:
for each row i
take element <i,j,value>and store it as element
<j,i,value>of the transpose;
• if we process the original matrix by the row
indices we will not know exactly where to place
element in the transpose matrix until we have
processed all the elements that precede it
Algorithm
for all elements in column j
take element <i,j,value>and store it as element
<j,i,value> of the transpose
void transpose(term a[], term b[]) {
int n, i, j, currentb;
Output :
Hello, world
2.char *strncat(char *dest, char *src, int
n):concatenate dest and n characters from src; return
result in dest
7 4 3 * 1 5 + / *
A=14
6 2 / 3 - 4 2 * +
A=8
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#define SIZE 50 /* Size of Stack */
case '-':
push(op1 - op2);
break;
• case '*':
push(op1 * op2);
break;
case '/':
push(op1 / op2);
break;
case '%':
push(op1 % op2);
break;
case '^':
push(pow(op1, op2));
break;
default:
printf("Invalid operator\n");
}
}
void push(int elem)
{
s[++top] = elem;
}
int pop()
{
return s[top--];
}
Stacks using dynamic arrays
• The static stack implementation(MAX SIZE)
can be limited because the size of the array is
defined at compile time. If the stack exceeds
this size, it will overflow.
• The solution is to use dynamic memory
allocation. Instead of defining a fixed size,
you dynamically allocate memory for the
stack and resize the array when the stack
is full.
THE QUEUE
• A queue is an ordered list in which all
insertions take place at one end and all
deletions take place at the opposite end.
Given a queue Q = (a0,a1……,an-1)
a0 is FRONT element
an-1 is REAR element
INSERTION –REAR END
DELETION- FRONT END
Types of Queues
1. Simple Queue
2. Circular Queue
3. Priority Queue
4. Dequeue (Double Ended Queue)
circular queue
• A circular queue exhibits similar characteristics
to that of a simple queue, with the additional
property of joining the front end to the rear
end.
• It is also known as the ring buffer.
Double Ended Queue
}
return queue[++ rear]
}
Dequeue (deletion from queue)
element deleteq(int {int front, int rear)
{
if (front == rear)
return queue_empty();
return queue[front++];
}
• only one function executes at any given time,
the function whose stack frame is on top of
the system stack is chosen.
• If this function invokes another function, the
local variables, except those declared static,
and the parameters of the invoking function
are added to its stack frame.
Stacks using dynamic arrays
• The static stack implementation (with a fixed
MAX_STACK_SIZE) can be limited because you
must define the maximum size at compile
time. If the stack exceeds this size, it will
overflow.
• The solution is to use dynamic memory
allocation. Instead of defining a fixed size, you
dynamically allocate memory for the stack and
resize the array when the stack is full.
int *stack;
int capacity;
int top;
void createStack(int initialCapacity)
{
stack = (int *)malloc(initialCapacity *sizeof(int));
capacity = initialCapacity;
top = -1;
}
int isEmpty()
{
return top < 0;
}
int isFull()
{
return top >= capacity - 1;
}
void stackFull()
{
printf("Stack is full. Doubling the stack
capacity...\n");
capacity *= 2;
stack = realloc(stack, capacity * sizeof(int))
}
void push(int key)
{
if (isFull())
{
stackFull();
}
top++;
stack[top] = key
printf("Pushed %d onto the stack.\n", key);
}
MULTIPLE STACKS AND QUEUES
• The representations of a single stack or a
single queue. In both cases, we have seen that
it is possible to obtain efficient sequential
representations.
• Let memory[MEMORY-SIZE] is a single
dimensional array to implement multiple
stacks
• Two-Stack Representation :
• one stack at the beginning (memory[0]),
• The second stack at the end
(memory[MEMORY-SIZE - 1]).
• The stacks grow toward each other
• Multiple Stacks Representation:
Assuming that we have n stacks , to
represent n stacks is to divide the available
memory into n equal (or proportional) segments
based on the expected usage of each stack.
For example,
• if the total memory is MEMORY-SIZE
• we have n stacks,
• we could allocate MEMORY-SIZE/n for each
stack
• Given a memory size of 12 and 3 stacks to
manage
• Let i refers to the stack numbers of the n
stacks
1.boundary[i], 0<=i<=MAX_STACKS
• This array holds the index of the boundary just
before the first element of stack i
• Points to the position immediately to the left
of the bottom element of stack i
• top[i]: 0<=i<=MAX_STACKS
This array holds the current top index of stack i,
which points to the last (topmost) element of
that stack.
Relevant Declaration
#define MEMORY_SIZE 100
#define MAX_STACKS 10
int memory[MEMORY_SIZE];
int top[MAX_STACKS];
int boundary[MAX_STACKS ];
int n;
• To divide the array into roughly equal
segments we use the following code:
top[0] = boundary[0]; = -1;
for (int j = 1; j < n; j++)
top[j]=boundary[j]=(MEMORY_SIZE/n)*j-1;
boundary[n]= MEMORY_SIZE-1
Push function
void push(int i, int item)
{
if (top[i] == boundary[i+1])
stackFull(i);
memory[++top[i]] = item;
}
Delete an item from i th stack
int pop(int i)
{
if (top[i] == boundary[i])
stack_empty(i);
return memory[top[i]--];
}
Circular Queues using dynamic arrays
• start with an array of a certain capacity, say 4.
In the example, the queue is shown with 4
elements, and the rear index is just before the
front index due to the circular nature
• you add an element, the rear index is
incremented as rear = (rear + 1) % capacity;.
This operation ensures that the index wraps
around if it reaches the end of the array
(circular behavior).
• If the rear index becomes equal to the front
index, the queue is full, and need to increase
the size of the array using realloc
• Doubling the Capacity:
• When the queue is full, the capacity is
doubled by creating a new array, newQueue,
with double the size of the old one.
Rearranging Elements:
• The queue's elements are rearranged in the new
array to maintain the correct order:
• The second segment of the queue (elements from
queue[front + 1] to queue[capacity-1]) is copied to the
beginning of the new array.
• The first segment of the queue (elements from
queue[0] to queue[rear]) is copied to the end of the
new array.
• This ensures that the circular order is maintained
even after the array's capacity has been increased.
void queueFull()
{
int *newQueue;
newqueue=(int*) malloc(2 * capacity *sizeof(*queue));
int start = (front + 1) % capacity;
if (start < 2)
copy(queue + start, queue + start + capacity,
newQueue);
else
{