Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
11 views103 pages

C++ Program

Uploaded by

Darshan B R
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views103 pages

C++ Program

Uploaded by

Darshan B R
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 103

E-BOOK

DATA-STRUCTURES AND
ALGORITHMS USING C

Data Structures and Algorithms Using C


Index
Sessions-Index Content Covered Page no.
Session - 01 Pointers- Introduction to Pointers 3
What Is a Pointer? 3
Pointer Declaration 3

Session – 02 Advanced Pointers 11


t
Relation between Pointers and Arrays, 11
Pointer Arithmetic Operation
NULL Pointer 19
Pointer to a constant 20
Constant pointer 21
Pointer to Array & Array of Pointers 24
Function pointer & Void pointer 27

Session- 03 Structures 29
Declaration of Structure 29
Structure Variable 30
Memory Allocation Concept 30
Accessing Structure Members 30
Passing Structure to Function 32
(by Value / Address)
Array of Structure- Nested Structure 34

Session -04 Structures (Advanced)- 39


Self-referential Structure 39
Pointer to structure 40
Nested Structure- 41
Union 42
Enum 43
Typedef 44

Session - 05 Introduction to Data Structure 46


Stack- Applications of Stack (static) 48

Session - 06 Dynamic Stack 54

Data Structures and Algorithms Using C


Session-08 Command Line Arguments 73
Memory leaks with Valgrind 74
Converting a String to an integer using atoi() 75

Session - 09 Queue- Applications of Queue 77


static and dynamic queue 82

Session -10 Circular Queue 86

Session - 11 Linked List- Introduction to Linked List 90

Session - 12 SLL Implementation- Create and Display 91

Session - 13 SLL Implementation 93


Insert at the Front End 93
Delete (Front, End)- Specific Position 95
Sorting the SLL 96

Session-14 Double-Linked List 99


Traversal Front-Rear 100

Session - 15 File I/O- kindly refer C material


Text and Binary Files-
Opening, Closing Files-
Character I/O - fgetc, fputc

Session -16 File I/O (Continued)-


String I/O - fgets, fputs
String I/O - sscanf, sprint
Block I/O - fread and fwrite
Random Access - fseek, ftell, rewind

Session-17 Git Basics- GitHub- init, add, commit, log

Session-18 Branching and Merging- Pushing to GitHub

Session-19 Problem Solving using HackerRank

Data Structures and Algorithms Using C


SESSION-1
POINTERS

INTRODUCTION TO POINTERS
Pointers are powerful features of C and C++ programming. Before we learn
pointers, let's learn about addresses in C programming.

Address in C
If you have a variable var in your program, &var will give you its address
in the memory. We have used address numerous times while using
the scanf() function.

Here, the value entered by the user is stored in the address of var variable.
Let's take a working example.

Output:
Note: You will probably get a different address when you run the above
code

What is pointer?
A pointer is a variable that stores the memory address of another variable.
Instead of holding a direct value, a pointer holds an address pointing to a
location in memory.

POINTER DECLARATION AND INITIALIZATION


A pointer variable must be declared before use:
Pointer Syntax:
data_type *pointer_name;

Data Structures and Algorithms Using C


Example:

Here, we have declared a pointer p of int type. You can also declare
pointers in these ways.

Here, we have declared a pointer p1 and p2.

Assigning addresses to Pointers


Let's take an example.

Here, 5 is assigned to the c variable. And the address of c is assigned to


the pc pointer.

Get Value of Thing Pointed by Pointers


To get the value of the thing pointed by the pointers, we use the * operator. For
example:

Data Structures and Algorithms Using C


• Here, the address of c is assigned to the pc pointer. To get the value
stored in that address, we used *pc.
• Note: In the above example, pc is a pointer, not *pc. You cannot and
should not do something like *pc = &c;
• By the way, * is called the dereference operator (when working with
pointers). It operates on a pointer and gives the value stored in that
pointer.

Changing Value Pointed by Pointers


Let's take an example.

We have assigned the address of c to the pc pointer. Then, we changed the value
of c to 1. Since pc and the address of c is the same, *pc gives us 1. Let's take
another example.

We have assigned the address of c to the pc pointer. Then, we changed *pc to 1


using *pc = 1;. Since pc and the address of c is the same, c will be equal to 1.

Let's take one more example.

Data Structures and Algorithms Using C


✓ Initially, the address of c is assigned to the pc pointer using pc = &c;.
Since c is 5, *pc gives us 5. Then, the address of d is assigned to
the pc pointer using pc = &d;. Since d is -15, *pc gives us -15.

✓ The format specifier %p is used in C (and C-like languages) to print a


pointer address—that is, the memory address that a pointer variable
holds.
Here's a breakdown:
• %p stands for "pointer".
• When you use printf("%p", ptr);, it prints the address stored in the pointer
variable ptr.
• The output is typically in hexadecimal format, often prefixed with 0x.
Size: 8 bytes
• On a 64-bit system, pointers are 8 bytes (64 bits) in size.
• That means any pointer, whether it's pointing to an int, char, float, or a
custom structure, occupies 8 bytes in memory.
• This size allows it to hold any address within a 64-bit address spa

Data Structures and Algorithms Using C


Example: Working of Pointers
Let's take a working example.

Explanation of the program


1. int* pc, c;

Here, a pointer pc and a normal variable c, both of type int, is


created. Since pc and c are not initialized at initially,
pointer pc points to either no address or a random address. And,

Data Structures and Algorithms Using C


variable c has an address but contains random garbage value.

2. c = 22;

This will assign 22 to the variable c. That is, 22 is stored in the


memory location of variable c.

3. pc = &c;

This assigns the address of variable c to the pointer pc.

4. c = 11;

This assign 11 to variable c.

5. *pc = 2;

This changes the value at the memory location pointed by the


pointer pc to

Memory Representation:
int num = 10;
int *ptr = #

Data Structures and Algorithms Using C


Example Program:

Logic Breakdown:
• num is an integer variable initialized with 10.
• ptr is a pointer that stores the address of num.

The program prints:


▪ The value of num.
▪ The memory address of num.
▪ The memory address stored in ptr.
▪ The value at the memory location stored in ptr
(dereferencing).
Common mistakes when working with pointers
Suppose you want pointer pc to point to the address of c. Then,

Data Structures and Algorithms Using C


Here's an example of pointer syntax beginners often find confusing.

Why didn't we get an error when using int *p = &c;?


It's because

is equivalent to

In both cases, we are creating a pointer p (not *p) and assigning &c to it.
To avoid this confusion, we can use the statement like this:

Data Structures and Algorithms Using C


SESSION-2
ADVANCE POINTERS

Relationship Between Arrays and Pointers


An array is a block of sequential data. Let's write a program to print the addresses
of the array elements.

• There is a difference of 4 bytes between two consecutive elements of the


array x. It is because the size of int is 4 bytes (on our compiler).
• Notice that, the address of &x[0] and x is the same. It's because the
variable name x points to the first element of the array.

Data Structures and Algorithms Using C


Relation between Arrays and Pointers
From the above example, it is clear that &x[0] is equivalent to x. And, x[0] is
equivalent to *x.

Similarly,
• &x[1] is equivalent to x+1 and x[1] is equivalent to *(x+1).
• &x[2] is equivalent to x+2 and x[2] is equivalent to *(x+2).
• ...
• Basically, &x[i] is equivalent to x+i and x[i] is equivalent to *(x+i).

Example 1: Pointers and Arrays

When you run the program, the output will be:

Data Structures and Algorithms Using C


Here, we have declared an array x of 6 elements. To access elements of the array,
we have used pointers. In most contexts, array names decay to pointers. In
simple words, array names are converted to pointers. That's the reason why you
can use pointers to access elements of arrays. However, you should remember
that pointers and arrays are not the same. There are a few cases where array
names don't decay to pointers.

Example 2: Arrays and Pointers

In this example, &x[2], the address of the third element, is assigned to


the ptr pointer. Hence, 3 was displayed when we printed *ptr.
And, printing *(ptr+1) gives us the fourth element. Similarly, printing *(ptr-
1) gives us the second element.

C Pass Addresses and Pointers


In C programming, it is also possible to pass addresses as arguments to functions.
To accept these addresses in the function definition, we can use pointers. It's
because pointers are used to store addresses. Let's take an example:

Data Structures and Algorithms Using C


Example: Pass Addresses to Functions

The addresses of num1 and num2 are passed to the swap() function
using swap(&num1, &num2);. Pointers n1 and n2 accept these arguments in
the function definition. When *n1 and *n2 are changed inside
the swap() function, num1 and num2 inside the main() function are also
changed.
Inside the swap() function, *n1 and *n2 swapped. Hence, num1 and num2 are
also swapped. Notice that swap() is not returning anything; its return type
is void.

Example 2: Passing Pointers to Functions

Data Structures and Algorithms Using C


Here, the value stored at p, *p, is 10 initially. We then passed the pointer p to
the addOne() function. The ptr pointer gets this address in the addOne()
function.
Inside the function, we increased the value stored at ptr by 1 using (*ptr)++;.
Since ptr and p pointers both have the same address, *p inside main() is also 11.

Pointer Arithmetic
What is Pointer Arithmetic?
Pointer arithmetic refers to performing arithmetic operations (like +, -, ++, --)
on pointers. This is especially useful when working with arrays or dynamic
memory.
Because pointers "point to" memory addresses, arithmetic operations on them
manipulate the memory address they store, taking into account the size of the
data type they point to.
Basic Pointer Arithmetic Operations
1. Increment: ptr++
What it does: Moves the pointer to the next element in memory. How: It
increases the address stored in the pointer by sizeof(data_type).

Example:

If sizeof(int) is 4 bytes, ptr++ moves the pointer by 4 bytes.

2. Decrement: ptr--
• What it does: Moves the pointer to the previous element in
memory.

Example:

Data Structures and Algorithms Using C


Again, the pointer moves back by sizeof(data_type) bytes.

3. Addition: ptr + n
• What it does: Moves the pointer forward by n elements.
• Note: This doesn't change the original pointer unless assigned.

Example:

4. Subtraction: ptr - n
• What it does: Moves the pointer backward by n elements.

Example:

Important Notes
• Pointer arithmetic is type-aware:
▪ If ptr is of type int *, ptr + 1 actually adds sizeof(int) to the
address.
▪ If it's a char *, then ptr + 1 adds just 1 byte.

o You can also subtract two pointers pointing into the same array:

Data Structures and Algorithms Using C


Out-of-bound pointer arithmetic (e.g., going beyond an array)
leads to undefined behaviour.

Visual Example:

Arithmetic Operations on Pointers

Data Structures and Algorithms Using C


• Pointer arithmetic includes: Increment (ptr++) – Moves the pointer
to the next memorylocation.Decrement (ptr--) – Moves the
pointer to the previous memory location.
• Addition (ptr + n) – Moves the pointer forward by n locations.
Subtraction (ptr - n) – Moves the pointer backward by n locations.

Types of Pointers in C
Depending on the parameters, pointers can be divided into a wide variety of
types. The following types of pointers are based on the type of variable that is
kept in the memory location that the pointer is pointing to.

Integer Pointers
The memory location of an integer variable is stored in an integer
pointer.

Syntax

Example of Integer Pointers in C

Data Structures and Algorithms Using C


NULL POINTER
A NULL pointer is a special pointer that does not point to any valid
memory location. It is typically used to indicate that a pointer is not
assigned to a valid object or memory.

Purpose of NULL Pointers


• Indicates an Uninitialized Pointer: Helps prevent accidental access
to garbage memory.
• Used in Error Handling: Functions often return NULL to indicate
failure.

Declaring a NULL Pointer


int *ptr = NULL; // ptr is a NULL pointer
PROGRAM: NULL Pointer Usage

Output:

Logic Breakdown:
• Declare a pointer ptr and initialize it to NULL.
• Use an if condition to check if the pointer is NULL.
• Print a message indicating whether the pointer is NULL or not.

Data Structures and Algorithms Using C


Pointer to Constant

A pointer to a constant in C is a pointer that points to a constant value,


meaning you cannot modify the value at the memory location the pointer is
pointing to through that pointer.

• You can change the pointer to point to another memory location.


• But the value at the location cannot be changed via the pointer.

Syntax

• A const keyword before the data type means the value being pointed to
is constant
• You can read the value using the pointer
• You cannot write or modify the value using that pointer.
A C program to demonstrate a pointer to a constant.

Data Structures and Algorithms Using C


Explanation

1. Declaration:
const int *ptr means ptr is a pointer to a const int, so the value it points
to is protected from modification.
2. Pointer Initialization:
ptr = &value sets the pointer to address of value, but *ptr = 100; would
result in a compile-time error.
3. Accessing Value:
*ptr is used to read the value at the pointed address — reading is
allowed.
4. Pointer Reassignment:
You can safely reassign the pointer to point to another variable (ptr =
&new_value).
5. Ensured Const Safety:
This mechanism ensures that functions or parts of code that get such a
pointer cannot accidentally modify the data.

CONSTANT POINTER
A constant pointer is a pointer whose value (i.e., the memory address it
holds) cannot be changed after initialization. Once a constant pointer is
assigned an address, it must always point to the same memory location.

Syntax:

Here, ptr is a constant pointer to an integer, meaning it must always


point to num1. However, we can modify the value stored at num1 via
*ptr.

Data Structures and Algorithms Using C


Example Program:

Key Points:
▪ Cannot change the address stored in ptr.
▪ Can change the value at the address using *ptr.
▪ ptr = &num2; results in a compilation error.

Pointer to Pointer
A pointer to a pointer, also called a double pointer, is a variable that
stores the address of another pointer. This allows for multiple levels of
indirection and is commonly used in complex data structures, dynamic
memory management, and function arguments that modify pointers.

Data Structures and Algorithms Using C


How It Works
• x contains the value 100
• ptr contains the address of x
• pptr contains the address of ptr

Accessing Values:

Use Cases:
• Dynamic memory allocation for multi-dimensional arrays
• Modifying a pointer inside a function
• Parsing command-line arguments (char **argv)
• Working with linked lists and trees
Wild Pointer
A wild pointer is a pointer that has been declared but not initialized, and
thus it points to an unknown or random memory location. Dereferencing
such a pointer can lead to unpredictable results and may cause a
program to crash.

Data Structures and Algorithms Using C


Issues Caused by Wild Pointers:
• Program crashes
• Memory corruption
• Security vulnerabilities
• Segmentation faults
Best Practices to Avoid Wild Pointers:
• Always initialize pointers:
int *ptr = NULL;

• Only dereference after proper assignment


• Use static analyzers to detect uninitialized pointers
Pointer to an Array
A pointer to an array is a pointer that holds the address of an entire array
rather than just a single element. This allows efficient traversal and
manipulation of the array using pointer arithmetic.
Key Concept:
• When an array is declared, its name acts as a pointer to the first
element.
• However, a pointer to an array explicitly stores the address of the
whole array.

Syntax:

Here, ptr is a pointer to an array of size elements.

Example Program: Pointer to an Array

Data Structures and Algorithms Using C


Output:

Logic Breakdown:
• Declaring an Array
• int arr[5] = {10, 20, 30, 40, 50};
• Creates an array of 5 integers.
• Declaring a Pointer to an Array
• int (*ptr)[5] = &arr;
• ptr stores the address of the entire array, not just the first
element.
• Accessing Array Elements
• Using (*ptr)[index], we can retrieve elements from the
array.

Array of Pointers
An array of pointers is a collection where each element is a pointer. This
allows you to store references to multiple variables, arrays, or even
strings, providing greater flexibility in memory management.

Syntax:

Accessing Data:

Array of Strings Example:

Data Structures and Algorithms Using C


Use Cases:
• Arrays of strings or variable-length arrays
• Jagged (non-uniform) multi-dimensional arrays
• Dynamic data structures like lists of arrays or arrays of objects

Array Pointer
The initial element of an array may be referenced by array pointers.

Syntax

Example of Array Pointer in C

Data Structures and Algorithms Using C


Function Pointer in C
A function pointer is a pointer that stores the address of a function and
can be used to call that function indirectly.

Enables functions to be passed as arguments, selected at runtime, or


implemented for callback mechanisms.

Syntax

Example

• You define a pointer with the same signature as the function.


• Assign the function name (without parentheses) to the pointer.
• Call the function using either (*pointer)(args) or pointer(args).

VOID POINTER
A void pointer (also known as a generic pointer) is a pointer that has no
specific data type associated with it. It can hold the address of any data
type, making it flexible for general-purpose programming.

Declaration and Initialization


void *ptr; // Declaring a void pointer
int num = 10;
ptr = # // Assigning address of an integer variable
Here, ptr can store the address of num, but since it is a void pointer,
dereferencing it requires typecasting.

Data Structures and Algorithms Using C


Example Program: Using Void Pointers

Logic Breakdown:
1. Declare a void *ptr that can point to any data type.
2. Assign different variables (int, float, char) to ptr.
3. Before dereferencing, explicitly typecast ptr to the correct data
type.

Data Structures and Algorithms Using C


SESSION – 3
STRUCTURES
Introduction to Structures, Declaring, Initializing, and Accessing
Structures
Structures (often called structs) are user-defined data types in C/C++ (and other
languages like Rust, Go, etc.) that allow grouping variables of different data
types under one name.

A structure in C is a collection of variables of different data types grouped


together under a single name. Each item in a structure is called a member or
field.

Why Use Structures?


When you want to store and manage multiple related variables (like student
details: name, age, roll number), structures help keep them organized and
manageable.
• To represent real-world entities, e.g., an employee’s name, age, and salary.
• To store data of different types together.
• To organize complex data efficiently in a program.

Syntax of Structure Definition:

• struct: Keyword used to define a structure.


• structure_name: Name given to the structure.
• member1, member2, ...: Members (variables) of the structure, each having
a specific data type.

Example:

Data Structures and Algorithms Using C


Here, a derived type struct Person is defined. Now, you can create variables of
this type.

Struct Variables
When a struct type is declared, no storage or memory is allocated. To allocate
memory of a given structure type and work with it, we need to create
variables.
Here's how we create structure variables:

Another way of creating a struct variable is:

In both cases, person1 and person2 are struct Person variables p[] is a struct
Person array of size 20.

Access Members of a Structure


There are two types of operators used for accessing members of a structure.
. - Member operator
-> - Structure pointer operator
Suppose you want to access the salary of person2. Here's how you can do it.

Data Structures and Algorithms Using C


Example:

In this program, we have created a struct named Person. We have also created
a variable of Person named person1. In main(), we have assigned values to the
variables defined in Person for the person1 object.

Data Structures and Algorithms Using C


Notice that we have used strcpy() function to assign the value to
person1.name.

This is because the name is a char array (C-string) and we cannot use the
assignment operator = with it after we have declared the string.
Finally, we printed the data of person1.

Example: Defining and Using a Structure

Logic Breakdown:
1. Structure Definition: struct Student defines a structure with three
members: name (string), age (integer), and marks (float).
2. Structure Variable: student1 is declared as a variable of type struct Student.
3. Accessing Members: We access the members of the structure using the dot
(.) operator.

Passing Structure to Function (by Value / Address)


In C, a structure (group of related variables) can be passed to a function either:
✓ By value: a copy of the structure is passed.
✓ By address (pointer): the original structure's address is passed, allowing
the function to modify it directly.

Syntax

Data Structures and Algorithms Using C


Value passing sends a copy;
address passing gives direct access to the original structure.

Working:
✓ When passing by value, the function works on a separate copy;
✓ The original data is not modified.
✓ When passing by address, the function uses a pointer, so any changes
reflect on the original structure.
✓ Passing by address is memory-efficient and allows modification.
✓ Used commonly in real-world programs like student records, employee
details, etc.

Example Program

Output:

Data Structures and Algorithms Using C


Key Logic Points of the Program:
✓ struct Student holds student information: roll number and name.
✓ displayByValue() gets a copy of the structure; cannot modify the original.
✓ displayByAddress() receives a pointer, using -> to access members.
✓ In the main(), we call both versions to show the difference.
✓ Passing by address is useful for modifying structure values inside
functions.

Nested Structures
A nested structure is a structure that contains another structure as a member.
This is useful when you need to model hierarchical or complex data.

Syntax of Nested Structures:

Example: Nested Structure

Data Structures and Algorithms Using C


Logic Breakdown:
1. Nested Structure: The Employee structure contains another structure
Address as a member.
2. Accessing Nested Members: The dot operator is used twice to access
members of the nested structure: emp.addr.street.

Array of Structures
An array of structures allows you to store multiple instances of a structure in an
array.

Syntax of Array of Structures:

Example: Array of Structures

Data Structures and Algorithms Using C


OUTPUT:

Logic Breakdown:
1. Array of Structures: An array of students of type struct Student is created
with 3 elements.
2. Accessing Array Members: A loop is used to iterate through each student,
and the dot operator is used to access individual members of each
structure.

Array of Structure
An array having a structure as its base type is known as an array of structure. To
create an array of structure, first structure is declared, and then an array of
structure is declared just like an ordinary array.

Example: Array of Structure


If the structure is declared like:

Then an array of structures can be created like:

Data Structures and Algorithms Using C


Explanation
In this example, the first structure employee is declared, then the array of
structures is created using a new type, i.e., struct employee. Using the above
array of structure, 10 sets of employee records can be stored and manipulated.
A similar array of structure can also be declared like:

Accessing Elements from an Array of Structure


To access any structure, index is used. For example, to read the emp_id of the
first structure, we use scanf(“%d”, emp[0].emp_id); as we know in C array
indexing starts from 0.

Similar array of structure can also be declared like:

C program to read records of three different students in structure having


member name, roll and marks, and displaying it.

Data Structures and Algorithms Using C


Data Structures and Algorithms Using C
Session 4:

Structures (Advanced)

Self-Referential Structure
Definition: A self-referential structure is a structure that includes a member
which is a pointer to the same structure type. This is essential for implementing
dynamic data structures like linked lists, trees, and graphs.
Syntax:

How it Works: The next pointer in each structure instance allows it to reference
another node of the same type, forming a chain of structures that can grow or
shrink during runtime.
Working: Enables creation of flexible and expandable data structures by
dynamically linking elements together.
Program:

Data Structures and Algorithms Using C


Output

Logic Points:
1. A structure Node contains data and pointer to another Node.
2. n1 is linked to n2 through the next pointer.
3. This structure setup enables building dynamic lists.
4. Accessing next node's data via n1.next->data.
5. Demonstrates basis of linked list functionality.

Pointer to Structure
Definition: A pointer to structure is a pointer variable that stores the address of
a structure variable. It allows access and manipulation of structure members
indirectly.
Syntax:

How it Works: The pointer holds the memory address of a structure variable.
Using the -> operator, we can access or modify the structure's members via the
pointer.
Working: Useful when passing structures to functions, working with arrays of
structures, or managing dynamic memory.
Program:

Data Structures and Algorithms Using C


Output:

Logic Points:
1. Structure variable s initialized with 100.
2. Pointer ptr holds address of structure s.
3. Member x accessed using ptr->x.
4. Demonstrates use of pointer to access structure fields.
5. Encourages memory-efficient manipulation of data.

Nested Structure
Definition: A nested structure is a structure declared inside another structure.
It groups related data hierarchically.
Syntax:

How it Works: The inner structure is declared within the outer structure and
can be accessed using the outer structure variable.

Data Structures and Algorithms Using C


Working: Helps in logically grouping and managing complex related
information under a single unit.
Program:

Output:
Logic Points:
1. Outer structure contains Inner structure.
2. Inner structure member initialized using {}.
3. Dot operator is used for accessing inner structure members.
4. Enables representation of complex entities (e.g., employee with
address).
5. Makes data encapsulation more logical and readable.
Union
Definition: A union is a user-defined data type that allows storing different data
types in the same memory location. Only one member can hold a value at any
given time.
Syntax:

Data Structures and Algorithms Using C


How it Works: All members of a union share the same memory space. The last
value assigned to a member will overwrite previous values.
Working: Saves memory when multiple variables are not used simultaneously.
Program:

Output :
Logic Points:
1. u.a and u.b share same memory location.
2. Assigning b overwrites a.
3. Saves memory in embedded or constrained systems.
4. Accessing wrong member causes unexpected results.
5. Efficient but requires careful handling.
Enum
Definition: An enum (enumeration) assigns names to a set of integral
constants, improving code readability.
Syntax:

Data Structures and Algorithms Using C


How it Works: The Compiler automatically assigns values starting from 0 unless
specified. Enum values behave like constants.
Working: Used in switch-case, menu selections, and states.
Program:

Output:

Logic Points:
1. Enum assigns 0-based index to days.
2. Wed corresponds to value 3.
3. Improves clarity in code logic.
4. Reduces errors by avoiding magic numbers.
5. Useful in state machines and UI options.

Typedef
Definition: typedef is used to create an alias (new name) for an existing data
type to make code more readable.
Syntax:

How it Works: The new name can then be used to declare variables instead of
the original type.
Data Structures and Algorithms Using C
Working: Reduces typing complexity, especially with structs or long type
names.
Program:

Output:
Logic Points:
1. typedef simplifies type declaration.
2. uint is a user-defined alias for unsigned int.
3. Helps in consistent naming across the project.
4. Used with structs: typedef struct { ... } StructName;
5. Enhances maintainability and abstraction.

Data Structures and Algorithms Using C


SESSION-5
Introduction To DataStructures
Definition:
A data structure is a specialized format for organizing and storing data.
General data structure types include the array, the file, the record, the
table, the tree, and so on.

Classifications (Primitive & Non Primitive)

Figure: Classification of classic data structures


Primitive Data Structures
✓ Primitive Data Structures are the basic data structures that directly
operate upon the machine instructions.
✓ They have different representations on different computers.
Integers, floating point numbers, Character constants, String
constants, and Pointers come under this category.
Non-primitive Data Structures
✓ Non-primitive data structures are more complicated data structures
and are derived from primitive data structures.
✓ They emphasize on grouping similar or different data items with a
relationship between each data item.
✓ Arrays, Lists, and Files come under this category.
Linear Data Structure:
✓ A data structure is said to be linear if its elements form a sequence.
✓ The elements of a linear data structure are represented by means of
Data Structures and Algorithms Using C
sequential memory locations.
✓ The other way is to have the linear relationship between the elements
represented by means of pointers or links.
Example: Array and Linked List.
Non-linear data structure:
✓ A data structure is said to be non-linear if its elements show a
hierarchical relationship between each other.
✓ All elements assign the memory a random form, and you can fetch data
elements through a random-access process.
Example: Trees and Graphs.
Data Structure Operations
Data are processed by means of certain operations that appear in the data
structure. Data has a situation on depends largely on the frequency with
which specific operations are performed. This section introduces the
reader to some of the most frequently used of these operations.
➢ Traversing: Accessing each record exactly once so that certain items in the
record may be processed.
➢ Searching: Finding the location of a particular record with a given key
value, or finding the location of all records that satisfy one or more
conditions.
➢ Inserting: Adding a new record to the structure.
➢ Deleting: Removing the record from the structure.
➢ Sorting: Managing the data or records in some logical order (Ascending or
descending order).
➢ Merging: Combining the records in two different sorted files into a single
sorted file.

Data Structures and Algorithms Using C


Stacks
Definition: A stack is an ordered collection of items into which new items
may be inserted and from which items may be deleted at one end, called
the top of the stack.
Hence, a stack is called a LIFO (Last-In-First-Out) data structure, as the
element that was inserted last is the first one to be taken out.
Stack Operations
✓ A stack supports two basic operations: push and pop.
✓ The push operation adds an element to the top of the stack, and the
pop operation removes the element from the top of the stack.
Push Operation
✓ The push operation is used to insert an element into the stack.
✓ The new element is added at the topmost position of the stack.
✓ However, before inserting the value, we must first check if TOP=MAX-
1, if the stack is full, and no more insertions can be done.
✓ If an attempt is made to insert a value in a stack that is already full,
an OVERFLOW message is printed.
Example:

✓ To insert an element with value 6, we first check if TOP = MAX–1.


✓ If the condition is false, then we increment the value of TOP and
store the new element at the position given by stack [TOP].
The figure shows the updated stack.

Algorithm:
Step 1: We first check for the OVERFLOW condition.
Step 2: TOP is incremented so that it points to the next location in the
array it points to the next location in the array.
Step 3: The value is stored in the stack at the location pointed by TOP.

Data Structures and Algorithms Using C


Pop Operation
✓ The pop operation is used to delete the topmost element from the
stack. However, before deleting the value, we must first check if
✓ TOP=NULL because if that is the case, then it means the stack is
empty and no more deletions can be done.
✓ If an attempt is made to delete a value from a stack that is already
empty, an UNDERFLOW message is printed.
Example:
Consider the stack given

To delete the topmost element, we first check if TOP=NULL. If the condition


is false, then we decrement the value pointed by TOP.

Algorithm:
Step 1: We first check for the UNDERFLOW condition.
Step 2: The value of the location in the stack pointed by TOP is stored in
VAL.
Step 3: TOP is decremente

Data Structures and Algorithms Using C


Array Representation of Stack
In the computer‘s memory, stacks can be represented as a linear array.
Every stack has a variable called TOP associated with it, which is used to

store the address of the topmost element of the stack.

It is this position where the element will be added to or deleted from. There
is another variable called MAX, which is used to store the maximum
number of elements that the stack can hold.
If TOP = NULL, then it indicates that the stack is empty and if TOP = MAX–
1, then the stack is full. (You must be wondering why we have written
MAX–1. It is because array indices start from 0.)
Example

Data Structures and Algorithms Using C


ADTStack is
objects: a finite ordered list with zero or more elements.
functions: for all stack∈Stack, item∈element, maxStackSize∈ positive
integer

Operation Pseudocode
Stack Create an empty stack whose maximum size is maxStackSize
CreateS(maxStackSize)
Boolean IsFull(stack, if (number of elements in stack = = maxStackSize)
maxStackSize) return TRUE
else
return FALSE
Stack Push(stack, item) if (IsFull(stack, maxStackSize))
return "Stack Full"
else
insert item into top of stack
return stack
Boolean IsEmpty(stack) if (number of elements in stack == 0)
return TRUE
else
return FALSE
Element Pop(stack) if (IsEmpty(stack))
return "Stack Empty"
else
remove and return element at top of stack

Program for stack implementation using an array

Data Structures and Algorithms Using C


Data Structures and Algorithms Using C
Data Structures and Algorithms Using C
Output:

Dynamic stack
✓ A dynamic stack using arrays allows the stack to grow as needed.
✓ It uses dynamic memory allocation to allocate or expand the array during
runtime, avoiding fixed size limitations.

Syntax

Data Structures and Algorithms Using C


Dynamically allocates memory for the stack of given capacity.

3. Working
✓ The stack is implemented using a dynamically allocated array.
✓ Top tracks the index of the last inserted element.
✓ Push checks if capacity is reached and uses realloc() to grow the array.
✓ Pop removes and returns the element at the top.
✓ Allows flexible and efficient memory usage.

C Program: Dynamic Stack Using Arrays

Data Structures and Algorithms Using C


Output:
Main Logic Points
✓ Memory is dynamically allocated and resized using realloc().
✓ Top points to the last inserted element.
✓ If capacity is full, double the array size.
✓ Popping simply decrements the top.
✓ display() traverses from 0 to the top.

Application of the stack

➢ Conversion of Expression
➢ Evaluation of expression
➢ Recursion
Conversion of Expression
There are three different conversions are infix, postfix and prefix
expressions.
• Expression is a collection of operands and operators
• An expression can be represented in three different ways.
➢ Infix expression: operators are between the two operands.
Example a+b

Data Structures and Algorithms Using C


➢ Prefix expression: operators are present before the operands.
Example +ab
➢ Postfix expression: operators are present after the operands.
Example ab+
Example
Infix expression Postfix expression Prefix expression

A+B AB+ +AB

(A+B)*C AB+C* +AB*C

(A-B)*(C+D) AB-CD+* *-AB+CD

(A + B) / (C + D) – (D * E) AB+CD+/DE*- -/+AB+CD*DE

To convert an expression from infix to prefix or postfix, we follow the rules of


precedence.
• Precedence: The order in which different operators are evaluated in
an expression is called precedence
• Associativity: The order in which operators of the same precedence are
evaluated in an expression is called Associativity.
The operators are listed in the order of higher precedence down to lower
precedence

Operator Associativity
--,++ left-to-right
Unary operators ,!,-,+, &, *,sizeof Right to left
*,/,% left-to-right
+,- left-to-right
Converting an expression from infix to postfix
The operands in the infix and the postfix expressions are in the same order.
With respect to operators , the precedence of operators plays an important
role in converting an infix expression to a postfix expression. We make use of
the stack to insert the operators according to their precedence.
The following operations are performed to convert an infix expression to
postfix.
Scan the symbol character by character
• If the symbol is an operand, place it in the postfix string

Data Structures and Algorithms Using C


• If the symbol is an opening parenthesis, push it onto the stack
• If the symbol is a closing parenthesis, pop the contents of the
stack until we see an opening parenthesis and place it in the
postfix string. The opening parenthesis and the closing
parenthesis are not placed in the postfix string.
• If the symbol is an operator and if the precedence of the input
symbol is more than the precedence of the symbol on top of the
stack, then the operator is pushed onto the stack. If the
precedence of the input symbol is less than the symbol on top of
the stack, we pop each such operators and place it in the postfix
string

Algorithm Polish(Q,P)
Suppose Q is an arithmetic expression written in infix notation. This
algorithm finds the equivalent Postfix expression P.
1. Push # onto STACK to identify the end of the stack
2. Scan Q from Left to right and repeat steps 3 to 6 for each character of
Q until the end of the string
3. If an operand is encountered, add it to P
4. If a left parenthesis is encountered, push it to onto the STACK.
5. If an operator is encountered, then
a. Repeatedly pop each operator that has equal or higher
precedence and add to P.
b. Add to Stack
6. If a right Parenthesis is encountered, then
a. Repeatedly pop from the stack and add to P each operator on top of
the stack until a left parenthesis is encountered.
b. Remove the left Parenthesis.[ do not add left parenthesis to stack]
[End of If Structure.]
[End of Step 2 loop]

7. Repeatedly pop the stack until it is empty and add to P


8. Exit

Data Structures and Algorithms Using C


Example: Translation of the infix string a*(b+c)*d to postfix

Infix Stack Postfix


Token [0] [1] [2] [3]
#
a # a
* # * a
( # * ( a
b # * ( ab
+ # * ( + ab
c # * ( + abc
) # * abc+
* # * abc+*
d # * abc+*d
Eos(\0) # abc+*d*

2 (A + B) / (C + D) – (D * E))
INFIX STACK POSTFIX
TOKEN [0] [1] [2] [3]
#
( (
A A
+ # ( +
B # ( + B
) # AB+
/ # /
( # / ( AB+
C # / ( AB+C
+ # / ( +
D # / ( AB+CD
) AB+CD+
- # - AB+CD+
/
( # - (
D # - ( AB+CD+
/D
* # - ( * AB+CD+
/D
E # - ( * AB+CD+
/DE
) AB+CD+
/DE*
AB+CD+
/DE*-

Data Structures and Algorithms Using C


Evaluating a postfix expression
Given an algebraic expression written in infix notation, the computer first
converts the expression into the equivalent postfix notation and then
evaluates the postfix expression. Both these tasks—converting the infix
notation into postfix notation and evaluating the postfix expression—make
extensive use of stacks as the primary tool. Using stacks, any postfix
expression can be evaluated very
easily. Every character of the postfix expression is scanned from left to
right. If the character encountered is an operand, it is pushed onto the
stack. However, if an operator is encountered, then the top two values are
popped from the stack and the operator is applied to these values. The
result is then pushed on to the stack.
Let us now take an example that makes use of this algorithm.

Example: Evaluation of postfix string 6 2 3 + - 3 8 2 / + * 2 $ 3 +

Token Stack content Operand Operand Result


[0] [1] [2] [3] 1 2
6 6
2 6 2
3 6 2 3
+ 6 5 2 3 5
- 1 6 5 1
3 1 3
8 1 3 8
2 1 3 8 2
/ 1 3 4 8 2 4
+ 1 7 3 4 7
* 7 1 7 7
2 7 2
$ 49 7 2 49
3 49 3
+ 52 49 3 52

Data Structures and Algorithms Using C


Algorithm or Steps
Operators Description Associativity
^$ Exponential or Degree Right to left
* Multiplication Left to Right
/ Division Left to Right
% Mod Left to Right
+ Addition Left to Right
- Subtraction Left to Right
Step 1 Add # at the end of the postfix expression.
Step 2 Scan every character of the postfix expression and
repeat step 3 and step 4 until #is encountered.
Step 3 If an operand is encountered, push it on the stack
If operator O is encountered, then
a. Pop the top two elements from the stack as A and B.
b. Evaluate B O A, where A is the topmost element and B is
the element below A.
c. Push the result of the evaluation on the stack.
d. Then End If statement
Step: 4 SET RESULT equal to the topmost element of the stack.

Step: 5 EXIT

Operators Precedence and Associativity


Program for postfix expression

Data Structures and Algorithms Using C


Output:

Limitations of the program

➢ It does not check if the postfix expression is valid or not. If we input


erroneous expression it returns wrong result
➢ We cannot enter negative numbers, as the symbol to indicate
negation will be misinterpreted as subtraction operation

Algorithm PostfixEval(P)

This algorithm finds the VALUE of an arithmetic expression P written in


postfix notation
1.Scan P from Left to right
2.Repeat steps 3 and 4 until we reach the end of P
3.If an operand is encountered, put it on the stack
4.If an operator is encountered, then:
a) remove the two top elements of the STACK, where A is the top element
and B is the next top element
b) Evaluate B A

Data Structures and Algorithms Using C


c) Place the result of (4) in STACK.
[End of If structure]
[End of step 2 Loop]
5. Set VALUE equal to the top element of STACK.
6. exit

Recursion: Recursion is the process of defining an object in terms of a simpler


case of itself. Suppose p is a function containing either a call statement to itself
(direct recursion) or a call statement to a second function that may eventually
result in a call statement back to the original function P(indirect recursion).
Then the function P is called a recursive function.
A recursive function must have the following two properties.

• There must be a certain argument called the base value for which the
function will not call itself.
• Each time the function refers to itself the argument of the function
must be closer to the base value.
Factorial function: The factorial of a number n is got by finding the product
of all the number for m 1 to n. ie 1*2*3…*n.. It is represented as n!
Example 4!=4*3*2*1=24
5!=5*4*3*2*1=120
0!=1
Therefore n!=n*(n-1)! Accordingly the factorial function can be
defined as Factorial function definition

a) If n=0, then n!=1


b) If n>0, then n!=n*(n-1)!
• The definition is recursive since the function refers to itself for all
values of n>0.
• The value of n! is explicitly given as 1 when the value of n=0, which
can be taken as the base value.

Data Structures and Algorithms Using C


Fibonacci numbers in C

• Fibonacci sequence is a sequence of integers. 0 1 1 2 3 5 8 ….. fib(0)


=0 and fib(1)=1 then each element in this sequence is the sum of the
previous two numbers.
• fib(n)=n if n=0 or if n=1
• fib(n)=fib(n-2)+ fib(n-1) if n>=2

Recursive function to generate the nth Fibonacci number

Tower of Hanoi
The Tower of Hanoi is a mathematical game or puzzle. It consists of three rods,
and a number of disks of different sizes which can slide onto any rod.

The puzzle starts with the disks in a neat stack in ascending order of size on
one rod, the smallest at the top, thus making a conical shape. The objective
of the puzzle is to move the entire stack to another rod, obeying the
following simple rules:
• Only one disk can be moved at a time.
• Each move consists of taking the upper disk from one of the stacks
and placing it on top of another stack i.e. a disk can only be moved if
it is the uppermost disk on a stack.

Data Structures and Algorithms Using C


• No disk may be placed on top of a smaller disk.

Program for Tower of Hanoi

Output:

Example: n=3 disks

Tracing of function with n=3 disks

Data Structures and Algorithms Using C


Data Structures and Algorithms Using C
Session-07
Dynamic Memory Allocation (DMA)
Dynamic Memory Allocation (DMA) in C is the process of allocating memory
during runtime using pointers. This allows a program to allocate memory based
on the actual requirements during execution rather than during compile time.
The memory is allocated using library functions like malloc(), calloc(), realloc(),
and free().

DMA for Variables


In this case, memory is allocated dynamically for a single variable.
Functions used:
• malloc(size_t size): Allocates a block of memory of size bytes and
returns a pointer to it.
• free(pointer): Frees the memory that was allocated using malloc or
calloc.

How it works:
• A pointer is declared, and memory for the variable is allocated dynamically
using malloc().
• Once done with the memory, free() is called to deallocate it and prevent
memory leaks.
Example

Output:

Data Structures and Algorithms Using C


Logic Breakdown:
1. malloc(sizeof(int)): Allocates memory for one integer (sizeof(int) returns
the size of an integer in bytes).
2. *ptr = 42;: Assigns the value 42 to the dynamically allocated memory.
3. free(ptr);: Frees the memory once we're done with it, preventing
memory leaks.

Dynamic memory allocation allows programs to request memory during


runtime instead of at compile time.
The stdlib.h library provides four key functions for memory management:

1. malloc() - Memory Allocation


The malloc() function dynamically allocates a specified number of bytes
and returns a pointer to the allocated memory. The allocated memory
contains garbage values (uninitialized memory).

Syntax:

Example:

Output:

Data Structures and Algorithms Using C


2. calloc() - Continuous Allocation
The calloc() function allocates memory for multiple elements and initializes
them to zero.
Syntax:

Example:

Output

3. realloc() - Resize Memory Block


The realloc() function is used to change the size of previously allocated
memory.
Syntax:

Example:

Data Structures and Algorithms Using C


Output:
4. free() - Deallocate Memory
The free() function releases dynamically allocated memory, preventing
memory leaks.
Example:

Main Logic:
• First, processData is called with the printElement callback to print each
element of the array.
• Then, we loop through the array and use the sumElement callback to
accumulate the sum of the elements.
• We pass different behaviour (printing or summing) to the same
processData function by changing the callback function.

Data Structures and Algorithms Using C


DMA for Arrays
Dynamic memory allocation can also be used for arrays. This is particularly
useful when the size of the array is not known beforehand, and it can change
during program execution.
How it works:
• Allocate memory for an array using malloc() or calloc().
• After using the array, free the allocated memory.
Example Program:

Output:

Logic Breakdown:
1. malloc(n * sizeof(int)): Allocates memory for n integers, where n
is input by the user.
2. arr[i]: Array elements are accessed and modified just like in a
statically declared array.
3. free(arr): Frees the memory allocated for the array.

Data Structures and Algorithms Using C


DMA for Structures
Dynamic memory allocation is often used for structures when you don't
know how many structures you will need or when the number of structures
can vary during runtime.
How it works:
✓ Allocate memory for one or more structures using malloc() or calloc().
✓ Use pointers to access and modify the structure’s members.
✓ Free the memory once done.
Example Program:

Output:

Logic Breakdown:
• malloc(sizeof(struct Student)): Allocates memory for one struct
Student object. The size of the structure is obtained using
sizeof(struct Student).
• studentPtr->name and studentPtr->age: Access the structure's
members using the pointer (studentPtr).
• free(studentPtr): Frees the memory allocated for the structure.

Data Structures and Algorithms Using C


Session-08
Command Line Arguments
Meaning:
Command line arguments allow users to pass values (like filenames, numbers,
etc.) to a program at the time of execution through the terminal or command
prompt. These arguments are captured in the main() function.
Syntax:

✓ argc is the count of command-line arguments.


✓ argv[] is an array of strings (character pointers) representing the
arguments.
Working:
When a C program is executed via the terminal, any additional words entered
after the program name are considered command-line arguments. These are
passed into the main() function. The first element argv[0] is always the
program's name, and the rest are user inputs. This mechanism helps create
flexible and dynamic programs without needing user prompts inside the
program.
Program: Count and Print Command Line Arguments

Output:

Data Structures and Algorithms Using C


Logic Points:
✓ Takes inputs from the command line while running the program.
✓ argc holds the number of arguments (including program name).
✓ argv is used to access each argument.
✓ argv[0] is always the program name.
✓ A loop prints all arguments one by one.
Additional
✓ You can convert the arguments (argv[i]) to integers using atoi() if needed
for numeric operations.
Memory Leaks with Valgrind
Meaning:
A memory leak occurs when a program allocates memory dynamically but does
not free it after use. This causes unused memory to be reserved, which can
slow down or crash the system over time.
Syntax (to detect with Valgrind):

✓ This command helps find lines where memory leaks occur.


Working:
✓ Dynamic memory allocation (using malloc(), calloc(), etc.) gives memory
at runtime. If free() is not called afterward, that memory remains
occupied even after the program ends.
✓ Valgrind is a debugging tool that shows where memory is leaked by
tracking allocation and deallocation.
Program: Demonstrate Memory Leak

Data Structures and Algorithms Using C


Logic Points:
✓ Allocates memory for 5 integers using malloc().
✓ Accesses and assigns values to the array.
✓ Does not call free() — memory not released.
✓ Valgrind detects the leak upon execution.
✓ Leak resolved by adding free(ptr); before return.
Optional Extension:
Fixing the leak:
✓ free(ptr);
✓ Always pair malloc() or calloc() with free() after you're done using the
memory.
Converting a String to Integer using atoi()
Meaning:
atoi() is a function in C that converts a numeric string (e.g., "123") into its
integer equivalent (123). It is declared in the stdlib.h header.
Syntax:

str is the string containing digits.


Working:
When a string with digits is passed to atoi(), it starts reading from the
beginning of the string and stops when a non-digit character is found. The
digits are converted into an integer. If the string has non-numeric characters at
the beginning, the function returns 0.
Program: Using atoi() to Add Two Numbers

Data Structures and Algorithms Using C


Output:

Logic Points:
✓ Takes two numeric strings from the command line.
✓ Uses atoi() to convert strings to integers.
✓ Adds the two integers.
✓ Displays the sum on screen.
✓ Validates if exactly two inputs are provided.

Data Structures and Algorithms Using C


Session-09
QUEUES
✓ A queue is an ordered collection of homogeneous data elements, in
which the first element is inserted from one end called and the deletion
of existing element takes place from the other end called as FRONT.
✓ This makes queue as FIFO (First in First Out) data structure, which means
that element inserted first will also be removed first.
Example

The ADT specification of the queue


✓ objects: a finite ordered list with zero or more elements.
✓ functions: for all queue∈Queue, item∈element, maxQueueSize∈
positive integer
Queue create an empty queue whose maximum size is
CreateQ(maxQueueSize) ::= maxQueueSize
BooleanIsFullQ(queue, if (number of elements in queue == maxQueueSize)
maxQueueSize) ::= returnTRUE else returnFALSE

QueueAddQ(queue, item) ::= if (IsFullQ(queue)) queueFull


else insert item at rear of queue and return queue
BooleanIsEmptyQ(queue) ::= if (queue == CreateQ(maxQueueSize)) returnTRUE else
return FALSE

Element DeleteQ(queue) ::= if (IsEmptyQ(queue)) return


else remove and return the item at front of queue.

Data Structures and Algorithms Using C


Array Representation

✓ In the following example figure, front = 0 and rear = 5.


✓ Suppose we want to add another element with value 45, then rear
would be incremented by 1 and the value would be stored at the
position pointed by rear.

Queue after insertion of a new element

✓ Here, front = 0 and rear = 6.


✓ Every time a new element has to be added, we repeat the same
procedure.
✓ If we want to delete an element from the queue, then the value of front
will be incremented. Deletions are done from only this end of the queue.

Data Structures and Algorithms Using C


Queue operation Insertion
However, before inserting an element in a queue, we must check for overflow
conditions. An overflow will occur when we try to insert an element into a
queue that is already full. When rear =MAX– 1, where MAX is the size of the
queue, we have an overflow condition. Note that we have written MAX – 1
because the index starts from 0.

✓ We first check for the overflow condition.


✓ We check if the queue is empty.
✓ In case the queue is empty, then both front and rear are set to zero, so
that the new value can be stored at the 0 location. Otherwise, if the
queue already has some values, then rear is incremented so that it
points to the next location in the array.
✓ The value is stored in the queue at the location pointed by rear.

Deletion
✓ Before deleting an element from a queue, we must check for underflow
conditions.

Data Structures and Algorithms Using C


✓ An underflow condition occurs when we try to delete an element from a
queue that is already empty. If front = –1 and rear = –1, it means there is
no element in the queue.

C implementation of queues for an integer array: A queue can be represented


by using an array to hold the elements of the array and to use two variables to
hold the position of the first and last element of the queue.

✓ The condition where the queue is empty is called queue underflow.


✓ When we define the size of the array, we cannot insert elements more
than the size of the array, this condition where the queue is full is called
as queue overflow.
Insert operation
The insert operation first checks for queue overflow.
If the queue is not full it inserts one element into the queue at the rear.

Data Structures and Algorithms Using C


Delete operation: Delete operation checks for queue underflow condition and
if the queue is not empty it will remove the element at the front.

Display operation: The display operation will display the elements of the queue
if the queue is not empty.

Data Structures and Algorithms Using C


Disadvantage of linear queue:
The following example illustrates the disadvantage of linear queue
f r Q[0] Q[1] Q[2] Q[3] Q[4] Comment
- -1 Queue is empty
-1 0 2 Insert 2
-1 1 2 3 Insert 3
-1 2 2 3 4 Insert 4
-1 3 2 3 4 5 Insert 5
-1 4 2 3 4 5 6 Insert 6
0 4 3 4 5 6 Delete- item deleted=2
1 4 4 5 6 Delete- item deleted=3
Insert 3(disadvantage)
Queue full. Element cannot
be inserted since rear= size-1
Even if the queue is empty, since the value of rear size-1 elements cannot be
inserted into the queue.
This is the disadvantage of linear queue.

Static queues
A static queue uses a fixed-size array to implement the queue.
Its size is set at compile-time and does not change during execution.
Syntax

Declares a fixed-size array with front and rear tracking queue ends.

Data Structures and Algorithms Using C


3. Working
• enqueue() adds elements at the rear of the array.
• dequeue() removes elements from the front.
• Once the array fills up, no more elements can be inserted.
• No dynamic memory usage; size is fixed and known.
• Suitable for predictable and small queue requirements.
C Program: Static Queue Using Arrays

Output:

Data Structures and Algorithms Using C


Main Logic Points:
✓ Uses a fixed array queue[MAX].
✓ front and rear track queue start and end.
✓ enqueue() increments rear to add values.
✓ dequeue() increments front to remove values.
✓ Checks for overflow and underflow conditions.

Dynamic Queue
A dynamic queue using arrays allows elements to be enqueued and dequeued
like a regular queue, but with flexibility in memory.
When the queue gets full, the array is dynamically resized (usually doubled)
using functions like realloc() in C.
It behaves like a circular queue to efficiently manage space.
Syntax

Dynamically resizes the array when the queue is full by allocating more
memory.
Working
✓ A struct is used to define the queue with its array, front, rear, and
capacity.
✓ Initially, memory is allocated with a fixed size (INITIAL_CAPACITY).
✓ When rear reaches capacity (i.e., the queue is full), the queue doubles its
size dynamically.
✓ During resizing, elements are shifted correctly to maintain the circular
nature of the queue.
✓ The enqueue() adds an element at the rear, and dequeue() removes from
the front.
✓ If the queue becomes empty after a dequeue, both front and rear are
reset to -1.

Data Structures and Algorithms Using C


C Program (Dynamic Queue Using Arrays)

Output

Data Structures and Algorithms Using C


Main Logic Points
✓ A queue is created using a structure with front, rear, and capacity.
✓ The queue dynamically resizes when full using realloc() logic.
✓ Circular indexing is used to manage space efficiently.
✓ Enqueue and Dequeue operations are handled based on the current
index status.
✓ A display() function shows current elements in the queue for testing.

Circular Queues
Circular Queue is a linear data structure in which the operations are performed
based on the FIFO (First In First Out) principle, and the last position is
connected back to the first position to make a circle.
It is also called ‘Ring Buffer’.

In a normal Queue, we can insert elements until the queue becomes full. But
once the queue becomes full, we cannot insert the next element even if there
is a space in front of the queue.

Data Structures and Algorithms Using C


Modification in the code to implement a circular queue
✓ Initial value of front and rear = 0
✓ To advance the pointer from size-1 to 0 the code rear++ is modified to
rear=(rear +1)%size and the code front++ is modified to
front=(front+1)%size
✓ Initially, when front=0 rear=0, i.e, when front == rear, the queue is
empty. Now, after 6 insertions are made, again front=0 and rear=0 0 that
is, the queue is full. So, we cannot distinguish between an empty and a
full queue.
✓ To avoid the resulting confusion, the value of the rear is incremented
before we check for the condition front == rear for queue overflow.

Insert operation: The insert operation first checks for queue overflow. If the
queue is not full it inserts one element into the queue at the rear.

Delete operation: Delete operation checks for queue underflow condition and
if the queue is not empty it will remove the element at the front.

Data Structures and Algorithms Using C


Circular Queues Using Dynamically Allocated Arrays
✓ To add an element to a full queue, we must first increase the size of this
array using a function such as realloc.
✓ As with dynamically allocated stacks, we use array doubling. However, it
isn't sufficient to simply double the array size using realloc.
✓ Consider the full queue.
This figure shows a queue with seven elements in an array whose
capacity is 8. To visualize array doubling when a circular queue is used,
the array is flattened out as shown in the array of Figure (b).

To get a proper circular queue configuration, The number of elements copied


can be limited to capacity-1 by customizing the array doubling code so as to
obtain the configuration as shown below.

Data Structures and Algorithms Using C


This configuration may be obtained as follows:
✓ Create a new array, newQueue of twice the capacity.
✓ Copy the second segment (i.e., the elements queue [front + 1] through
queue [capacity - 1 ]) to positions in newQueuebeginning at 0.
✓ Copy the first segment (i.e., the elements queue [0] through queue
[rear]) to positions in newQueue beginning at capacity-front-1.
Function to add to a circular queue has no change

Function to double queue capacity

The function copy(a,b,c) copies elements from locations a through b-1 to


locations beginning at c

Data Structures and Algorithms Using C


SESSION-11
Linked List

Introduction to Linked List


A Linked List is a dynamic data structure made of nodes, where each node
contains data and a pointer to the next node. Unlike arrays, linked lists do not
require contiguous memory and allow efficient insertion and deletion.

Representation of Singly Linked List


A linked list is represented as a pointer to the first node where each node
contains:

Data: Here the actual information is stored.


Next: Pointer that links to the next node.

Syntax:

This defines a single node having an integer data and a pointer next pointing to
the next node in the list.
Working:
✓ In a Singly Linked List (SLL), each node points only to the next node, and
the last node points to NULL.
✓ A pointer called head usually points to the first node.
✓ You can traverse the list using this pointer to access all nodes one by one
Data Structures and Algorithms Using C
SESSION-12
SLL Implementation – Create and Display
Meaning:
Creating a Singly Linked List means allocating memory dynamically and linking
each node with the next. Displaying the list means traversing from the head
node and printing each node’s data.
Syntax:

✓ Initializes the list as empty.


✓ Nodes are later added dynamically using malloc().
Working:
✓ head starts as NULL.
✓ Each time a node is created, it's linked to the last node’s next.
✓ To display, start at the head and keep printing until the next pointer
becomes NULL.
Program: Create 3 Nodes and Display List

Data Structures and Algorithms Using C


Output
Logic Points:
✓ Defines a structure for the node.
✓ Creates 3 nodes using malloc().
✓ Links the nodes using next pointers.
✓ Displays the list from head to end.
✓ Ends traversal when NULL is reached.

Data Structures and Algorithms Using C


SESSION-13
SLL Implementation

Insert at the Front End


Meaning:
Inserting at the front of the list means adding a new node before the current
head, and then making the new node the new head.
Syntax:

The new node’s next points to the old head, then head is updated.
Working:
✓ A new node is created.
✓ Its next is linked to the current head.
✓ The head pointer is updated to this new node.
Program: Insert a Node at Front

Data Structures and Algorithms Using C


Output:

Logic Points:
✓ Pass head by reference to modify it.
✓ Create a new node with malloc().
✓ Link new node to current head.
✓ Update head to point to new node.
✓ Display from updated head.

Delete from Front, End, and Specific Position


Meaning:
✓ Front Deletion: Removes the first node.
✓ End Deletion: Removes the last node.
✓ Specific Position: Deletes node at a given index.
Syntax (Front):

Move head to the next, free the old head.


Working (Front):
Save the current head in temp.
Move the head to the next node.
Free the old head.
Program: Delete Front, End, Position

Data Structures and Algorithms Using C


Data Structures and Algorithms Using C
Output:
Logic Points:
✓ Front deletion removes the first node.
✓ End deletion finds second last node and frees the last.
✓ Specific position is accessed via index traversal.
✓ Memory is freed after deletion.
✓ NULL checks ensure safe operations.

Sorting the SLL


Meaning:
Sorting a linked list means reordering nodes based on data (ascending or
descending). It’s usually done using simple algorithms like Bubble Sort with
pointer manipulation.
Syntax:

Swaps data between nodes if out of order.


Working:
✓ Use two loops to compare nodes.

Data Structures and Algorithms Using C


✓ Swap their data if they are not in order.
✓ This keeps pointers intact, only data is changed.
Program: Sort a Linked List (Ascending)

Data Structures and Algorithms Using C


Output:

Logic Points:
✓ Bubble sort is applied by swapping data fields.
✓ The outer loop selects a node.
✓ The inner loop compares it with the following nodes.
✓ Swaps data if unordered.
✓ The final list is sorted without moving pointers.

Data Structures and Algorithms Using C


SESSION-14
DOUBLE-LINKED LIST

A doubly linked list (DLL) is a type of linked list in which each node contains
three parts: data, a pointer to the next node, and a pointer to the previous
node.

Traversing from front to rear means starting from the head node and moving
toward the tail, visiting every node one by one.
Representation of a Doubly Linked List
A doubly linked list is represented as a pointer to the first node (head), where
each node contains:
• Data: The actual information stored in the node.
• Next: A pointer that links to the next node in the sequence.
• Previous: A pointer that links to the previous node in the sequence.

Syntax

This structure defines a node in a doubly linked list with data, a pointer to the
next node, and a pointer to the previous node.

Data Structures and Algorithms Using C


Traversal Front-Rear
Working:
✓ A doubly linked list allows traversal in both directions: from head to tail
and vice versa.
✓ To traverse from front to rear, you start at the head node and repeatedly
follow the next pointer until you reach NULL.
✓ This type of traversal is useful when you need to display or process data
in order from beginning to end.
✓ Since each node has a reference to the previous node, it also supports
backward traversal, but in this section we focus only on forward.

Example C Program

Data Structures and Algorithms Using C


Output:

Key Logic Points of the Program:


✓ A doubly linked list node has both prev and next pointers.
✓ insertEnd() adds a new node at the end while updating both pointers
correctly.
✓ The list is created with four elements: 10, 20, 30, and 40.
✓ traverseForward() prints each node’s data from the beginning to the end.
✓ The loop ends when the next pointer becomes NULL
➤ Backward Traversal (Rear to Front):
If you want to traverse from the last node to the first,

This function first reaches the last node and then moves back using prev.

Data Structures and Algorithms Using C


Data Structures and Algorithms Using C

You might also like