Estructuras de Datos
Estructuras de Datos
Estructuras de Datos
DE DATOS
Yoan Pinzón
by Dilan A. Correa
© 2020
Estructuras de Datos
The C Language
© 2020
In This Session
● The C Language
⊳ The Origins of C
⊳ Program Structure
⊳ Data Types
⊳ Operators
⊳ Control Structures
⊳ Iteration Statements
⊳ Break and Continue
⊳ Arrays
⊳ Pointers
⊳ Functions
⊳ Argument Passing Methods
⊳ Dynamic Memory Allocation
⊳ Structures
⊳ Files
Program Structure
#include <stdio.h>
// other preprocessor directives
function-definition 1; function-definition 2; . . .
int main(){
declaration 1;
declaration 2;
. . .
execution-statement 1;
execution-statement 2;
. . .
return 0;
}
2. The header file: The header file included in the basic C program
is stdio.h which would be used in a basic C program. The file stdio.h
provides the fundamental input and output definitions and functions for
C. We will be using other header files later on.
3. The main() funtion: This marks the start of the main part of
the program. All programs will contain one and only one definition of a
function called main.
4. The braces: The opening brace ({) and the closing brace (}) mark
the beginning and the end of the program body. Any code enclosed by
the two braces is referred to as a block. Any variable, or function, defined
in a block only has scope (i.e. is only available) within that block.
/*
This program prompts the user for two integers.
It then calculates the sum
*/
#include <stdio.h>
int main( ){
int x, y;
return 0;
}
Data Types
There are just three fundamental data types in C: int, char and float.
These basic data types together with a small number of modifiers (e.g.
short, long, unsigned) are used to build more complex data types.
Strings
string is not a fundamental data type such as int, float or char. Instead,
strings are represented as arrays of characters, so we will return to subject
of strings later, when we discuss arrays in general.
Arithmetic Operators
Operator Function Use Association
( ) parentheses (expr list) L-to-R
* multiply expr1 * expr2 L-to-R
/ divide expr1 / expr2 L-to-R
% modulo expr1 % expr2 L-to-R
+ plus expr1 + expr2 L-to-R
- minus expr1 - expr2 L-to-R
Example:
int main(){
int i=4, j=7, k=5, val1, val2;
val1 = i * j / 2 + k % 2 -3 ;
val2 = (i * j / ( 2 + k )) % 2 - 3;
printf( "val1=%d\n", val1 ); // outputs 12
printf( "val1=%d\n", val2 ); // outputs -3
return 0;
}
Examples:
Expression true/false
(6 <= 6) && (5 < 3) false
(6 <= 6) || (5 < 3) true
(5 != 6) true
(5 < 3) && (6 <= 6) || (5 != 6) true
(5 < 3) && ((6 <= 6) || (5 != 6)) false
!((5 < 3) && ((6 <= 6) || (5 != 6))) true
Example:
// Assumes int are 4 bits
unsigned int a = 11; // 1011
unsigned int b = ~a; // 0100
unsigned int c = a << 1; // 0110
unsigned int d = a >> 2; // 0010
unsigned int e = a & c; // 0010
unsigned int f = a ^ c; // 1101
unsigned int g = a | c; // 1111
Assignment Operators
Operator Function Use Association
= conventional assignment lvalue = expr R-to-L
*= multiply and assign lvalue *= expr R-to-L
/= divide and assign lvalue /= expr R-to-L
%= modulo and assign lvalue %= expr R-to-L
+= add and assign lvalue += expr R-to-L
-= subtract and assign lvalue -= expr R-to-L
<<= shift left and assign lvalue <<= expr R-to-L
>>= shift right and assign lvalue >>= expr R-to-L
&= AND and assign lvalue &= expr R-to-L
|= OR and assign lvalue |= expr R-to-L
ˆ= XOR and assign lvalue ˆ= expr R-to-L
Examples:
Expression Equivalent to
number += 1; number = number + 1;
total -= discount; total = total - discount;
bonus *= 2; bonus = bonus * 2;
time /= rush factor; time = time / rush factor;
change %= 100; change = change % 100;
amount *= count1 + count2; amount = amount * (count1 + count2);
Example:
int main(){
int x=5;
return 0;
}
Operators
– in decreasing precedence order –
Type Conversion
There is the need to convert one type to another. This is done using
the syntax:
b=(float)c;
d=(int)a;
printf( "a=%f\n", a);
printf( "b=%f\n", b);
printf( "c=%d\n", c);
printf( "d=%d\n", d);
return 0;
}
we can specify that a variable’s value cannot be altered during the exe-
cution of a program with the reserved word const.
Example:
const double Pi = 3.14159;
int main(){
double radius, area, circumference;
return 0;
}
Control Structures
if(Boolean-expression){
i-statement-1;
i-statement-2;
if(Boolean-expression){
. . .
statement-1;
}
statement-2;
else
. . .
{
}
e-statement-1;
e-statement-2;
. . .
}
int main(){
int grade;
return 0;
}
Example 2. Get a candidate’s age and test score, and reports whether
the candidate has passed the test. It uses the following criteria: candi-
dates between 0 and 14 years old have a pass mark of 50%, 15 and 16
year olds have a pass mark of 55%, over 16’s have a pass mark of 60%:
int main(){
int candidate_age, candidate_score;
return 0;
}
switch(selector){
case label-1: statement-1;
break;
. . .
. . .
. . .
int main(){
int score;
return 0;
}
To see how they work, let us use all three of then for the same purpose,
namely to compute s = Σni=1i (s = 1 + 2 + 3 + . . . + n).
return 0;
}
int main(){
int s = 0, i, n;
return 0;
}
As you see there are not major differences among them. However, the for-loop
statement should be used when we know what the range of the loop is going to be.
Otherwise we should use a while-loop or do-while-loop statement. The do-while-
loop statement is desirable when we need to execute the loop-statement before
checking for the condition.
Example:
#include <stdio.h>
int main(){
double s = 0.0, x;
return 0;
}
Example:
#include <stdio.h>
int main(){
int i;
return 0;
}
Arrays
The use of arrays permits us to manipulate a group of memory locations
as a single entity, but at the same time gives us direct access to any
individual component. Arrays are simple examples of structured data
types.
Declaring an array: The general syntax for an array declaration is: type
array-name[size-d1][size-d2] ...;
Example:
#include <stdio.h>
int main(){
int i, a[10];
return 0;
}
Examples:
int a[2][3] = { { 1,2,3 }, { 4,5,6 } };
int b[2][3] = { 1,2,3,4,5 };
int c[2][3] = { { 1,2 }, { 4 } };
Values of a by row: 1 2 3
4 5 6
Values of b by row: 1 2 3
4 5 0
Values of c by row: 1 2 0
4 0 0
#include <stdio.h>
int main(){
int i, j;
int a[2][3] = { { 1,2,3 }, { 4,5,6 } };
int b[2][3] = { 1,2,3,4,5 };
int c[2][3] = { { 1,2 }, { 4 } };
Example:
#include <stdio.h>
int main(){
int i = 16;
int * pi;
pi = &i;
return 0;
}
Functions
body-of-the-funtion;
. . .
}
temp = x; x = y; y = temp;
return;
}
int main(){
int a = 4, b = 5;
swap( a, b );
printf( "a=%d\nb=%d\n", a, b );
return 0;
}
Passing by Reference
The parameters receive the address of the arguments rather that a copy
of its value. The values of the arguments do change.
Example:
#include <stdio.h>
return;
}
int main(){
int a = 4, b = 5;
return 0;
}
Example 1:
int * p = malloc( sizeof(int) );
malloc will allocate unnamed memory of type int and will return the
address where the allocation was done.
Example 2:
int * q = malloc( 128 * sizeof(int) );
This line will allocate memory for an array of 128 elements of type int.
Example:
free( p );
free( q );
Structures
A structure is a collection of one or more variables
Example 1:
#include <stdio.h>
int main( ){
struct point {
int x;
int y;
};
return 0;
}
3 struct cat
4 {
5 int age;
6 int height;
7 char name[20];
8 char father[20];
9 char mother[20];
10 };
12 int main()
13 {
14 struct cat myCat;
15 printf("Enter the name of the cat: " ); scanf("%s", myCat.name );
16 printf("How old is %s? ", myCat.name ); scanf("%d", &myCat.age );
17 printf("How high is %s ( in hands )? ", myCat.name );
18 scanf("%d", &myCat.height );
19 printf("Who is %s’s father? ", myCat.name ); scanf("%s", myCat.father );
20 printf("Who is %s’s mother? ", myCat.name ); scanf("%s", myCat.mother );
21 printf("\n%s is %d years old, %d hands high,", myCat.name, myCat.age, ⤦
Ç myCat.height);
22 printf(" and has %s and %s as parents.\n", myCat.father,myCat.mother );
24 return 0;
25 }
Files
In C we can make use of the function fopen to open a file, and fprintf
to write in it.
Example:
1 #include <stdio.h>
3 int main(){
4 FILE *f;
5 int i;
13 return 0;
14 }
”a+” reading/appending
Files
We can use fscanf to read from a file.
Example:
1 #include <stdio.h>
3 int main(){
4 FILE *f;
5 int x;
14 return 0;
15 }
© 2020
In This Session
A data structure is a data object along with the relationship that exist
among the instances and elements, and which are provided by specifying
the functions of interest.
A list is a data object whose instances are of the form (e1, e2, . . . , en)
where n is a finite natural number.
The ei terms are the elements of the list and n is the length.
In this course we will only focus our attention on the first two
representations
FE300 5 2 4 8 9 ...
element length
FE300 5
first
link
data 5 2 4 8 9
elements 5 2 4 8 9
firstNode 2
node [0] [1] [2] [3] [4] [5] [6] [7] [8] [9]
next 6 7 1 -1 5
element 8 5 4 9 2
first=2
5 2 4 8 9 -1
i= i − 1
location
This means that the ith element of the list (if it exists) is at position
i − 1 of the array.
Example
An array list with 5 elements and max size 10 will look like this:
[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]
FE300 5 2 4 8 9
#ifndef ARRAYLIST
#define ARRAYLIST
#include <stdio.h>
#include <stdlib.h>
#define CAP 100
struct List{
int a[ CAP ], n;
void (*add) ( List *, int, int );
void (*delete) ( List *, int );
int (*get) ( List *, int );
int (*search) ( List *, int );
void (*display) ( List * );
int (*size) ( List * );
int (*empty) ( List * );
};
#endif
List createList( ){
List l;
l.n = 0;
l.add = &add;
l.delete = &delete;
l.get = &get;
l.search = &search;
l.display = &display;
l.size = &size;
l.empty = ∅
return l;
}
add
get, search
testlist.c
#include <stdio.h>
#include "arraylist.h"
int main(){
List maria = createList( );
maria.add( &maria, 0, 100 );
maria.add( &maria, 1, 80 );
maria.add( &maria, 2, 15 );
maria.add( &maria, 3, 24 );
maria.add( &maria, 4, 135 );
maria.display( &maria );
maria.delete( &maria, 2 );
maria.display( &maria );
printf( "La lista tiene %d elementos\n", maria.size( &maria ) );
printf( "El segundo elemento es %d\n", maria.get( &maria, 1 ) );
printf( "El numero 24 tiene posicion %d\n", maria.search( &maria, 24 ) );
return 0;
}
C:\Users\Yoan\Desktop\code\progs>gcc testlist.c
C:\Users\Yoan\Desktop\code\progs>a
List: 100 80 15 24 135
List: 100 80 24 135
La lista tiene 4 elementos
El segundo elemento es 80
El numero 24 tiene posicion 2
C:\Users\Yoan\Desktop\code\progs>
Complexity of Operations
add : On
delete : O
n
get : Θ1
search : On
display : Θn
size : Θ1
empty : Θ1
createList : Θ1
● Each element keeps explicit information about the location of the next
element through a pointer (or link)
● Also called Chain
first
Link Field
Data Field 5 2 4 8 9
Singly linked list or chain
Example
A linked list with 5 elements will look like this:
first
L
Link Field
Data Field 5 2 4 8 9 first
FE30
FF10
link
FF26
FE45 link
FE30 0
data
link
FF10 2 data
data 9
5
FE45
link FA10
FA10 link
data FF26
4 data
8
#ifndef LINKEDLIST
#define LINKEDLIST
#include <stdio.h>
#include <stdlib.h>
struct Node{
int item;
Node * next;
};
struct List{
Node * firstNode;
int n;
void (*add) ( List *, int, int );
void (*delete) ( List *, int );
int (*get) ( List *, int );
int (*search) ( List *, int );
void (*display) ( List * );
int (*size) ( List * );
int (*empty) ( List * );
};
#endif
List createList( ){
List l;
l.firstNode = NULL;
l.n = 0;
l.add = &add;
l.delete = &delete;
l.get = &get;
l.search = &search;
l.display = &display;
l.size = &size;
l.empty = ∅
return l;
}
... link
1 2 3 n data
New Node
(a) Before
first
... link
2 3 4 n+1 data
1
(b) After
New Node
(a) Before
k+1
(b) After
add
first
(a) Before
first
(b) After
delete
void delete( List * x, int index ){
int i;
if( index < 0 || index >= x->n ){
fprintf( stderr, "Error : invalid index\n" );
return;
}
if( empty( x ) ){
fprintf( stderr, "Error : list is empty\n" );
return;
}
Node * y;
if( index == 0 ){
y = x->firstNode;
x->firstNode = x->firstNode->next;
}
else{
Node * p = x->firstNode;
for( i = 0; i < index - 1; i++ )
p = p->next;
y = p->next;
p->next = p->next->next;
}
free( y );
x->n--;
return;
}
int main(){
List maria = createList( );
maria.add( &maria, 0, 100 );
maria.add( &maria, 1, 80 );
maria.add( &maria, 2, 15 );
maria.add( &maria, 3, 24 );
maria.add( &maria, 4, 135 );
maria.display( &maria );
maria.delete( &maria, 2 );
maria.display( &maria );
printf( "La lista tiene %d elementos\n", maria.size( &maria ) );
printf( "El segundo elemento es %d\n", maria.get( &maria, 1 ) );
printf( "El numero 24 tiene posicion %d\n", maria.search( &maria, 24 ) );
return 0;
}
C:\Users\Yoan\Desktop\code\progs>gcc testlist.c
C:\Users\Yoan\Desktop\code\progs>a
List: 100 80 15 24 135
List: 100 80 24 135
La lista tiene 4 elementos
El segundo elemento es 80
El numero 24 tiene posicion 2
C:\Users\Yoan\Desktop\code\progs>
add : On
delete : O
n
get : On
search : On
display : Θn
size : Θ1
empty : Θ1
createList : Θ1
● You can access any array item directly with equal access time, whereas
you must traverse a linked list to access the ith element
© 2020
In This Session
insertions
deletions
bottom top
e e e
1 2 3
... ei ... en- en
1
insertions
deletions
designate the left end of the array as the bottom and the
right end as the top
#include <stdio.h>
#include <stdlib.h>
#define CAP 100
struct Stack{
int a[ CAP ];
int top;
void (*push) ( Stack *, int );
void (*pop) ( Stack * );
int (*peek) ( Stack * );
void (*display) ( Stack * );
int (*empty) ( Stack * );
};
#endif
createStack
Stack createStack( ){
Stack s;
s.top = -1;
s.push = &push;
s.pop = &pop;
s.peek = &peek;
s.display = &display;
s.empty = ∅
return s;
}
#include <stdio.h>
#include "arraystack.h"
int main(){
Stack maria = createStack( );
maria.push( &maria, 100 );
maria.push( &maria, 80 );
maria.push( &maria, 15 );
maria.push( &maria, 24 );
maria.push( &maria, 135 );
maria.display( &maria );
maria.pop( &maria );
maria.display( &maria );
while( !maria.empty( &maria ) ){
printf( "Deleting top element %d\n", maria.peek( &maria ) );
maria.pop( &maria );
}
return 0;
}
C:\Users\Yoan\Desktop\code\progs>gcc teststack.c
C:\Users\Yoan\Desktop\code\progs>a
Stack: [top] 135 24 15 80 100 [bottom]
Stack: [top] 24 15 80 100 [bottom]
Deleting top element 24
Deleting top element 15
Deleting top element 80
Deleting top element 100
C:\Users\Yoan\Desktop\code\progs>
push : Θ
1
pop : Θ
1
peek : Θ
1
display : Θ
n
empty : Θ
1
createStack : Θ
1
designate the left end of the list as the top and the other
end as the bottom
#ifndef LINKEDSTACK
#define LINKEDSTACK
#include <stdio.h>
#include <stdlib.h>
struct Node{
int item;
Node * next;
};
struct Stack{
Node * top;
void (*push) ( Stack *, int );
void (*pop) ( Stack * );
int (*peek) ( Stack * );
void (*display) ( Stack * );
int (*empty) ( Stack * );
};
#endif
Stack createStack( ){
Stack s;
s.top = NULL;
s.push = &push;
s.pop = &pop;
s.peek = &peek;
s.display = &display;
s.empty = ∅
return s;
}
push, pop
teststack.c
#include <stdio.h>
#include "linkedstack.h"
int main(){
Stack maria = createStack( );
maria.push( &maria, 100 );
maria.push( &maria, 80 );
maria.push( &maria, 15 );
maria.push( &maria, 24 );
maria.push( &maria, 135 );
maria.display( &maria );
maria.pop( &maria );
maria.display( &maria );
while( !maria.empty( &maria ) ){
printf( "Deleting top element %d\n", maria.peek( &maria ) );
maria.pop( &maria );
}
return 0;
}
C:\Users\Yoan\Desktop\code\progs>gcc teststack.c
C:\Users\Yoan\Desktop\code\progs>a
Stack: [top] 135 24 15 80 100 [bottom]
Stack: [top] 24 15 80 100 [bottom]
Deleting top element 24
Deleting top element 15
Deleting top element 80
Deleting top element 100
C:\Users\Yoan\Desktop\code\progs>
Complexity of Operations
push : Θ
1
pop : Θ
1
peek : Θ
1
display : Θ
n
empty : Θ
1
createStack : Θ
1
● (((a+b)*c+d*e)/((f+g)-h+i))
● (a*(a+b))/(b+d)
Parentheses Matching
– Strategy –
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
( ( ( a + b ) * c + d * e ) / ( ( f + g ) - h ) )
3
2
1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
( ( ( a + b ) * c + d * e ) / ( ( f + g ) - h ) )
Parentheses Matching
– Implementation –
parenthesismatching.c
#include <stdio.h>
#include <string.h>
#include "arraystack.h"
int main( ){
char x[256];
printf( "Type an expression \n" );
gets( x );
printf( "The pairs of matching parentheses in %s are:\n", x );
printMatchedPairs( x );
return 0;
}
C:\Users\Yoan\Desktop\code\progs>gcc parenthesismatching.c
C:\Users\Yoan\Desktop\code\progs>a
Type an expression
(((a+b)*c+d*e)/((f+g)-h+i))
The pairs of matching parentheses in (((a+b)*c+d*e)/((f+g)-h+i)) are:
2 6
1 13
16 20
15 25
0 26
Switchbox Routing
– Example –
1 2 3 4 5 6 7 8 9 10
Net={ 1, 2, 3, 4, 4, 3, 2, 5, 5, 1 }
1 2 3
10 4
Routable !
9 5
8 7 6
1 2 3 4 5 6 7 8 9 10
Net={ 1, 2, 3, 4, 4, 2, 3, 5, 5, 1 }
1 2 3
10 4
NOT
Routable!
9 5
8 7 6
switchbox.c
#include <stdio.h>
#include "arraystack.h"
int main( ){
int i, n, * net;
printf( "Type number of pins in switch box\n" );
scanf( "%d", &n );
net = ( int * ) malloc( sizeof( int ) * n );
printf( "Type net numbers for pins 1 through %d\n", n );
for( i = 0; i < n; i++ )
scanf( "%d", &net[ i ] );
checkBox( net, n );
return 0;
}
checkBox
void checkBox( int * net, int n ){
int i;
Stack s = createStack( );
for( i = 0; i < n; i++ )
if( !s.empty( &s ) )
if( net[ i ] == net[ s.peek( &s ) ] )
s.pop( &s );
else s.push( &s, i );
else s.push( &s, i );
if( s.empty( &s ) ){
printf( "Switch box is routable\n" );
return;
}
printf( "Switch box is not routable\n" );
return;
}
C:\Users\Yoan\Desktop\code\progs>gcc switchbox.c
C:\Users\Yoan\Desktop\code\progs>a
Type number of pins in switch box
10
Type net numbers for pins 1 through 10
1 2 3 4 4 3 2 5 5 1
Switch box is routable
C:\Users\Yoan\Desktop\code\progs>a
Type number of pins in switch box
10
Type net numbers for pins 1 through 10
1 2 3 4 4 2 3 5 5 1
Switch box is not routable
C:\Users\Yoan\Desktop\code\progs>
Time Complexity
© 2020
In This Session
● Time Complexity
⊳ Growth of Functions
⊳ Growth Rates
⊳ Asymptotic Notation: O, Ω, Θ
– How does the running time of an algorithm increase with the size
of the input in the limit as the input increases in size without
bound?
– Define sets of functions that satisfy certain criteria and use these
to characterize time and space complexity of algorithms
time
2n-7
n
0.5n+3
n
(a) Growth of Functions (Linear)
log n
n
(b) Growth Rates
Growth Rates
¢
¨0, f ngrows slower than gn
¨
¨
f n ¨
¨
¨ª, f ngrows faster than gn
lim ¦
n ª gn ¨¨
¨
¨
¨otherwise f nand gn
¤have the same growth rate
¨
f nhgn
lim f n~gn= 0
n ª
● Deal with the behavior of functions in the limit (for sufficiently large
value of its parameters)
– 7n − 3 is On
f(n)
n0 n
f(n)=O(g(n))
yoan Estru
turas de Datos 158
The Ω Notation
f n= Ωgn if there exist positive constants c and 0n such that for
every n Cn0,
f nCcgn
time
f(n)
cg(n)
n0 n
f(n)= (g(n))
yoan Estru
turas de Datos 159
The Θ Notation
f n= Θgnif f n= Ognand f n= Ωn, or equivalently, if there
are positive constants c1, c2 and n0 such that for every n Cn0,
c1gnBf nB2cgn
time
c2 g(n)
f(n)
c1 g(n)
n0 n
f(n)=£(g(n))
yoan Estru
turas de Datos 160
Danger of Asymptotic Notation
● Even though the former algorithm is better for all but finitely many
instances, the latter is better for all the instances that can exist in
the known universe.
● constant O1
● logarithmic Olog n
● polylogarithmic Ologc n, c C1
● n log n On log n
● sublinear Ona, 0 < a < 1
● linear On
● quadratic On2
● polynomial Onc, c C1
● exponential Ocn, c > 1
● factorial On!
© 2020
In This Session
front rear
e e e
1 2 3
... ei ... en- en
1
deletions insertions
L front = location
1; rear = location
n
T T T E
A A A
F
front front
front
Lfront points one position before the position of the first element in the
queue.
L Empty queue: front = rear
(initially front=rear=0)
L Full queue: (rear+1)%MaxSize = front
#include <stdio.h>
#include <stdlib.h>
#define CAP 100
struct Queue{
int a[ CAP ];
int front, rear, n;
void (*put) ( Queue *, int );
void (*delete) ( Queue * );
int (*getFront) ( Queue * );
int (*getRear) ( Queue * );
void (*display) ( Queue * );
int (*empty) ( Queue * );
};
#endif
createQueue
Queue createQueue( ){
Queue q;
q.front = q.rear = q.n = 0;
q.put = &put;
q.delete = &delete;
q.getFront = &getFront;
q.getRear = &getRear;
q.display = &display;
q.empty = ∅
return q;
}
getFront, getRear
testqueue.c
#include <stdio.h>
#include "arrayqueue.h"
int main(){
Queue maria = createQueue( );
maria.put( &maria, 100 );
maria.put( &maria, 80 );
maria.put( &maria, 15 );
maria.put( &maria, 24 );
maria.put( &maria, 135 );
maria.display( &maria );
maria.delete( &maria );
maria.display( &maria );
printf( "Front element is %d\n", maria.getFront( &maria ) );
printf( "Rear element is %d\n", maria.getRear( &maria ) );
while( !maria.empty( &maria ) ){
printf( "Deleting front element %d\n", maria.getFront( &maria ) );
maria.delete( &maria );
}
return 0;
}
C:\Users\Yoan\Desktop\code\progs>gcc testqueue.c
C:\Users\Yoan\Desktop\code\progs>a
Queue: [front] 100 80 15 24 135 [rear]
Queue: [front] 80 15 24 135 [rear]
Front element is 80
Rear element is 135
Deleting front element 80
Deleting front element 15
Deleting front element 24
Deleting front element 135
C:\Users\Yoan\Desktop\code\progs>
Complexity of Operations
put : Θ
1
delete : Θ
1
getFront : Θ
1
getRear : Θ
1
display : Θ
n
empty : Θ
1
createQueue : Θ
1
...
front rear
...
front rear
(a) Addition
...
front rear
(b) Deletion
#ifndef LINKEDQUEUE
#define LINKEDQUEUE
#include <stdio.h>
#include <stdlib.h>
struct Node{
int item;
Node * next;
};
struct Queue{
Node *front, *rear;
void (*put) ( Queue *, int );
void (*delete) ( Queue * );
int (*getFront) ( Queue * );
int (*getRear) ( Queue * );
void (*display) ( Queue * );
int (*empty) ( Queue * );
};
#endif
Queue createQueue( ){
Queue q;
q.front = q.rear = NULL;
q.put = &put;
q.delete = &delete;
q.getFront = &getFront;
q.getRear = &getRear;
q.display = &display;
q.empty = ∅
return q;
}
put, delete
void put( Queue * x, int e ){
Node * y = malloc( sizeof( Node ) );
y->item = e;
y->next = NULL;
if( empty( x ) )
x->front = y;
else
x->rear->next = y;
x->rear = y;
return;
}
display, empty
#include <stdio.h>
#include "linkedqueue.h"
int main(){
Queue maria = createQueue( );
maria.put( &maria, 100 );
maria.put( &maria, 80 );
maria.put( &maria, 15 );
maria.put( &maria, 24 );
maria.put( &maria, 135 );
maria.display( &maria );
maria.delete( &maria );
maria.display( &maria );
printf( "Front element is %d\n", maria.getFront( &maria ) );
printf( "Rear element is %d\n", maria.getRear( &maria ) );
while( !maria.empty( &maria ) ){
printf( "Deleting front element %d\n", maria.getFront( &maria ) );
maria.delete( &maria );
}
return 0;
}
C:\Users\Yoan\Desktop\code\progs>gcc testqueue.c
C:\Users\Yoan\Desktop\code\progs>a
Queue: [front] 100 80 15 24 135 [rear]
Queue: [front] 80 15 24 135 [rear]
Front element is 80
Rear element is 135
Deleting front element 80
Deleting front element 15
Deleting front element 24
Deleting front element 135
C:\Users\Yoan\Desktop\code\progs>
put : Θ
1
delete : Θ
1
getFront : Θ
1
getRear : Θ
1
display : Θ
n
empty : Θ
1
createQueue : Θ
1
Queue Application
– Image-Component Labelling –
1 2
1 1 2 2
1 3
(a) Input 1 1 (b) Output 3 3
1 1 1 4 3 5
1 1 1 1 4 4 4 5
1 1 1 1 1 4 4 4 5 5
imagecomponets.c
#include <stdio.h>
#include "arrayqueue.h"
struct Position{
int row, col;
};
int main( ){
inputImage( );
labelComponents( );
outputImage( );
return 0;
}
inputImage
void inputImage( ){
printf( "Enter image size: " );
scanf( "%d", &size );
pixel = malloc( ( size + 2 ) * sizeof( int * ) );
for( i = 0; i < size + 2; i++ )
pixel[i] = malloc( ( size + 2 ) * sizeof( int ) );
printf( "Enter the pixel array in row-major order\n" );
for( i = 1; i <= size; i++ )
for( j = 1; j <= size; j++ )
scanf( "%d", &pixel[ i ][ j ] );
return;
}
void labelComponents( ){
int numOfNbrs = 4, id = 1, r, c;
Position nbr, here, offset[ 4 ] = {
{ 0, 1 }, // right
{ 1, 0 }, // down
{ 0, -1 }, // left
{ -1, 0 } // up
};
for( i = 0; i <= size + 1; i++ ){
pixel[ 0 ][ i ] = pixel[ size + 1 ][ i ] = 0;
pixel[ i ][ 0 ] = pixel[ i ][ size + 1 ] = 0;
}
Queue qx = createQueue();
Queue qy = createQueue();
for( r = 1; r <= size; r++ )
for( c = 1; c <= size; c++ )
if( pixel[ r ][ c ] == 1 ){
pixel[ r ][ c ] = ++id;
here = (Position) { r, c };
while( 1 ){
for( i = 0; i < numOfNbrs; i++ ){
nbr.row = here.row + offset[ i ].row;
nbr.col = here.col + offset[ i ].col;
void outputImage( ){
printf( "\nThe labeled image is\n\n" );
for( i = 1; i <= size; i++ ){
for( j = 1; j <= size; j++ )
printf( "%d ", pixel[ i ][ j ] );
printf( "\n" );
}
}
imagecomponents.input
7
0 0 1 0 0 0 0
0 0 1 1 0 0 0
0 0 0 0 1 0 0
0 0 0 1 1 0 0
1 0 0 0 1 0 0
1 1 1 0 0 0 0
1 1 1 0 0 0 0
C:\Users\Yoan\Desktop\code\progs>gcc imagecomponents.c
0 0 2 0 0 0 0
0 0 2 2 0 0 0
0 0 0 0 3 0 0
0 0 0 3 3 0 0
4 0 0 0 3 0 0
4 4 4 0 0 0 0
4 4 4 0 0 0 0
Queue Application
– Lee’s Wire Router –
T
6 6
5 6 2 3 4 5 6 5 6 2 3 4 5 6
4 1 2 4 1 2
3 2 1 S 1 3 2 1 S 1
3 2 1 2 3 3 2 1 2 3
3 T 3 T
6 5 4 5 6 6 5 4 5 6
wirerouter.c
#include <stdio.h>
#include "arrayqueue.h"
struct Position{
int row, col;
};
int main( ){
inputData( );
if( findPath( ) ) outputPath( );
else printf( "There is no wire path" );
return 0;
}
inputData
void inputData( ){
printf( "Enter grid size: " );
scanf( "%d", &size );
printf( "Enter the start position\n" );
scanf( "%d %d", &start.row, &start.col );
printf( "Enter the finish position\n" );
scanf( "%d %d", &finish.row, &finish.col );
grid = malloc( ( size + 2 ) * sizeof( int * ) );
for( i = 0; i < size + 2; i++ )
grid[i] = malloc( ( size + 2 ) * sizeof( int ) );
printf( "Enter the grid array in row-major order\n" );
for( i = 1; i <= size; i++ )
for( j = 1; j <= size; j++ )
scanf( "%d", &grid[ i ][ j ] );
return;
}
void findPath( ){
int numOfNbrs = 4;
Position here, nbr, offset[ 4 ] = {
{ 0, 1 }, // right
{ 1, 0 }, // down
{ 0, -1 }, // left
{ -1, 0 } // up
};
for( i = 0; i <= size + 1; i++ ){
grid[ 0 ][ i ] = grid[ size + 1 ][ i ] = 1;
grid[ i ][ 0 ] = grid[ i ][ size + 1 ] = 1;
}
if( ( start.row == finish.row ) && ( start.col == finish.col ) )
return 1;
here = (Position) { start.row, start.col };
grid[ start.row ][ start.col ] = 2;
Queue qx = createQueue();
Queue qy = createQueue();
while( 1 ){
for( i = 0; i < numOfNbrs; i++ ){
nbr.row = here.row + offset[ i ].row;
nbr.col = here.col + offset[ i ].col;
if( grid[ nbr.row ][ nbr.col ] == 0 ){
grid[ nbr.row ][ nbr.col ] = grid[ here.row ][ here.col ] + 1;
if( ( nbr.row == finish.row ) && ( nbr.col == finish.col ) )
break;
qx.put( &qx, nbr.row );
qy.put( &qy, nbr.col );
}
}
if( ( nbr.row == finish.row ) && ( nbr.col == finish.col ) )
break;
if( qx.empty( &qx ) ) return 0;
here.row = qx.getFront( &qx );
here.col = qy.getFront( &qy );
qx.delete( &qx );
qy.delete( &qy );
}
pathLength = grid[ finish.row ][ finish.col ] - 2;
here = finish;
for( j = pathLength - 1; j >= 0; j-- ){
path[ j ] = here;
for( i = 0; i < numOfNbrs; i++ ){
nbr.row = here.row + offset[ i ].row;
nbr.col = here.col + offset[ i ].col;
if( grid[ nbr.row ][ nbr.col ] == j + 2 ) break;
}
here = (Position) { nbr.row, nbr.col };
}
return 1;
}
void outputPath( ){
printf( "The wire path is\n" );
for( i = 0; i < pathLength; i++ )
printf( "%d %d\n", path[ i ].row, path[ i ].col );
return;
}
wirerouter.input
7
3 2
4 6
0 0 1 0 0 0 0
0 0 1 1 0 0 0
0 0 0 0 1 0 0
0 0 0 1 1 0 0
1 0 0 0 1 0 0
1 1 1 0 0 0 0
1 1 1 0 0 0 0
C:\Users\Yoan\Desktop\code\progs>gcc wirerouter.c
© 2020
In This Session
– somebody’s descendants
– governmental/company subdivisions
Terminology
A tree is a finite nonempty set of elements
● x, y are siblings
2
v
● Elements with no children are called
leaves
3
x y
● Level: root=level 1; children=level 2,3,
...
4
P1: Every binary tree with n elements, n > 0, has exactly n − 1 edges.
Proof: Each element (except the root) has one parent. §exactly one
edge between each child and its parent. Hence, §n − 1 edges. j
Proof: By induction on i.
Basis: i = 1; number of elements = 1 = 20
Ind. Hypothesis: i = k; number of elements at level k B2k−1.
Look at level i = k + 1
(number of elements at level k + 1) B2 (number of elements at level k)
B2 × 2k−1 = 2k . j
h
n BQ 2i−1 = 2h − 1
i=1
j
2 3
4 5 6 7
2 3
4 5 6
Proof: By induction on i. j
Uses P5
1
A
2 3
B C
4 5 6 7
D E
1 2 3 4 5 6 7
A B C D E
root
LeftChild RightChild
● data data
● LeftChild
● RightChild
data data
Example:
A
B C
D E F
#ifndef BINARYTREE
#define BINARYTREE
#include <stdio.h>
#include <stdlib.h>
struct TreeNode{
int item;
TreeNode * left;
TreeNode * right;
};
struct Tree{
TreeNode * root;
void (*makeTree) ( Tree *, int, Tree *, Tree * );
void (*preorder) ( TreeNode * );
void (*inorder) ( TreeNode * );
void (*postorder) ( TreeNode * );
void (*levelorder) ( TreeNode * );
int (*empty) ( TreeNode * );
int (*size) ( TreeNode * );
int (*height) ( TreeNode * );
};
#endif
Tree createTree( ){
Tree t;
t.root = NULL;
t.makeTree = &makeTree;
t.preorder = &preorder;
t.inorder = &inorder;
t.postorder = &postorder;
t.levelorder = &levelorder;
t.empty = ∅
t.size = &size;
t.height = &height;
return t;
}
makeTree
levelorder
testbinarytree.c
#include <stdio.h>
#include "binarytree.h"
int main(){
Tree a = createTree( );
Tree x = createTree( );
Tree y = createTree( );
Tree z = createTree( );
y.makeTree( &y, 1, &a, &a );
z.makeTree( &z, 2, &a, &a );
x.makeTree( &x, 3, &y, &z );
y.makeTree( &y, 4, &x, &a );
printf( "Preorder sequence is " );
y.preorder( y.root );
printf( "\n" );
printf( "Inorder sequence is " );
y.inorder( y.root );
printf( "\n" );
printf( "Postorder sequence is " );
y.postorder( y.root );
printf( "\n" );
printf( "Level sequence is " );
C:\Users\Yoan\Desktop\code\progs>gcc testbinarytree.c
C:\Users\Yoan\Desktop\code\progs>a
Preorder sequence is 4 3 1 2
Inorder sequence is 1 3 2 4
Postorder sequence is 1 2 3 4
Level sequence is 4 3 1 2
empty = 0
size = 4
height = 3
C:\Users\Yoan\Desktop\code\progs>
+
+
* d
(a*b)+(c/d) * / (((a-b)*c)+d)
- c
a b c d
a b
Infix form: a*b+c/d a-b*c+d
Prefix form: +*ab/cd +*-abcd
Postfix form: ab*cd/+ ab-c*d+
● Postfix evaluation:
lScan left-to-right
lPut operator to a stack
lApply the encountered operator to the operands in the stack and
delete them from the stack.
© 2020
In This Session
● Linear list.
● Heap.
● Max tree (min tree): is a tree in which the value in a each node is
greater (less) than or equal to those in its children.
● Max heap (min heap): is a max (min) tree that is also a complete
binary tree.
14 2
12 7 7 4
10 8 6 10 8 6
Representation of a Heap
Time Complexity: O
log n
Example: Insert 5.
20 20 20
15 2 15 2 15 5
14 10 14 10 5 14 10 2
20 20 20
15 5 15 5 15 21
14 10 2 14 10 2 21 14 10 2 5
21
15 20
14 10 2 5
Deletion
● Delete the rightmost leaf at the highest level and put it in the root.
Time Complexity: O
log n
21 2
15 20 15 20 15 20
14 10 2 14 10 2 14 10
20
15 2
14 10
20 10
15 2 15 2 15 2
14 10 14 10 14
15 15
14 2 10 2
10 14
maxheap.h
#ifndef MAXHEAP
#define MAXHEAP
#include <stdio.h>
#include <stdlib.h>
#define CAP 100
struct Heap{
int * a;
int n;
void (*put) ( Heap *, int );
void (*delete) ( Heap * );
int (*top) ( Heap * );
int (*initialize) ( Heap *, int *, int );
void (*display) ( Heap * );
int (*empty) ( Heap * );
};
#endif
Heap createHeap( ){
Heap h;
h.n = 0;
h.a = malloc( sizeof( int ) * CAP + 1 );
h.put = &put;
h.delete = &delete;
h.top = ⊤
h.initialize = &initialize;
h.display = &display;
h.empty = ∅
return h;
}
put
testheap.c
#include <stdio.h>
#include "maxheap.h"
int main(){
int array[] = { 0, 8, 23, 89, 100, 35, 11, 52, 77, 44, 60 };
Heap maria = createHeap( );
maria.put( &maria, 100 );
maria.put( &maria, 80 );
maria.put( &maria, 15 );
maria.put( &maria, 24 );
maria.put( &maria, 135 );
maria.display( &maria );
printf( "Top element is %d\n", maria.top( &maria ) );
maria.delete( &maria );
maria.display( &maria );
maria.initialize( &maria, array, 10 );
maria.display( &maria );
while( !maria.empty( &maria ) ){
printf( "Deleting max element %d\n", maria.top( &maria ) );
maria.delete( &maria );
}
return 0;
}
C:\Users\Yoan\Desktop\code\progs>gcc testheap.c
C:\Users\Yoan\Desktop\code\progs>a
Heap: 135 100 15 24 80
Top element is 135
Heap: 100 80 15 24
Heap: 100 77 89 44 60 11 52 23 8 35
Deleting max element 100
Deleting max element 89
Deleting max element 77
Deleting max element 60
Deleting max element 52
Deleting max element 44
Deleting max element 35
Deleting max element 23
Deleting max element 11
Deleting max element 8
C:\Users\Yoan\Desktop\code\progs>
2) Extract (i.e. delete) elements from the heap one at a time. Each
deletion takes Olog ntime, so the total time is O
n log n