C and DS Content
C and DS Content
1
Agenda
1 Introduction to C
8 Lists
10 Binary Trees
Talentio Solutions India
Pvt. Ltd.
Introduction to C
Module 1
Objectives
Eg:FORTRON,PASCAL,C ..etc.
Assemblers and Compilers
• Expressions
• Arithmetic, logical, and assignment operators in an infix notation
• Statements
• Sequences of conditional, iteration, and branching instructions
• Functions
• Groups of statements and variables invoked recursively
Constants, Variables keywords and Identifiers
• The main( ) is a special function used by the C system to tell the computer
where the program starts.
• Any Variable used in the program must be declared before using it.
Purpose
• Exposure to Program development environment, compilation,
debugging and running a “Welcome program” program
• Working with printf & scanf function for integer data type.
Summary
Duration: 4hrs
C Expressions & Operators
• Traditional mathematical expressions
y = a*x*x + b*x + c;
Prefix operator first does the operation and then result is assigned to
the variable.
Postfix operator first assigns the value to the variable and then does
the operation.
Conditional/ Ternary Operator
• The Logical OR
Operator
a || b
(a < b) || (c < d)
• Conversions take place across assignments; the value of the right side is
converted to the type of the left, which is the type of the result.
Type Conversions (Contd.).
• Consider the following assignments:
int i;
char c;
i = c;
• The problem with the above assignment is that the fractional portion of
the above division is lost, and d is effectively assigned the integer
quotient of the two integers i and j.
Explicit Type Conversion (Contd.).
• To resolve this, the variable i can be type cast into a double as in:
d = (double)i / j;
• int i is converted to a double using the explicit cast operator. Since one of
the operands is a double, the other operand (j) is also converted to a
double, and the result is a double.
• The result is assigned to a double with no side effects. The cast operator
can be done only on the right-hand side of an assignment.
Bit-wise Operators
statement–
block; True
test expression ?
}
statement–block
statement-x; False
Statement-x
if….else statement
if(test expression)
{ False
True Test expression?
true-block statements;
}
else False-block
True-block
{
False-block statements;
}
statement-x; Statement-x
Example - if- else Construct
The following function checks whether the
character entered by the user is a star (*)
character. start
#include <stdio.h>
ch = ‘ ‘
main( )
{
char ch; Input ch
ch = getchar( );
fflush(stdin); is ch = ‘*’
true
Print *
if (ch = = ‘*’)
puts (“You have entered false
the star character”);
else Not a *
• On the first condition evaluating to false, the else part of the first
condition consists of another if statement that is evaluated for a
condition.
• A nested if statement is
encountered if the statement to
be executed after a condition
evaluates to true is another if
statement.
• General form
while(test-condition)
{
body of the loop
}
Example - The while Loop
#include <stdio.h>
/* function to accept a string and display it 10 times
main( )
{
int counter=0;
char message[10];
gets( message);
fflush( stdin);
while (counter <= 9)
{
puts( message);
counter = counter + 1;
gets( message);
fflush (stdin)
}
}
do…while loop
• The general form of do..while loop is
do
{
body of the loop
} while (test-condition) ; Execute body of loop
for(initialization;test-condition;increment)
{
body of the loop
}
#include <stdio.h>
/* this function displays a message 10 times */
main( )
{
int i;
for( i = 0; i <= 9; i = i + 1)
{
puts( “message”);
}
}
Features of for loop
• Initializing, testing and incrementing are placed in the for loop itself, thus
making them visible to the programmers and users, in one place.
• The for statement allows for negative increments. More than one variable
can be initialized at a time.
for (p=1,n=0;n<17;++n)
• The increment section can also have more than one part.
for (n=1,m=50;n<=m;m++,n--)
• The break statement is used to exit early from all loop constructs (while,
do-while, and for)
• When the loops are nested,the break would only exit from the loop
containing it.
• The goto requires a label in order to identify the place where the
branch is to be made.
int no,sqroot;
read:scanf(“%d”,&no);
if(no<0)
goto read;
sqroot=sqrt(no);
C Statements
• Expression
• Conditional
• if (expr) { … } else {…}
• switch (expr) { case c1: case c2: … }
• Iteration
• while (expr) { … } zero or more iterations
• do … while (expr) at least one iteration
• for ( init ; valid ; next ) { … }
• Jump
• goto label
• continue; go to start of loop
• break; exit loop or switch
• return expr; return from function
Hands-on: 2 hours
Purpose
Purpose
Character Arrays
Char name[11];
• To define a character array, need to define a array of size n+1 characters.This is
because all character arrays are terminated by a NULL character (‘\0’)
• where name[0] through name[9] will contain the characters comprising the
name, and name[10] will store the NULL character
Array - Memory allocation
#include<stdio.h>
main( )
{
char array1[ ] = {‘A’, ‘R’, ‘R’, ‘A’, ‘Y’,
‘\0’};
char array2[ ] = {“ARRAY”};
char dayofweek[ ] = {‘M’, ‘T’, ‘W’, ‘T’, ‘F’,
‘S’, ‘S’, ‘\0’};
float values[ ] = {100.56, 200.33, 220.44,0};
}
Array Processing
#include<stdio.h>
main( )
{ char array1[ ] = {‘A’, ‘R’, ‘R’, ‘A’, ‘Y’, ‘\0’};
char array2[ ] = {“ARRAY”};
char dayofweek[ ] = {‘M’, ‘T’, ‘W’, ‘T’, ‘F’, ‘S’,
‘S’, ‘\0’};
float values[ ] = {100.56, 200.33, 220.44, 400.22,
0};
int i = 0;
printf( “String 1 is %s\n”, array1);
printf( “String 2 is %s\n”, array2);
for( i = 0; dayofweek[i] != ‘\0’; i = i +1)
printf ( “The Day %d in a week is %c\n”, i + 1,
dayofweek[i];
for( i = 0; values[i] != 0; i = i +1)
printf ( “The amount %d in a week is %f\n”, i + 1,
values[i];
Array Manipulation Using Subscripts
/* this function finds the length of a character string */
#include <stdio.h>
main( )
{
int i = 0;
char string[11];
main( )
{
int total, int_array[20], i = -1;
do
{
i = i + 1;
printf(“Enter number %d (0 to terminate)\n”);
scanf(“%d”, &int_array[i]);
}while (int_array[i] != 0);
i = 0;
while (int_array != 0)
{
printf(“Element number %d is %d\n”, i + 1,
int_array[i]);
total = total + int_array[i];
}
printf(“The sum of the numbers in the array is %d \n”,
total);
}
Two-Dimensional Arrays
• Declaration:
type array_name[rowsize][columnsize];
Eg:
int m[3][3]={0,0,0,1,1,1,2,2,2};
m[0][0] m[0][1] m[0][2]
m[1][0] m[1][1] m[1][2]
m[2][0] m[2][1] m[2][2]
In multi-dimensional
arrays,elements are stored
sequentially row wise in memory.
Two-dimensional Arrays (Contd.).
row 0
row 1
row 2
• The measure of the flexibility of any program is the ease with which
changes can be implemented.
#include <stdio.h>
#define RG 3
#define PR 3
main( )
{ int r_counter, p_counter, rp_array[RG][PR], total_sales = 0;
float rp_array_perc[RG][PR];
int i, *pointer_to_an_integer;
i = 22;
pointer_to_an_integer = &i;
/* initialize pointer variable (pointer_to_an_integer) with address of the integer
variable i. */
i variable name
#include<stdio.h>
main( )
{ int x, y, *pointer;
x = 22;
pointer = &x;
y = *pointer; /* obtain whatever pointer is pointing
to */
}
Pointers - Variations on a Theme
• Consider the following code snippet:
int x, y, *pointer1, *pointer2;
pointer1 = &x /* return the address of x into pointer1 */
pointer2 = pointer1;
/* assign the address in pointer1 to pointer2. Hence, both the pointer variables, pointer1
and pointer2, point to the variable x. */
i variable name
pointer2
1000
Pointers - Variations on a Theme (Contd.).
• Consider the following code
snippet:
int x, y, *p1, *p2;
x = 22;
y = 44;
p1 = &x; /* p1 points to x */
p2 = &y ; /* p2 points to y */
*p1 = *p2 ;
/* make whatever p1 was pointing
to (variable x and hence the
value 22) equivalent to whatever
p2 is pointing to. */
Two-dimensional
• Since a pointer to a character can be a pointer to a string, it
follows that a two-dimensional character array can be declared as
an array of character pointers.
p
100
108 400 5 10 15 20 25
Pointer Arithmetic (Contd.).
• Hence, *(p + 1) returns the address 300.
• Therefore, * (*(p + 1)) returns the value at this address, i.e., the
element with the value 3. In other words, the element at the offset
[1,0].
• The following table gives various pointer expressions, and their values:
Purpose
• Functions facilitate:
• Reusability
• Procedural abstraction
• Function Parameters
• Function parameters are defined as part of a function header, and are
specified inside the parentheses of the function.
• The reason that functions are designed to accept parameters is that you
can embody generic code inside the function.
• All that would be required by the function would be the values that it
would need to apply the generic code on the values received by it through
its parameters
Function Parameters
• The format string, and the variable name can be called the
parameters to the function printf( ) in this example.
Invoking Functions
• In C, functions that have parameters are invoked in one of two
ways:
• Call by value
• Call by reference
Call by Value Call by reference
void swap(int,int );
void swap( int *, int *);
main()
main()
{ int a=10, b=20;
{ int a=10, b=20;
swap(a, b);
swap(&a, &b);
printf(“ %d %d
printf(“ %d %d \n”,a,b);
\n”,a,b);
}
}
• Consider the situation where you want to use the pow( ) function,
called the power function, one of many functions in the
mathematics library available for use by the programmer.
• A function call such as pow(x, y) returns the value of x raised to the power
y.
Function Prototype (Contd.).
• A function prototype tells the compiler the number and data types
of arguments to be passed to the function and the data type of the
value that is to be returned by the function.
• It is important to know how the CPU manages all this, i.e., knowing
where to look for when a function call is encountered, and having
executed the function, to also know where it has to return to.
• Compile-time constants
• Large integer values
• Floating-point values
• Literal strings
Dynamic Memory
code area
global/static area
stack
free space
heap
Procedure Activation Record
arguments
bookkeeping information
A Procedure Activation (return address)
Record or a Stack Frame
local data
local temporaries
Registers
• int z;
fn_a( int m ) fn_b( int n )
• main( )
{ {
• {
• int x; int y; int b;
• fn_a( ); fn_b( ); …..
• ….. . return instruction ….. .
return instruction
• . . .
• .
. .
• .
. }
• }
• }
A View of the Runtime Stack
z
S Global static area
t Activation record of main
x
a
m
c
y
k
control link Activation record of call to fn_a( )
G return address
r n
o control link Activation record of call to fn_b( )
w return address
t fp b
sp
h Free Store (Heap)
Access to Variables
• Two examples:
• The number of arguments in a call may vary from call to call.
• The size of an array parameter or a local array variable may vary from call to
call.
• The strings are the words that make up the command line
arguments.
• Since the element argv[0] contains the command itself, the value
of argc is at least 1.
Command-Line Arguments (Contd.).
#include <stdio.h>
main(int argc, char * argv[ ])
{ int i;
for (i = 0; argv[1][i] != ‘\0’, i++)
{ if ((argv[1][i] >= ‘a’) && (argv[1][i] <= ‘z’))
argv[1][i] = argv[1][i] – 32;
}
printf( “%s”, argv[1]);
}
Storage Qualifiers
• Variable declarations,
therefore, are by default,
auto.
Global Variables
/* A sample C program */
• Global variable is defined # include <stdio.h>
outside all functions.
/* function prototype */
int sum( );
• A typical convention of
defining global variables is /* a and b are global variables, visible to main( ) as well
before the main( ) function. as to sum( ) */
int a=10, b=20;
• In such a case, if the functions use the same global variables, then
their declarations would involve the use of the extern qualifier
Extern Variables (Contd.).
• Example: strcpy( string1, “XYZ”) will copy the string “XYZ” to the
string string1.
• Example:
• sprintf( str, “%02d-%02d-%02d”, 28, 8, 71)
will return the string 28-08-71 into str.
Functions for Formatting Data in Memory (Contd.).
• Example:
sscanf(str, “%2d%2s%s%d”, &day, suffix, mnth, &year)
printf(“The day is : %d, suffix is %s, month is %s, year is %d\n”, day, suffix,
mnth, year);
• If the data in str is “29th July 1971”, the output will be:
• The day is 29, suffix is th, month is July, year is 1971
Recursion: Factorial Function
• You may therefore write the
definition of this function as
follows: You may therefore define:
0! = 1
1! = 1 * 0!
2! = 2 * 1!
• 0! = 1 3! = 3 * 2!
• 1! = 1 4! = 4 * 3!
• 2! = 2 * 1
• 3! = 3 * 2 * 1 prod = 1
• 4! = 4 * 3 * 2 * 1 for (x = n; x > 0; x--)
{
prod *= x;
return (prod)
• n! = 1 if n = = 0
}
• n! = n * (n-1) * (n-2) * ….. * 1 if n
> 0.
Evolving a Recursive Definition for the \
Factorial
• You will now attempt to incorporate this process into an
algorithm. You want the algorithm to accept a non-negative
integer, and to compute in a variable fact the non-negative
integer that is n factorial.
if (n == 0)
fact = 1;
else
{
x = n – 1;
find the value of x!. call it y;
fact = n * y;
}
Mechanics of Recursion
int fact(n)
• In the statement y = fact(x), the int n;
function fact( ) makes a recursive {
call to itself.
int x, y;
if ( n == 0)
• This is the essential ingredient of return (1);
a recursive routine.
else
{
• The programmer assumes that
the function being computed x = n-1;
has already been written, and y = fact(x);
uses it in its own definition.
return ( n *
y);
• However, the programmer must }
ensure that this does not lead to
an endless series of calls. }
Mechanics of Recursion (Contd.).
•s 2 * *
3 * *
3 2 *
4 * * 4 3 * 4 3 *
n x y n x y n x y n x y
Mechanics of Recursion (Contd.).
0 * *
1 * * 1 0 *
1 0 1
2 1 * 2 1 *
2 1 * 2 1 1
3 2 * 3 2 *
3 2 * 3 2 *
4 3 * 4 3 *
4 3 * 4 3 *
n x y n x y n x y n x y
Mechanics of Recursion (Contd.).
3 2 2
4 3 * 4 3 6
n x y n x y n x y
• Then you compile your code, and every time your program
comes to that point, your function is called.
• But what can you do, if you don't know at build-time which
function has got to be called? Or, invoke functions at runtime.
Function Pointers (Contd.).
• However you can also solve the latter problem using a switch-
statement, where you call the functions just like you want it, in
the different branches.
struct empdata {
int empno;
char name[10];
char job[10];
float salary;
};
Declaring a Structure - Conventions
struct empdata {
int empno;
char name[10];
char job[10];
float salary;
} emprec; /* emprec is a variable of
structure type empdata */
• fread( ) will return the actual number of records read from the file.
This feature can be checked for a successful read.
Byte 0 Byte 1
ch
Unions (Contd.).
switch (money)
{
case penny : printf( “penny”);
break;
case nickel : printf( “nickel”);
break;
case dime : printf( “dime”); break;
case quarter : printf( “quarter”);
break;
case half_dollar : printf(
“half_dollar”); break;
case dollar : printf( “dollar”);
break;
}
Typedef Statements
• Purpose
• construct Structures, Unions & Enumeration and performing
computation
Summary
• The format string, along with the data to be output, are the
parameters to the printf( ) function.
#include<stdio.h>
main( )
{
int number = 97;
printf(“Value of num is %d\n”, number);
printf(“The Character equivalent of %d is
%c\n”, number, number);
}
Formatted Input
• #include<stdio.h>
• main( )
• {
• char string[40];
• printf(“Enter a string of maximum 39 characters”);
• scanf(“%s”, string);
• fflush(stdin);
• printf(“%s”, string);
• }
Files
• This structure to which the file pointer point to, is of type FILE,
defined in the header file <stdio.h>.
“w” Write only mode The “w” mode creates an empty file
for output. If a file by the name
already exists, it is deleted. Data can
only be written to the file, and not
read from it
File Access Modes
“a” Append mode Allows data to be appended to the end of the file,
without erasing the existing contents. It is therefore
useful for adding data to existing data files.
“w+” Write + Read This mode works similarly to the “w” mode, except
mode that it allows data to be read back after it is written.
“a+” Read + This mode allows existing data to be read, and new
Append mode data to be added to the end of the file.
Character-based File I/O
#include<stdio.h>
main( )
{
char ch;
while ( (ch = fgetc( stdin)) != EOF)
{
fputc (ch, stdout);
}
}
Nuggets on FILE Type Pointers
• The NULL return value of fopen( ) can be used for error checking
as in the following line of code:
• if ((fp = fopen(“a.dat”, “r”)) = = NULL)
• printf(“Error Message”);
The exit( ) function
• fgets( ) reads the next input line (including the newline) from
file fp into the character array line;
• For output, the function fputs( ) writes a string (which need not
contain a newline) to a file:
• For example, when a file is opened for input, the current position
in the file from which input takes place is the beginning of the
file.
• If, after opening the file, the first input operation results in ten
bytes being read from the file, the current position in the file
from which the next input operation will take place is from the
eleventh byte position.
Random Access (Contd.).
• A current position beyond the last byte in the file indicates end
of file.
The fseek( ) Function
• fp = fopen(“employee.dat”, r)
employee.dat
1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
current offset
The fseek( ) function (Contd.).
employee.dat
1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
current offset
The fseek( ) function (Contd.).
• fgets(string, 7, fp);
employee.dat
1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
current offset
The fseek( ) function
• Consider the following schematic representation of a file in
terms of a string of 30 bytes. The file contains records and
fields that are not delimited by any special character.
• fseek(fp, -10L, 2)
employee.da
t
1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
current offset
The rewind( ) Function
Purpose
• Performing file related i/o operations
Summary
Duration: 3 hrs
Introduction
• Design Issue:
• select and design appropriate data types
What is Program
• A Set of Instructions
• Data Structures + Algorithms
• Algorithm = Logic + Control
Functions of Data Structures
• Array
• Stack
• Queue
• Linked List
• Tree
• Heap
• Hash Table
• Priority Queue
• Three issues:
Free
malloc( )
Dynamic Storage Allocation (Contd.).
• Rules:
• Each segment contiguous in memory (no holes)
• Segments do not move once allocated
• malloc()
• Find memory area large enough for segment
• Mark that memory is allocated
• free()
• Mark the segment as unallocated
Simple Dynamic Storage Allocation
First large-enough
free block selected
Free block divided
into two
Previous next
pointer updated
Newly-allocated
region begins with
a size value
Simple Dynamic Storage Allocation
(Contd.).
Appropriate
position in free list
identified
Newly-freed region
added to adjacent
free regions
malloc() and free()
• The parameter to malloc( ) is an unsigned integer which
represents the number of bytes that the programmer has
requested malloc( ) to allocate on the heap.
int *a;
a = (int *) malloc(sizeof(int) * k);
a[5] = 3;
free(a);
• Create a sorted At the end of this module, you will be able to:
Duration: 6 hrs
Linked Lists
• A linked List is a collection of structures ordered not by their
physical placement in memory but by logical links that are stored
as part of the data in the structure itself.
struct node
{
type item;
struct node *next;
};
Arrays & Linked Lists
Arrays Linked Lists
• The sequential organization is The order of the list is given by
provided implicitly by its index. links from one item to another.
• The memory allocation is static. Memory allocation is dynamic
• Elements are physically and Elements are logically adjacent
logically adjacent.
• Binary and Linear search Only linear search applicable.
applicable. Searching is fast Searching is slow
• Insertion and deletion of elements Insertion and deletion of
takes more time. elements is fast.
• Arrays take less memory than Linked Lists take more memory
linked lists. than arrays (address of the next
node is to be stored)
Creating a Linked List..
Struct node
{
int marks;
struct node *next;
};
node
marks next
Begin
if the list is empty, then, node cannot be deleted.
else if node to be deleted is the first node,then,make the head
to point
to the second node.
else delete the node from the body of the list.
End
struct marks_list
{
int marks;
struct marks_list *next;
};
main()
{ struct marks_list * makenode();
• struct marks_list *new;
• start = NULL;
• char menu = ‘0 ‘;
while (menu != ‘4’)
{
printf( “Add Nodes :\n”);
printf( “Delete Nodes :\n”);
printf( “Traverse a list :\n”);
printf( “Exit :\n”);
menu = getchar( );
switch (menu)
{
case ‘1’ : addnode( ); break;
case ‘2’ : deletenode( ); break;
case ‘3’ : traverse( ); break;
case ‘4’: exit( ); break;
} /* end of switch */
} /* end of main( ) */
Creating a Sorted Linked List (Contd.).
addnode( )
{ char ch = 'y';
while ( ch = = 'y' )
{ new = makenode(); struct marks_list * makenode()
/* creation of a list is treated as {
a special case of insertion */ struct marks_list *new;
if ( start == NULL) new=(struct marks_list *)
malloc(sizeof(struct(marks_l
{ start = new; }
ist));
else { insert(); scanf("%d",&new->marks);
traverse( ); } new->next = NULL;
printf("%s","Want to add more return(new);
nodes\n"); }
scanf( "%c", &ch );
fflush( stdin );
} /* end of while */
} /* end of addnode( )
Creating a Sorted Linked List (Contd.).
insert(struct marks_list *start) /* insertion in the middle of a list */
{ struct marks_list *ptr, *prev; if(new->marks > ptr->marks)
{ continue; }
for(ptr=start,prev=start;(ptr);pr else { prev->next = new;
ev=ptr,ptr=ptr->next) new->next = ptr; }
{ if (new->marks < start->marks) } /* end of for loop */
{ /* insertion at the
beginning of a list */ /* insertion at the end of the list */
new->next = start; if (ptr == null)
start = new; { prev->next = new;
} new->next = null;
}
} /* end of insert */
Linked List – Search, Delete
• The doubly linked lists uses double set of pointers, one pointing to
the
• next and other pointing to the preceding item.This allows us to
traverse
• the list in either direction
• Circular doubly linked lists employ both the forward pointer and
• backward pointer in circular form.
Different types of Linked lists
Advantages and Disadvantages of Linked lists
• Linked list uses the memory that is just needed for the list at any
point of time.(It is not necessary to specify the no of nodes to be
used in the list).
• Linked list use more storage than an array with the same no of
items.
Doubly Linked List
• In a doubly linked list, each node has two pointers, one say, next
pointing to the next node in the list, and another say, prior
pointing to the previous node in the list.
• In a doubly linked list, the prior pointer of the first node will be
null, as there is no node before the first node.
• In a doubly linked list, the next pointer of the last node will be
null, as there is no node after this list.
• A doubly linked list would have two pointers, start and last to
facilitate traversal from the beginning and end of the list
respectively.
Declaration of a Doubly Linked List
• struct marks_list
• {
• struct double_list *prior;
• int info;
• struct marks_list *next;
• }
Visualizing a Doubly Linked List
last
start
100 140
{ insert();
addnode( )
traverse( );
{
}
char ch = 'y';
printf("%s","Want to add
while ( ch = = 'y' )
more nodes\n");
{ new = makenode();
scanf( "%c", &ch );
/* creation of a list is
treated as a special case of fflush( stdin );
insertion */ } /* end of while */
if ( start = = NULL) } /* end of addnode( )
{ start = new;
start->prior = null;
}
else
struct marks_list * makenode()
{struct marks_list *new;
new=(struct marks_list *) malloc(sizeof(struct(marks_list));
scanf("%d",&new->marks);
new->prior = NULL;
new->next = NULL;
return(new);
}
insert( )
{ struct marks_list *ptr, *prev;
for(ptr=start,prev=start;(ptr);prev=ptr,ptr=ptr->next)
{ if (new->marks < start->marks)
{/* insertion at the beginning of a list */
new->next = start;
new->prior = NULL;
start->prior = new;
last = start;
start = new;
}
Creating a Sorted Doubly Linked List
(Contd.).
• Purpose
• construct single and doubly linked list and perform insertion,
deletion and append operations
Summary
Duration: 4 hrs
What is a Stack?
• create (s)
• to create s an empty stack
• push (s, i)
• to insert element i on top of the stack
• pop (s)
• to remove top element of the stack
• top (s)
• to return top element of stack
• empty(s)
• to check whether the stack is empty or not
• Others
• Full stack, Stack count, Destroy stack
Implementation of Stacks
new
info next
top 2 3
info next
Creating a Node on a Stack
top A B
next
Applications of Stacks
• main( ) is the first one to execute, but it is the last one to finish,
after a( ) has finished and returned.
• Every time the student at the front of the queue deposits the fee,
he leaves the queue (analogous to deleting nodes from a queue).
• The student who comes first in the queue is the one who leaves
the queue first.
1 2 3 1 2 3 4
front rear
front rear
(a) (b)
2 3 4
front rear
(c)
Queue Operations
• The first step you must perform in working with any queue is to
initialize the queue for further use. Other important operations
are to add an element, and to delete an element from a queue.
rear
2 4 7
front
Queue Declaration & Operations
• struct queue
• {
• int info;
• struct queue *next;
• };
• struct queue *front, *rear;
• struct queue
• { int info;
• struct queue *next;
• };
• /* pointer declarations to point to the front, and rear of the
queue */
• struct queue *front, *rear;
• main( )
• {
• front = NULL;
• rear = NULL;
Insertion into a Queue (Contd.).
char menu = ‘0 ‘;
while (menu != ‘3’)
{
printf( “Add Nodes :\n”);
printf( “Delete Nodes :\n”);
printf( “Exit :\n”);
menu = getchar( );
switch (menu)
{
case ‘1’ : enq( );
break;
case ‘2’ : deq( )
break;
case ‘3’: exit( );
break;
} /* end of switch */
} /* end of main( ) */
Insertion into a Queue (Contd.).
• void enq( )
• {
• struct queue *new;
• new = getnode( );
• if(queue_pointer->front= =queue_pointer->rear = = null)
• {
• queue_pointer->front = new;
• queue_pointer->rear = new;
• }
• else
• {
• rear->next = new;
• rear = new;
• }
• }
Creating a Node on a Queue
New node
inserted at rear of
rear queue
2 4 7 8
front
New
Deletion from a Queue
• int deq( )
• {
• struct queue *temp;
• int x;
• if(queue_pointer->front= =queue_pointer->rear = = null)
• {
• printf( “Queue Underflow\n”);
• exit (1);
• }
• temp = front;
• x=temp->info;
• front = front->next;
• free(temp);
• if(front = = null) /* check for queue becoming empty after node deletion
*/
• rear = null;
• return(x);
• }
Deletion of a Node From a Queue
rear
2 4 7
front
• Whenever the CPU is free, it executes the job that is at the front
of the job queue.
• Similarly, there are queues for shared I/O devices. Each device
maintains its own queue of requests.
• The first print request is the first one to be processed. New print
requests are added at the end of the queue.
Hands-on: 2 hours
• Purpose
• construct stack and queue so that to perform related operations
Summary
Duration: 5 hrs
Eliminative or a Binary Search
• The search time increases in direct proportion with the size of the
linked list.
Example - Binary Search
• Game that will highlight a new mechanism of searching
• A coin is with one of the members in the audience divided into the
two sections on the left and the right respectively as shown in the
diagram.
J K L A B C
M N O D E F
P Q R G H I
Example - Binary Search (Contd.).
J K L
6 searches saved
X NO
M N O
YES
P Q R
Example - Binary Search (Contd.).
• X is now left with row to the right of the middle row containing
P, Q, and R that has to be searched.
• Here too, he can position himself right at the middle of the row
adjacent to Q and pose the same question,
• “Which side of the audience has the coin?” ‘Q’ replies that the
coin is to his left.
P Q R
NO YES
X
Trees
• Trees are non-linear data
structures.
• In a tree structure, each node may
point to several nodes
• Tree are very flexible and a
powerful data structure
• Used for a wide variety of
applications.
• A tree is a collection of nodes that
are connected to each other.
• contains a unique first element known
as the root, which is shown at the top
of the tree structure.
• A node which points to other nodes is
said to be the parent of the nodes
• the nodes that the parent node points
to are called the children, or child
nodes of the parent node.
Tree (Contd.).
• The length of the longest path from the root to any node is
known as the depth of the tree.
• The root is at level 0 and the level of any node in the tree is one
more than the level of its parent.
• Even while searching the right subtree of the root node and its
descendant subtrees, we keep searching only one-half of the
right subtree and its descendants.
• Before we visit the root of the left subtree, we must visit its left
subtree, which is empty.
• Hence the root of the left subtree rooted at B is visited first. Next,
the right subtree of this node is traversed inorder.
Inorder Traversal (Contd.).
• Again, first its left subtree containing only one node D is visited,
then its root C is visited, and finally the right subtree of C that
contains only one node E is visited.
• After completing the left subtree of root A, we must visit the root
A, and then traverse its right subtree, which is empty.
• For postorder traversal, we must traverse both the left and the
right subtrees of each node before visiting the node itself.
• You may note that when you traverse a binary search tree
inorder, the keys will be in sorted order because all the keys in
the left subtree are less than the key in the root, and all the
keys in the right subtree are greater than that in the root.
• The same rule applies to all the subtrees until they have only
one key.
• To create an empty tree, you must initialize the root to null. The
first node will be inserted into the tree as a root node as shown in
the following figure.
Root 10
15
Insertion into a Tree (Contd.).
• Now 12 is larger than the root; it must go to the right
subtree of the root.
Root 10
15
12
7 15
12
Insertion into a Tree (Contd.).
• Similarly, 8, 18, 6 and 20 are inserted at the proper place as shown
in the following figures.
Insertion into a Tree (Contd.).
• We must also create a node for the new value and finally, we have
to adjust the left and right pointers to insert the new node.
• To find the insertion place for the new value, say 17, we initialize a
temporary pointer p, which points to the root node.
Insertion into a Tree (Contd.).
• But once p becomes null, it is not possible to link the new node at
this position because there is no access to the node that p was
pointing to (node with value 18) just before it became null.
• You therefore need a way to climb back into the tree so that you
can access the node containing 18, in order to make its left
pointer point to the new node with the value 17.
• For this, you need a pointer that points to the node containing 18
when p becomes null.
• When p becomes null, this pointer will point to the leaf node (the
node with value 18) to which you must link the new node (node
with value 17).
Insertion into a Tree (Contd.).
• Once you know the insertion place, you must adjust the pointers
of the new node.
• At this point, you only have a pointer to the leaf node to which the
new node is to be linked.
• If the value in the leaf node is greater, we insert the new node as
its left child; otherwise we insert the new node as its right child.
Creating a Tree – A Special Case of Insertion
• A special case of insertion that you need to watch out for arises
when the tree in which you are inserting a node is an empty tree.
• You must treat it as a special case because when p equals null, the
second pointer (trail) trailing p will also be null, and any reference
to info of trail like trail->info will be illegal.
• You have seen that to insert a node, you must compare x with
root->info.
• The base case is inserting a node into an empty tree. You can
write a recursive routine (rinsert) to insert a node recursively as
follows:
• Given the following input, their insertion into the tree in the same
order would more or less produce a balanced binary search tree as
shown below:
• Input values: 10, 15, 12, 7, 8, 18, 6, 20
Circumstances When a Binary Tree Degenerates into a
Linked List (Contd.).
• If the same input is given in the sorted order as
• 6, 7, 8, 10, 12, 15, 18, 20, you will construct a lopsided tree with
only right subtrees starting from the root.
• There is no way you can make the parent of the deleted node to
point to both of the children of the deleted node.
• So, you attach one of the subtrees of the node to be deleted to the
parent, and then link the other subtree onto the appropriate node
of the first subtree.
• You can attach the right subtree to the parent node and then link
the left subtree on to the appropriate node of the right subtree.
Case III – Deletion Of a Node With Two Child
Nodes (Contd.).
• Therefore, you must attach the left subtree as far to the left as
possible. This proper place can be found by going left until an
empty left subtree is found.
• Also, note that you first attach the left subtree at the proper place
and then attach the right subtree to the parent node of the node
to be deleted.
Search The Tree (Contd.).
• Then you compare the information field of p with the given value
x. If the information is equal to x, you exit the routine and return
the current value of p.
search (p,x)
int x;
struct tree *p;
{
p = root;
while (p != null && p->info != x)
{
if (p->info > x)
p = p->left;
else
p = p->right;
} return (p);
}
Hands-on: 2 hours
Purpose