Sunteți pe pagina 1din 133

2016699 http://dis.unal.edu.

co/profesores/ypinzon/2016699

Estructuras de Datos
Lecture Notes

Yoan Pinz on, PhD


Profesor Asociado Universidad Nacional de Colombia Departamento de Ingenier a de Sistemas e Industrial http://dis.unal.edu.co/profesores/ypinzon/

c 2009

Teacher opens the door, but you must enter by yourself Chinese Proverb

Estructuras de Datos
Sesi on 1
Preliminares, Introducci on al C++ (1ra Parte)
Yoan Pinz on, PhD Profesor Asociado Universidad Nacional de Colombia http://dis.unal.edu.co/profesores/ypinzon c 2009

Session 1
Preliminares Horario de Clases Horario de Consulta Cr editos Intensidad Horaria Formato de Clase Comportamiento en Clase Bibliograf a P agina Web Docente Monitor de Curso Calendario Acad emico Evaluaciones Formato de las Evaluaciones Parciales Evaluaciones Supletorias Publicaci on de Calicaciones Reclamaci on de Calicaciones ProgramaCalendario

on al C++ (1ra Parte) Introducci



The Origins of C++ Program Structure Data Types Operators Control Structures
http://dis.unal.edu.co/profesores/ypinzon/2016699

Preliminares
Horario de Clases
Lunes 07-08 08-09 09-10 10-11 11-12 12-01 01-02 02-03 03-04

Martes

Miercoles

Jueves

Viernes

Grupo 2 Grupo 2

Grupo 2 Grupo 2

Salon 453-107

http://dis.unal.edu.co/profesores/ypinzon/2016699

Horario de Consulta
Lunes 07-08 08-09 09-10 10-11 11-12 12-01 01-02 02-03 03-04

Martes

Miercoles

Jueves

Viernes

Consulta Consulta

Ocina 453-116

Durante el horario de consulta, el estudiante tiene la oportunidad de consultar sus dudas sobre algunos de los aspectos vistos en clase, y/o discutir sobre los progresos de su trabajo

http://dis.unal.edu.co/profesores/ypinzon/2016699

Cr editos Esta asignatura tiene una valor de 3 (tres) cr editos

Intensidad Horaria Esta es una asignatura te orico-pr actica de 4 horas presenciales y 5 horas de trabajo personal por semana Este curso NO es validable!

Formato de la Clase La clase comiez a transcurridos cinco minutos de la hora establecida para su inicio Si llega tarde: est e sucientemente preparado porque ... Se dar a un descanso de aproximadamente 10 minutos por cada hora de clase
http://dis.unal.edu.co/profesores/ypinzon/2016699

Comportamiento en Clase 1. Por respeto hacia los dem as (y hacia m ) LLegue a tiempo No conteste llamadas en clase 2. Por respeto hacia usted mismo (y otros) Haga preguntas Levante la mano; haga la pregunta No sea timido; recuerde que no existen preguntas est upidas! He who asks is a fool for ve minutes, but he who does not ask remains a fool forever. Old Chinese saying 3. Por respeto hacia el tema (y hacia m ) Haga preguntas propias Trate de entender el qu e, el c omo, el porqu e y el para qu e ciles no son aburridos Los temas dif Los temas aburridos no son dif ciles Est e preparado para corregirme (educadamente)

http://dis.unal.edu.co/profesores/ypinzon/2016699

Bibliograf a S. Sahni, Data Structures, Algorithms and Applications in C++, Silicon Press; 2nd edition, 2004. S. Sahni, Data Structures, Algorithms and Applications in C++, WCB/McGraw-Hill, 1998. M. A. Weis, Data Structures and Algorithm Analysis in C++, 2/E, Addison-Wesley, 1999. B. Stroustrup, The C++ Programming Language, 3/E, AddisonWesley, 2000. S. B. Lippman and J. Lajoie, C++ Primer, 3rd Edition, AddisonWesley, 1998. A Aho, J Hopcroft and J Ullman, Data Structures and Algorithms, Addison-Wesley, 1983.

http://dis.unal.edu.co/profesores/ypinzon/2016699

P agina Web La p agina web del curso (cuya direcci on aparece abajo) contendr a informaci on relevante para los alumnos, de modo que sugerir a que la revisara con frecuencia http://dis.unal.edu.co/profesores/ypinzon/2016699 Docente Yoan Pinz on Ocina : 453/116 eMail : ypinzon@unal.edu.co WWW : http://dis.unal.edu.co/profesores/ypinzon Monitor del Curso John Alexander Cely Suarez

http://dis.unal.edu.co/profesores/ypinzon/2016699

Calendario Acad emico

L 2

Feb 2009 M M J
3 4 5

V 6

W e e k

L 2

Mar 2009 M M J
3 4 5

V 6

W e e k 2 3 4 5 6

Abr 2009 M M J
1 2

V 3

W e e k 6 7 8 9 10

May 2009 M M J V
1

W e e k 10 11 12 13 14

L 1 8

Jun 2009 M M J V S
2 3 4 5

W e e k 15 16 17

9 10

11 12 13

9 10

11 12 13

9 10

9 10

11 12

16 17 18 19 20 23 24 25 26 27
1

16 17 18 19 20 23 24 25 26 27 30 31

13 14 15 16 17 20 21 22 23 24 27 28 29 30

11 12 13 14 15 18 19 20 21 22 25 26 27 28 29

15 16 17 18 19 20 22 23 24 25 26 29 30

inicio/fin de clases primera evaluacin ordinaria (1Abr2009) segunda evaluacin ordinaria (6May2009) tercera evaluacin ordinaria (3Jun2009) semana santa

http://dis.unal.edu.co/profesores/ypinzon/2016699

Evaluaciones Se tomar an CUATRO evaluaciones con los siguientes porcentajes:

Valor Porcentaje

Nota 1 Nota 2 Nota 3 Nota 4

1ra evaluacin ordinaria escrita (1Abr)........... 2da evaluacin ordinaria escrita (6May)........ 3ra evaluacin ordinaria escrita (3Jun).......... talleres (23Feb - 20Jun) .........................................

25% 25% 25% 25%

Total: 100%
Todas las evaluaciones se dar an en el rango de 0.0 a 5.0

http://dis.unal.edu.co/profesores/ypinzon/2016699

Evaluaciones (cont.) El curso cuenta con un componente te orico (75%) y un componente pr actico (25%)

aaaaaaaa aaaaaaaaaaa Nota1 aaaaaaaa aaaaaaaaaaa aaaaaaaa 25%aaaaaaaaaaa aaaaaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaaaaa aaaaaaaaaaa Nota4 aaaaaaaa Nota2 aaaaaaaaaaa aaaaaaaaaaaaaaaaaa a a aaaaaaaa 25% a a a a aaaaaaaaaaaaaaaaaa aaaa 25% aaaaaaaa aaaaaaaaaaa a a aaaaaaaaaaaaaaaaaa aaaa aaaaaaaa aa aa aaaaaaaaaaa a a a aa aaaaaaaa aaaaa aaaaaaaaaaaaa aaaa Nota3 a aaaaaaaa aaaaaaaaaaaaaaaaaaa aaaaa aaaaaaaa aaaaaaaaaaa
aaaaa25% aaaaaaa aa aa aaaa a a a a a a aaaaaaa

Teora (75%)

aaaaa aaaaa aaaaa aaaaa

Este curso NO es validable, quien lo repruebe deber a, forzosamente, cursar el curso nuevamente!
http://dis.unal.edu.co/profesores/ypinzon/2016699

a Prctic (25%)

10

Formato de las Evaluaciones Parciales

Las notas 1, 2 y 3 ser an evaluaciones parciales escritas Cada evaluaci on tendra un valor de 25% de la nota nal

Evaluaciones Supletorias

Cuando existen causas justicadas a juicio del profesor La solicitud de evaluaci on supletoria debe hacerse por escrito al profesor dentro de los cinco (5) d as h abiles siguientes a la fecha de presentaci on de la evaluaci on ordinaria prevista

http://dis.unal.edu.co/profesores/ypinzon/2016699

11

Publicaci on de Calicaciones

Los resultados de las evaluaciones ordinarias se dar an a conocer dentro de los diez (10) d as h abiles siguientes a su realizaci on.

Reclamaci on de Calicaciones

La revisi on de las calicaciones de evaluaciones ordinarias podr a ser reclamada, por una sola vez, dentro de los cinco (5) d as h abiles siguientes a la entrega de la nota, ante el Director del Departamento de Ingenier a de Sistemas e Industrial.

http://dis.unal.edu.co/profesores/ypinzon/2016699

12

ProgramaCalendario
PROGRAMA-CALENDARIO a. Identificacin de la asignatura: nombre completo, cdigo y nmero de crditos
Estructuras de Datos, 2016699, 3 crditos Semana 11,12=Tree Data Structure (terminology, binary trees, properties, Binary Tree ADT, fomula based representation, linked representation, binary tree traversals, an application, binary search trees) Semana 13,14=Priority Queue Data Structure (max priority queues ADT, heaps, formula based representation, an application) Semana 15,16=Dictionary Data Structure (dictionary ADT, BST representation, linear list representation, skip list representation, hash table representation)

b. Metodologa a utilizar
Combinacin de clase magistral y clase prctica de 4 horas de duracin. Se introducen los temas tericos, se explica la estructura de datos, se especifica el ADT (tipo de dato abstracto), se explica la codificacin en C++ haciendo nfasis en las diferentes formas que existen para representar datos en la memoria del computador, se ven algunas aplicaciones, se desarrolla un taller sobre el tema visto.

d. Carcter, tipo y ponderacin de pruebas


N1, evaluacin escrita, ordinaria, 25% N2, evaluacin escrita, ordinaria, 25% N3, evaluacin escrita, ordinaria, 25% N4, evaluacin prctica, ordinaria, 25%

c. Distribucin de los temas y subtemas


Semana 1,2,3,4=Introduccin al C++ (the origins of c++, Semana 5=LinearList using a Formula-based representation (methods of representing data, linear list ADT,
linear list coding in C++) program structure, data types, operators, control structures, iteration statements, arrays, pointers, dynamic memory allocation, functions, templates, inline expansion, overloading, exception handling, clases)

e. Fechas de presentacin de pruebas


N1(1Abr) N2(6May) N3(3Jun) N4(23Feb-20Jun)

f. Porcentaje mnimo exigido de asistencia


80%

Semana 6=Chain using a Linked representation

(conding in C++, comparing array based representation and linked representation) Semana 7,8=Stack Data Structure (stack ADT, formula based representation using inheritance and a customised implementation, linked representation using inheritance and a customised implementation, two applications : parentheses matching and switchbox routing) Semana 9,10=Queue Data Structure (queue ADT, formula based representation using a customised implementation, linked representation using a customised implementation, two applications : image component labeling and lees wire router)

g. Bibliografa
S. Sahni, Data Structures, Algorithms and Applications in C++, Silicon Press; 2nd edition, 2004. A Aho, J Hopcroft and J Ullman, Data Structures and Algorithms, Addison-Wesley, 1983.

h. Si la asignatura es validable o no
NO es validable

http://dis.unal.edu.co/profesores/ypinzon/2016699

13

The Origins of C++

C++ was developed by Bjarne Stroustrup of AT&T Bell Laboratories in the early 1980s, and is based on the C language. C++ is intended as an incremental improvement of C. Most C programs can be compiled using a C++ compiler. ANSI C++ : The American National Standards Institution (ANSI) provides ocial and generally accepted standard denitions of many programming languages, including C and C++ . Such standards are important. A program written only in ANSI C++ is guaranteed to run on any computer whose supporting software conforms to the ANSI standard. In other words, the standard guarantees that ANSI C++ programs are portable.

http://dis.unal.edu.co/profesores/ypinzon/2016699

14

Program Structure
#include <iostream.h> // other preprocessor directives function-definition 1; function-definition 2; . . . int main(){ declaration 1; declaration 2; . . . execution-statement 1; execution-statement 2; . . . return 0; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

15

1. Comments: In C++ comments can be included by using the double slash (//) - anything following the double slash will be ignored by the compiler but only to the end of the line. C-style comments (/* .... */) can also be used in C++ ; where multiple line comments are required. However it is better to stick to one form of comment throughout rather than mix dierent styles. 2. The header le: The header le included in the basic C++ program is iostream.h, rather than stdio.h which would be used in a basic C program. The le iostream.h provides the fundamental input and output denitions and functions for C++ . We will be using other header les 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 denition of a function called main.

http://dis.unal.edu.co/profesores/ypinzon/2016699

16

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, dened in a block only has scope (i.e. is only available) within that block. 5. Identiers: As we have seen, C++ programs can be written using many English words which are not reserved words as:

asm auto break case catch char class const

continue default delete do double else enum extern

float for friend goto if inline int long

new operator private protected public register return short

signed sizeof static struct switch template this throw

try typedef union unsigned virtual void volatile while

http://dis.unal.edu.co/profesores/ypinzon/2016699

17

Here is an example of a complete C++ program:


// This program prompts the user for two integers. // It then calculates the sum #include <iostream.h> int main(){ int x, y; cout << "Enter two numbers" << endl; cin >> x >> y; cout << "The sum of " << x << " and "; cout << y << " is " << x+y << endl; return 0; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

18

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 modiers (e.g. short, long, unsigned) are used to build more complex data types. Integral data types Data type [signed] char unsigned char short int unsigned short int unsigned int long unsigned long long long int unsigned long long int
These

Bytes 1 1 2 2 4 4 4 4 8 8

Values [-128, 127] [0, 255] [-32768, 32767] [0, 65535] [231, 231-1] [0, 4294967295] [-231, 231-1] [0, 4294967295] [-263, 263-1] [0, 264-1]

values depend on the particular system and are described in the header le limits.h

http://dis.unal.edu.co/profesores/ypinzon/2016699

19

Real numeric types Data type oat double long double


These

Bytes 4 8 16

Values 1.175494351038 3.402823471038 2.225073858507201410308 1.7976931344862315710308 104931 104932

values depend on the particular system and are described in the header le float.h

Boolen types Data type bool Bytes 1 Values true, false

http://dis.unal.edu.co/profesores/ypinzon/2016699

20

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.

User Dened Data Types Later in the course we will study the topic of data types in much more detail. We will see how the programmer may dene his own data types. This facility provides a powerful programming tool when complex structures of data need to be represented and manipulated.

http://dis.unal.edu.co/profesores/ypinzon/2016699

21

Operators
Arithmetic Operators
Operator ( ) * / % + Function parentheses multiply divide modulo plus minus Use (expr expr1 expr1 expr1 expr1 expr1 list) * expr2 / expr2 % expr2 + expr2 - expr2 Association L-to-R L-to-R L-to-R L-to-R L-to-R L-to-R

Example:
int main(){ int i=4, j=7, k=5, val1, val2; val1 val2 cout cout = i * j / 2 + k % 2 -3 ; = (i * j / ( 2 + k )) % 2 - 3; << "val1=" << val1 << endl; // outputs 12 << "val2=" << val2 << endl; // outputs -3

return 0; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

22

Equality, Relational and Logical Operators


Operator ! < <= > >= == != && || Function logical NOT less than less than or equal greater than greater than or equal equal not equal logic AND logic OR Use !expr expr1 expr1 expr1 expr1 expr1 expr1 expr1 expr1 Association R-to-L L-to-R L-to-R L-to-R L-to-R L-to-R L-to-R L-to-R L-to-R

< expr2 <= expr2 > expr2 >= expr2 == expr2 != expr2 && expr2 || expr2

Examples:
Expression (6 <= 6) && (5 < 3) (6 <= 6) || (5 < 3) (5 != 6) (5 < 3) && (6 <= 6) || (5 != 6) (5 < 3) && ((6 <= 6) || (5 != 6)) !((5 < 3) && ((6 <= 6) || (5 != 6))) true/false false true true true false true

http://dis.unal.edu.co/profesores/ypinzon/2016699

23

Bitwise Operators
Operator << >> & | Function bitwise NOT shift left shift right bitwise AND bitwise XOR bitwise OR Use expr expr1 << expr2 expr1 >> expr2 expr1 & expr2 expr1 expr2 expr1 | expr2 Association R-to-L L-to-R L-to-R L-to-R L-to-R L-to-R

Example:
// Assumes int unsigned int a unsigned int b unsigned int c unsigned int d unsigned int e unsigned int f unsigned int g are 4 bits = 11; // = ~a; // = a << 1; // = a >> 2; // = a & c; // = a ^ c; // = a | c; // 1011 0100 0110 0010 0010 1101 1111

http://dis.unal.edu.co/profesores/ypinzon/2016699

24

Assignment Operators
Operator = *= /= %= += -= <<= >>= &= |= = Function conventional assignment multiply and assign divide and assign modulo and assign add and assign subtract and assign shift left and assign shift right and assign AND and assign OR and assign XOR and assign Use lvalue = expr lvalue *= expr lvalue /= expr lvalue %= expr lvalue += expr lvalue -= expr lvalue <<= expr lvalue >>= expr lvalue &= expr lvalue |= expr lvalue = expr Association R-to-L R-to-L R-to-L R-to-L R-to-L R-to-L R-to-L R-to-L R-to-L R-to-L R-to-L

generally a op= b is equivalent to a = a op b. Examples:


Expression number += 1; total -= discount; bonus *= 2; time /= rush factor; change %= 100; amount *= count1 + count2; Equivalent to number = number + 1; total = total - discount; bonus = bonus * 2; time = time / rush factor; change = change % 100; amount = amount * (count1 + count2);

http://dis.unal.edu.co/profesores/ypinzon/2016699

25

Unary Operators
Operator ++ -sizeof sizeof ++ -+ Function post increment post decrement size of object size of type pre increment pre decrement unary plus unary minus Use lvalue++ lvalue-sizeof(expr) sizeof(type) ++lvalue --lvalue +lvalue -lvalue Association L-to-R L-to-R R-to-L R-to-L R-to-L R-to-L R-to-L R-to-L

Example:
int main(){ int x=5; cout << x << endl; cout << x++ << endl; cout << x << endl; x=5; cout << x << endl; cout << ++x << endl; cout << x << endl; return 0; }

// outputs 5 // outputs 5 // outputs 6 // outputs 5 // outputs 6 // outputs 6

http://dis.unal.edu.co/profesores/ypinzon/2016699

26

Operators
in decreasing precedence order Oper. ( ) ++ -sizeof sizeof ++ - ! + & * * / % + << >> < <= > >= Function parentheses post increment post decrement size of object size of type pre increment pre decrement bitwise NOT logical NOT unary minus unary plus address of dereference multiply divide modulo plus minus shift left shift right less than less than or equal greater than greater than or equal Use (expr list) lvalue++ lvalue-sizeof(expr) sizeof(type) ++lvalue --lvalue expr !expr -lvalue +lvalue &expr *expr expr1 * expr2 expr1 / expr2 expr1 % expr2 expr1 + expr2 expr1 - expr2 expr1 << expr2 expr1 >> expr2 expr1 < expr2 expr1 <= expr2 expr1 > expr2 expr1 >= expr2 Association L-to-R L-to-R L-to-R R-to-L R-to-L R-to-L R-to-L R-to-L R-to-L R-to-L R-to-L R-to-L R-to-L L-to-R L-to-R L-to-R L-to-R L-to-R L-to-R L-to-R L-to-R L-to-R L-to-R L-to-R

http://dis.unal.edu.co/profesores/ypinzon/2016699

27

Operators (Cont.)
in decreasing precedence order Oper. == != & | && || ?: << >> = *= /= %= += -= <<= >>= &= |= = Function equal not equal bitwise AND bitwise XOR bitwise OR logic AND logic OR alternative if stream insertion stream extraction conventional assignment multiply and assign divide and assign modulo and assign add and assign subtract and assign shift left and assign shift right and assign AND and assign OR and assign XOR and assign Use expr1 == expr2 expr1 != expr2 expr1 & expr2 expr1 expr2 expr1 | expr2 expr1 && expr2 expr1 || expr2 expr1 ? expr2 : expr3 expr1 << expr2 expr1 >> expr2 lvalue = expr lvalue *= expr lvalue /= expr lvalue %= expr lvalue += expr lvalue -= expr lvalue <<= expr lvalue >>= expr lvalue &= expr lvalue |= expr lvalue = expr Association L-to-R L-to-R L-to-R L-to-R L-to-R L-to-R L-to-R L-to-R L-to-R L-to-R R-to-L R-to-L R-to-L R-to-L R-to-L R-to-L R-to-L R-to-L R-to-L R-to-L R-to-L

http://dis.unal.edu.co/profesores/ypinzon/2016699

28

Type Conversion There is the need to convert one type to another. This is done using the syntax: (type) variable or type(variable) The following program is a complete example.
int main(){ float a=9.23, b; int c=3, d; b=(float)c; d=int(a); cout << "a=" cout << "b=" cout << "c=" cout << "d=" return 0; }

<< << << <<

a b c d

<< << << <<

endl; endl; endl; endl;

http://dis.unal.edu.co/profesores/ypinzon/2016699

29

Constant Variables we can specify that a variables value cannot be altered during the execution of a program with the reserved word const. Example:
#include <iostream.h> const double Pi = 3.14159; int main(){ double radius, area, circumference; cout << "Circle radius: "; cin >> radius; area = Pi * radius * radius; circumference = Pi * 2 * radius; cout << "Area of circle with radius " << radius << " is " << area << endl; cout << "Circumference is " << circumference << endl; return 0; }

Generally speaking, it is considered good practice to put constant declarations before the main program heading, and variable declarations afterwards, in the body of main.
http://dis.unal.edu.co/profesores/ypinzon/2016699

30

Control Structures
If and If/Else selection structure
if(Boolean-expression){ i-statement-1; i-statement-2; . . . } else { e-statement-1; e-statement-2; . . . }

if(Boolean-expression){ statement-1; statement-2; . . . }

http://dis.unal.edu.co/profesores/ypinzon/2016699

31

Example 1. Get a candidates grade and reports whether the candidate has passed the test or not. The pass mark is 50%.

#include <iostream.h> int main(){ int grade; cout << "Enter the grade: "; cin >> grade; if(grade >= 50){ cout << "Passed" << endl; } else { cout << "Failed" << endl; cout << "You must take this course again" << endl; } return 0; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

32

Example 2. Get a candidates age and test score, and reports whether the candidate has passed the test. It uses the following criteria: candidates between 0 and 14 years old have a pass mark of 50%, 15 and 16 year olds have a pass mark of 55%, over 16s have a pass mark of 60%:
int main(){ int candidate_age, candidate_score; cout << "Enter the candidates age: "; cin >> candidate_age; cout << "Enter the candidates score: "; cin >> candidate_score; if (candidate_age <= 14 && candidate_score >= 50) cout << "This candidate passed the test." << endl; else if (candidate_age <= 16 && candidate_score >= 55) cout << "This candidate passed the test." << endl; else if (candidate_score >= 60) cout << "This candidate passed the test." << endl; else cout << "This candidate failed the test." << endl; return 0; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

33

The switch multiple-selection structure

switch(selector){ case label-1: statement-1; break; . . . . . . . . . case label-N: statement-N; break; default: d-statement; }

Example. Get a candidates test score. If score has value 0, 1, 2, 3 or 4, print You have fail, if score has value 5, print You can do better, if score has value 6 or 7, print You have done quite well, and nally, if score has value 8, 9 or 10, print Well done!!!.

http://dis.unal.edu.co/profesores/ypinzon/2016699

34

int main(){ int score; cout << "Enter the score"; cin >> score; switch(score){ case 0: case 1: case 2: case 3: case 4: cout << "You have fail." << endl; break; case 5: cout << "You can do better." << endl; break; case 6: case 7: cout << "You have done quite well." << endl; break; case 8: case 9: case 10: cout << "Well done!!!." << endl; break; default: cout << "Wrong score." << endl; } return 0; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

35

A awed diamond is better than a common stone that is perfect. Chinese Proverb

Estructuras de Datos
Sesi on 2
Introducci on al C++ (2da Parte)
Yoan Pinz on, PhD Profesor Asociado Universidad Nacional de Colombia http://dis.unal.edu.co/profesores/ypinzon c 2009

Previous Session
Introduction to C++ (Part I)

The Origins of C++ Program Structure Data Types Operators Control Structures

http://dis.unal.edu.co/profesores/ypinzon/2016699

Session 2
Introduction to C++ (Part II)

Iteration Statements Break and Continue Arrays Pointers Dynamic Memory Allocation Functions Argument Passing Methods

http://dis.unal.edu.co/profesores/ypinzon/2016699

Iteration Statements
There are three types of iteration statements, which are informally known as loops:
The for-loop statement: for(init-statement; condition; expression) { loop-statement-1; loop-statement-2; . . . } The do-while-loop statement: do { loop-statement-1; loop-statement-2; . . . } while(condition); The while-loop statement: while(condition) { loop-statement-1; loop-statement-2; . . . }

To see how they work, let us use all three of then for the same purpose, namely to compute s = n i=1 i (s = 1 + 2 + 3 + . . . + n).
http://dis.unal.edu.co/profesores/ypinzon/2016699

With a for-loop statement:


#include <iostream.h> int main(){ int s=0, i, n; cout << "Enter n: "; cin >> n; for(i=1; i<=n; i++) s+=i; cout << "s= " << s << endl; return 0; }

With a for-loop statement:


#include <iostream.h> int main(){ int s=0, i, n; cout << "Enter n: "; cin >> n; i=1; while(i<=n){ s+=i; i++; } cout << "s= " << s << endl; return 0; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

With a do-while-loop statement:


#include <iostream.h> int main(){ int s=0, i, n; cout << "Enter n: "; cin >> n; i=1; do { s+=i; i++; } while(i<=n); cout << "s= " << s << endl; return 0; }

As you see there are not major dierences 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.
http://dis.unal.edu.co/profesores/ypinzon/2016699

Break and Continue


break: causes an immediate exit from a loop.

Example:
#include <iostream> int main(){ double s=0.0, x; cout << "Enter numbers, separated by blanks." << endl; cout << "They are added up as long as they are positive." << endl << endl; for (;;){ // Example of a forever-loop cin >> x; if (x <= 0) break; s += x; } cout << "Sum of the positive numbers that have "; cout << "been read: " << s << endl; return 0; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

continue: causes an immediate jump to the test for the continuation

of the loop. Example:


#include <iostream> int main(){ int i; for(i=1; i<=10; i++){ if(i==5) continue; cout << i << " "; } cout << endl << "Used continue to skip the printing of value 5" << endl; return 0; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

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 <iostream> int main(){ int i, a[10]; for (i=0; i<10; i++){ cout << "a[" << i+1 << "]= "; cin >> a[i]; } cout << "The same integers, in reverse order: "; for (i=9; i>=0; i--) cout << a[i] << " "; return 0; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

Initializing an array: 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 } }; 2 3 Values of a by row: 1 4 5 6 2 3 Values of b by row: 1 4 5 0 2 0 Values of c by row: 1 4 0 0

http://dis.unal.edu.co/profesores/ypinzon/2016699

Pointers
Variables that contains a memory address as its value. There are two important pointer operators namely:
Operator & * Function address of dereference Meaning returns the address of the object given by the operand returns the object that has the address given by the operand

Example:
#include <iostream.h> int main(){ int i=16; int * pi; pi = &i; cout << *pi << endl; // Outputs 16 return 0; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

10

Dynamic Memory Allocation


When the allocation is done by a run-time library invoked during program execution. Allocation of dynamic objects: Using the keyword new Example 1:
int * p = new int(128);

This line of code will allocate unnamed memory of type int and will initialize its value to 128. Example 2:
int * q = new int[128];

This line will allocate memory for an array of 128 elements of type int. Deallocation of dynamic objects: Using the keyword delete for single objects and delete[] for an array of objects. Example:
delete p; delete[] q;
http://dis.unal.edu.co/profesores/ypinzon/2016699

11

Functions
User-dened operation to facilitate the reuse of code within programs. a function basically consists of:

return type function name list of parameters body

return-type function-name(para1, para2, . . .) { . . . body-of-the-funtion; . . . }

http://dis.unal.edu.co/profesores/ypinzon/2016699

12

Argument Passing Methods


Passing by Value This is the default method, a copy of the arguments is made and passed to the corresponding parameters. The values of the arguments do not change. Example:
#include <iostream.h> void swap(int x, int y){ int temp; temp=x; x=y; y=temp; return; } int main(){ int a=4, b=5; swap(a, b); cout << "a=" << a << endl << "b=" << b << endl; return 0; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

13

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 <iostream.h> void swap(int* x, int* y){ int temp; temp=*x; *x=*y; *y=temp; return; } int main(){ int a=4, b=5; swap(&a, &b); cout << "a=" << a << endl << "b=" << b << endl; return 0; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

14

Learning is a treasure that will follow its owner everywhere. Chinese Proverb

Estructuras de Datos
Sesi on 3
Introducci on al C++ (3ra Parte)
Yoan Pinz on, PhD Profesor Asociado Universidad Nacional de Colombia http://dis.unal.edu.co/profesores/ypinzon c 2009

Previous Session
Introduction to C++ (Part II)

Iteration Statements Break and Continue Arrays Pointers Dynamic Memory Allocation Functions Argument Passing Methods

http://dis.unal.edu.co/profesores/ypinzon/2016699

Session 3
Introduction to C++ (Part III)

References Templates Inline Expansion Overloading Exception Handling Classes and Objects Constructors Destructor Inheritance

http://dis.unal.edu.co/profesores/ypinzon/2016699

References
A reference is an alias or a name to an existing object. They are similar to pointers in that they must be initialized before they can be used. Example 1:

#include <iostream.h> int main(){ int n = 10; int& r = n; r = - 10; cout << "n=" << n << endl; // Outputs -10 n = 7; cout << "r=" << r << endl; // Outputs 7 return 0; }
http://dis.unal.edu.co/profesores/ypinzon/2016699

Example 2:
#include <iostream.h> void swap(int& x, int& y){ int temp; temp=x; x=y; y=temp; return; } int main(){ int a=4, b=5; swap(a, b); cout << "a=" << a << endl << "b=" << b << endl; return 0; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

Templates
C++ templates may be used to parameterize functions or classes. Example:
#include <iostream.h> template <class T > void swap(T &x, T &y){ T t = x; x = y; y = t; } int main(){ int a = 10, b = 20; double d = 10.0, e = 20.0; char c = a, s = b; swap(a, cout << cout << cout << }
http://dis.unal.edu.co/profesores/ypinzon/2016699

b); swap(d, e); swap(c, "a=" << a << endl; cout "d=" << d << endl; cout "c=" << c << endl; cout

s); << "b=" << b << endl; << "e=" << e << endl; << "s=" << s << endl;

return 0;

Inline Expansion
Some functions are so small that the overhead of invoking the function call takes more time than the body of the function itself. C++ provides the inline keyword to inform the compiler to place the function inline rather than generate the code for calling the routine. Example 1:
inline int max(int x, int y) { return (x > y ? x : y); }

Example 3:
template<class T > inline T square(T x) { return x * x; }

Example 2:
inline void swap(int& x, int& y) { int temp = x; x = y; y = temp; return; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

Overloading
Simply, the same function name or operator symbol can be given several dierent denitions. The number and types of the arguments supplied to a function or operator tell the compiler which denition to use. Overloading is most often used to provide dierent denitions for member functions of a class. Overloading can also be used for functions that are not a member of any class. Example:
int Search(const int* data, const int key); int Search(const float* data, const float key); int Search(const double* data, const double key);

The compiler will ensure that the correct function is called based on the types of the arguments passed to Search(). When arguments do not exactly match the formal parameter types, the compiler will perform implicit type conversions (e.g., int to oat) in an attempt to nd a match.

http://dis.unal.edu.co/profesores/ypinzon/2016699

Exception Handling
An exception is just a run-time anomaly that a program may detect. Exceptions are thrown by the system or by the programmer and are caught using the try and catch keywords. Example:
try{ x = new long long int [n]; } catch(...){ cout << "Out of memory" << endl; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

Classes and Objects


C++ allows the declaration and denition of classes. Instances of classes are called objects. A class is separated into three access control sections: public, protected and private.
class Classic_Example{ public: // Data and methods accessible to // any user of the class protected: // Data and methods accessible to // class methods, derived classes, and // friends only private: // Data and methods accessible to class // methods and friends only };

A C++ class is an extension to the struct type specier in C.


http://dis.unal.edu.co/profesores/ypinzon/2016699

Example:

1 2 3 4 5 6 7 8 9

class Point{ int _x, _y; // Point Coordinates public: void setX(const int void setY(const int int getX() { return int getY() { return }; void Point::setX(const int val){ _x = val; } void Point::setY(const int val){ _y = val; }

16 17 18 19

int main(){ Point mypoint;

// Declaration

val); val); _x; } _y; }

20 21 22 23 24 25 26 27

mypoint.setX(1); mypoint.setY(2); int x = mypoint.getX(); int y = mypoint.getY(); cout << "x =" << x << endl; cout << "y =" << y << endl; return 0; }

10 11 12

13 14 15

http://dis.unal.edu.co/profesores/ypinzon/2016699

10

This example declares a class Point and dene an object called mypoint. You can think of a class denition as a structure denition with functions (or methods). Currently, we need to call the set method to initialize a point object. However, we would like to initialize the point when we dene it. We therefore use special methods called constructors.

http://dis.unal.edu.co/profesores/ypinzon/2016699

11

Constructors
Constructors are methods which are used to initialize an object at its denition time. We extend our class Point such that it initializes a point to coordinates (0, 0):
class Point{ int _x, _y; public: Point(){ // Default _x = _y = 0; } void setX(const int void setY(const int int getX() { return int getY() { return }; Constructor val); val); _x; } _y; }

Constructors have the same name of the class. They have no return value. As other methods, they can take arguments. For example, we may want to initialize a point to other coordinates than (0, 0). We therefore dene a second constructor taking two integer arguments within the class:
http://dis.unal.edu.co/profesores/ypinzon/2016699

12

class Point{ int _x, _y; public: Point(){ // Default Constructor _x = _y = 0; } Point(const int x, const int y){ // Second Constructor _x = x; _y = y; } void setX(const int val); void setY(const int val); int getX() { return _x; } int getY() { return _y; } };

Constructors are implicitly called when we dene objects of their classes:


Point apoint; Point bpoint(12, 34);

With constructors we are able to initialize our objects at denition time.


http://dis.unal.edu.co/profesores/ypinzon/2016699

13

If we want to create a point from another point, hence, copying the properties of one object to a newly created one, we create a copy constructor. For example:
class Point{ int _x, _y; public: Point(){ // Default Constructor _x = _y = 0; } Point(const int x, const int y){ // Second Constructor _x = x; _y = y; } Point(const Point &from){ // Copy Constructor _x = from._x; _y = from._y; } void setX(const int val); void setY(const int val); int getX() { return _x; } int getY() { return _y; } };

http://dis.unal.edu.co/profesores/ypinzon/2016699

14

The third constructor takes a constant reference to an object of class Point as an argument and assigns x and y the corresponding values of the provided object. The copy constructor is called in the following cases:
Point bpoint(apoint); Point cpoint = apoint;

http://dis.unal.edu.co/profesores/ypinzon/2016699

15

Destructor
The destructor is the mechanism which automatically destroys an object when it gets invalid (for example, because of leaving its scope). Example:
1 2 3 4 5 6 7 8 9 10 11 12 13

class Point{ int _x, _y; public: // Default Constructor Point(){ _x = _y = 0; } // Second Constructor Point(const int x, const int y){ _x = x; _y = y; }

14 15 16 17 18 19 20 21 22 23 24 25

// Copy Constructor Point(const Point &from){ _x = from._x; _y = from._y; } // Destructor ~Point() { /* Nothing to do! */ } void setX(const int val); void setY(const int val); int getX() { return _x; } int getY() { return _y; } };

http://dis.unal.edu.co/profesores/ypinzon/2016699

16

Inheritance
In C++ this word is replaced by a colon. As an example lets design a class for 3D points. Of course we want to reuse our already existing class Point. We start designing our class as follows:
class Point3D : public Point{ int _z; public: Point3D(){ // Default Constructor setX(0); setY(0); _z = 0; } Point3D(const int x, const int y, const int z){ // Second Constructor setX(x); setY(y); _z = z; } ~Point3D() { /* Nothing to do */ } // Destructor int getZ() { return _z; } void setZ(const int val) { _z = val; } };

http://dis.unal.edu.co/profesores/ypinzon/2016699

17

A class species two interfaces: one to the users of the class (the public interface) and another to implementors of derived classes (the union of public and protected parts). Inheritance works almost identically. When the inheritance is public, the public interface of the base class becomes part of the public interface to users of the derived class. When the inheritance is protected, the public and protected parts of the base class are accessible to the member functions of the derived classes, but not to general users of the derived classes. Finally, when inheritance is private, the public and protected parts of the base class are only accessible to the implementor of the class, but not to users or derived classes. Inheritance public private protected Base Class public protected public protected public protected Derived Class public protected private private protected protected

http://dis.unal.edu.co/profesores/ypinzon/2016699

18

If your strength is small, dont carry heavy burdens. If your words are worthless, dont give advice. Chinese Proverb

Estructuras de Datos
Sesi on 4
Methods of Representing Data
Yoan Pinz on, PhD Profesor Asociado Universidad Nacional de Colombia http://dis.unal.edu.co/profesores/ypinzon c 2009

Previous Session
Introduction to C++ (Part III)

References Templates Inline Expansion Overloading Exception Handling Classes and Objects Constructors Destructor Inheritance

http://dis.unal.edu.co/profesores/ypinzon/2016699

Session 4
Preliminaries Methods of Representing Data Formula-based Representation Linked Representation Indirect Addressing Representation Simulating Pointers Representation LinearList Data Structure Formula-based Representation

http://dis.unal.edu.co/profesores/ypinzon/2016699

Preliminaries
Data Structure: data object along with the relationship that exist among the instances and elements, and which are provided by specifying the functions of interest. Our main concern will be:
The representation of data objects (actually of their instances)

The representation should facilitate an ecient implementation of functions ADT - Abstract Data Type: A general way that provides a specication of the instances as well as of the operations that are to be performed. This representation is completely independent of the implementation.

http://dis.unal.edu.co/profesores/ypinzon/2016699

Methods of Representing Data


Formula-based Representation: Uses a mathematical formula to determine where (i.e., the memory address) to store each element of a data object.

[0]

[1]

[2]

[3]

[4]

...

[MaxSize-1]

FE300

5 2 4 8 9
element FE300

...
length 5

http://dis.unal.edu.co/profesores/ypinzon/2016699

Linked Representation: The elements may be stored in any arbitrary set of memory locations. Each element keeps explicit information about the location of the next element called pointer (or link).

first

link data

http://dis.unal.edu.co/profesores/ypinzon/2016699

Indirect Addressing Representation: Is a combination of formulabased and linked representation where the addresses of the elements are collected into a table.

elements

table

[0]

[1]

[2]

[3]

[4]

http://dis.unal.edu.co/profesores/ypinzon/2016699

Simulating Pointers Representation: Similar to the linked list representation. However, pointers are replaced by integers.

firstNode node next element first=2


[0]

2
[1] [2] [3] [4] [5] [6] [7] [8] [9]

-1

8 5

4 9 2

5
node[2]

2
node[7]

4
node[5]

8
node[1]

-1

node[6]
7

http://dis.unal.edu.co/profesores/ypinzon/2016699

LinearList Data Structure


Preliminaries

A linear list is a data object whose instances are of the form (e1, e2, . . . , en ) where n is a nite natural number. The ei terms are the elements of the list and n is the length. A linear list may be dened as an abstract data type (ADT) as follows:
AbstractDataType LinearList { instances: ordered nite collection of zero or more elements operations: Create(): create an empty linear list Destroy(): erase the list IsEmpty(): return true if the list is empty. false otherwise Length(): return the number of elements in the list Find(k, x): return the kth element of the list in x,return false is no kth element Search(x): return the position of x in the list, return 0 if is not in the list Delete(k, x): delete the kth element and return it in x, returns the modied list Insert(k, x): insert x just after the kth element, returns the modied linear list Output(out): put the list into the output stream out }
http://dis.unal.edu.co/profesores/ypinzon/2016699

LinearList Data Structure


Formula-Based Representation

A formula-based representation uses an array to represent the instances of a linearlist. A simple formula is used to determine the location of each element: location(i) = i 1

This means that the ith element of the list (if it exists) is at position i 1 of the array.

http://dis.unal.edu.co/profesores/ypinzon/2016699

Class denition of LinearList

template<class T> class LinearList{ public: LinearList(int MaxListSize = 10); // constructor LinearList(){delete [] element;} // destructor bool IsEmpty() const {return length == 0;} int Length() const {return length;} bool Find(int k, T& x) const; // return the kth element of list in x int Search(const T& x) const; // return position of x LinearList<T>& Delete(int k, T& x); // delete kth element and return in x LinearList<T>& Insert(int k, const T& x); // insert x just after kth element void Output(ostream& out) const; private: int length; int MaxSize; T *element; // dynamic 1D array };
http://dis.unal.edu.co/profesores/ypinzon/2016699

10

An instance of this class (LinearList L of integers) with lenght=5 and MaxSize=10 will look like this:

[0]

[1]

[2]

[3]

[4]

[5]

[6]

[7]

[8]

[9]

FE300

5 2 4 8 9
element FE300 MaxSize 10 length 5

http://dis.unal.edu.co/profesores/ypinzon/2016699

11

Constructor

template<class T> LinearList<T>::LinearList(int MaxListSize) { // Constructor for formula-based linear list. MaxSize = MaxListSize; element = new T[MaxSize]; length = 0; }

Time Complexity: O(1) + time required by new. Remark: Time Complexity of destructor is O(1).

http://dis.unal.edu.co/profesores/ypinzon/2016699

12

IsEmpty, Length, Find, Search


template<class T> bool LinearList<T>::Find(int k, T& x) const { // Set x to the kth element of the list. Return false if no kth; true otherwise. if (k < 1 || k > length) return false; // no kth x = element[k - 1]; return true; } template<class T> int LinearList<T>::Search(const T& x) const { // Locate x. Return position of x if found. Return 0 if x not in list. for (int i = 0; i < length; i++) if (element[i] == x) return ++i; return 0; }

Time Complexities: IsEmpty : Find : (1) (1) Length Search : : (1) O(n)
13

http://dis.unal.edu.co/profesores/ypinzon/2016699

Deleting the kth element If the list doesnt have a kth element, then throw an exception (OutOfBounds). Otherwise, move elements ek+1, ek+2, . . . , en one position to the left and reduce the value of n (length).
template<class T> LinearList<T>& LinearList<T>::Delete(int k, T& x) { // Set x to the kth element and delete it. // Throw OutOfBounds exception if no kth element. if (Find(k, x)) { // move elements k+1, ..., down for (int i = k; i < length; i++) element[i-1] = element[i]; length--; return *this; } else throw OutOfBounds(); }

Time Complexity : s :

((n k)s), bytes per element


http://dis.unal.edu.co/profesores/ypinzon/2016699

14

Inserting after the kth element Move elements ek+1, ek+2, . . . , en one position to the right, insert the new element at position k + 1, and increase the value of n (length).
template<class T> LinearList<T>& LinearList<T>::Insert(int k, const T& x) { // Insert x after the kth element. // Throw OutOfBounds exception if no kth element. // Throw NoMem exception if list is already full. if (k < 0 || k > length) throw OutOfBounds(); if (length == MaxSize) throw NoMem(); // move one up for (int i = length-1; i >= k; i--) element[i+1] = element[i]; element[k] = x; length++; return *this; }

Time Complexity :

((n k)s).

http://dis.unal.edu.co/profesores/ypinzon/2016699

15

Outputting the list


template<class T> void LinearList<T>::Output(ostream& out) const{ // Put the list into the stream out. for (int i = 0; i < length; i++) out << element[i] << " }

";

// overload << to actually print the list template <class T> ostream& operator<<(ostream& out, const LinearList<T>& x){ x.Output(out); return out; }

Time Complexity : (n).

http://dis.unal.edu.co/profesores/ypinzon/2016699

16

Testing LinearList Class


File llist.cc
#include <iostream.h> #include "llist.h" #include "xcept.h" void main(void){ try{ LinearList<int> L(5); cout << "Length = " << L.Length() << endl; cout << "IsEmpty = " << L.IsEmpty() << endl; L.Insert(0,2).Insert(1,6); cout << "List is " << L << endl << "IsEmpty = " << L.IsEmpty() << endl; int z; L.Find(1,z); cout << "First element is " << z << endl << "Length = " << L.Length() << endl; L.Delete(1,z); cout << "Deleted element is " << z << endl << "List is " << L << endl; } catch (...){ cerr << "An exception has occurred" << endl; } }

http://dis.unal.edu.co/profesores/ypinzon/2016699

17

File llist.out
Length = 0 IsEmpty = 1 List is 2 6 IsEmpty = 0 First element is 2 Length = 2 Deleted element is 2 List is 6

http://dis.unal.edu.co/profesores/ypinzon/2016699

18

The one who turns in his own, shall dig two graves. Chinese Proverb

Estructuras de Datos
Sesi on 5
Linked Representation
Yoan Pinz on, PhD Profesor Asociado Universidad Nacional de Colombia http://dis.unal.edu.co/profesores/ypinzon c 2009

Previous Session
Preliminaries Methods of Representing Data Formula-based Representation Linked Representation Indirect Addressing Representation Simulating Pointers Representation LinearList Data Structure Formula-based Representation

http://dis.unal.edu.co/profesores/ypinzon/2016699

Session 5
LinearList Data Structure Linked Representation

http://dis.unal.edu.co/profesores/ypinzon/2016699

Methods of Representing Data


Recalling

Formula-based Representation: Uses a mathematical formula to determine where (i.e., the memory address) to store each element of a data object.

[0]

[1]

[2]

[3]

[4]

...

[MaxSize-1]

FE300

5 2 4 8 9
element FE300

...
length 5

http://dis.unal.edu.co/profesores/ypinzon/2016699

Linked Representation: The elements may be stored in any arbitrary set of memory locations. Each element keeps explicit information about the location of the next element called pointer (or link).

first

link data

http://dis.unal.edu.co/profesores/ypinzon/2016699

LinearList Data Structure


Linked Representation Each element of an instance of a data object is represented as a group

of memory locations called cell or node.


The elements may be stored in any arbitrary set of memory locations. 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

9
http://dis.unal.edu.co/profesores/ypinzon/2016699

Singly linked list or chain


5

Class denition for a chain

1 2 3 4 5 6 7 8

template <class T> class ChainNode{ friend Chain<T>; private: T data; ChainNode<T> *link; };

9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

template<class T> class Chain{ public: Chain(){first = 0;} Chain(); bool IsEmpty() const {return first == 0;} int Length() const; bool Find(int k, T& x) const; int Search(const T& x) const; Chain<T>& Delete(int k, T& x); Chain<T>& Insert(int k, const T& x); void Output(ostream& out) const; private: ChainNode<T> *first; // pointer to first node };

Note: this representation does not specify the maximum size!

http://dis.unal.edu.co/profesores/ypinzon/2016699

An instance of this class (Chain L of integers) with lenght=5 will look like this:
first

L
Link Field Data Field

9
FE30

first FE30

FF10 link FE45 data FF26 link 0 data

link FF10 data

5
FE45 link FA10 data FA10 link FF26 data

http://dis.unal.edu.co/profesores/ypinzon/2016699

Destructor

template<class T> Chain<T>::Chain() { // Chain destructor. Delete all nodes in chain. ChainNode<T> *next; // next node while (first){ next = first->link; delete first; first = next; } }

Time Complexity : (n)

http://dis.unal.edu.co/profesores/ypinzon/2016699

Length

template<class T> int Chain<T>::Length() const { // Return the number of elements in the chain. ChainNode<T> *current = first; int len = 0; while (current){ len++; current = current->link; } return len; }

Time Complexity : (n)

http://dis.unal.edu.co/profesores/ypinzon/2016699

Find

template<class T> bool Chain<T>::Find(int k, T& x) const { // Set x to the kth element in the chain. // Return false if no kth; return true otherwise. if (k < 1) return false; ChainNode<T> *current = first; int index = 1; // index of current while (index < k && current){ current = current->link; index++; } if (current){ x = current->data; return true; } return false; // no kth element }

Time Complexity : (k)


http://dis.unal.edu.co/profesores/ypinzon/2016699

10

Search

template<class T> int Chain<T>::Search(const T& x) const { // Locate x. Return position of x if found. // Return 0 if x not in the chain. ChainNode<T> *current = first; int index = 1; // index of current while (current && current->data != x){ current = current->link; index++; } if (current) return index; return 0; }

Time Complexity : (n)

http://dis.unal.edu.co/profesores/ypinzon/2016699

11

Outputting a Chain

template<class T> void Chain<T>::Output(ostream& out) const { //Insert the chain elements into the stream out. ChainNode<T> *current; for (current=first; current; current=current->link) out << current->data << " "; } // overload << template <class T> ostream& operator<<(ostream& out, const Chain<T>& x){ x.Output(out); return out; }

Time Complexity : (n)

http://dis.unal.edu.co/profesores/ypinzon/2016699

12

Deleting the kth element

first

link data
1

...
k-1 k k+1

...
n

(a) Before
first

link data
1

...
k-1 k

...
n+1

(b) After
Time Complexity : (k)
http://dis.unal.edu.co/profesores/ypinzon/2016699

13

Delete
template<class T> Chain<T>& Chain<T>::Delete(int k, T& x) { // Set x to the kth element and delete it. // Throw OutOfBounds exception if no kth element. if (k < 1 || !first) throw OutOfBounds(); // no kth // p will eventually point to kth node ChainNode<T> *p = first; // move p to kth & remove from chain if (k == 1) // p already at kth first = first->link; // remove else { // use q to get to k-1st ChainNode<T> *q = first; for (int index = 1; index < k - 1 && q; index++) q = q->link; if (!q || !q->link) throw OutOfBounds(); // no kth p = q->link; // kth q->link = p->link; // remove from chain } // save kth element and free node p x = p->data; delete p; return *this; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

14

Inserting after the kth element If k=0


first ...
1 2 3 n

link data

New Node

(a) Before
first ...
2 3 4 n+1

link data

(b) After
http://dis.unal.edu.co/profesores/ypinzon/2016699

15

If k=0

first
1

...
k k+1

...
n

link data

New Node

(a) Before
first
1

...
k k+2

...
n+1

link data

k+1

(b) After
http://dis.unal.edu.co/profesores/ypinzon/2016699

16

Insert
template<class T> Chain<T>& Chain<T>::Insert(int k, const T& x) { // Insert x after the kth element. Throw OutOfBounds exception if no kth element. // Pass NoMem exception if inadequate space. if (k < 0) throw OutOfBounds(); // p will eventually point to kth node ChainNode<T> *p = first; for (int index = 1; index < k && p; index++) p = p->link; // move p to kth if (k > 0 && !p) throw OutOfBounds(); // no kth // insert ChainNode<T> *y = new ChainNode<T>; y->data = x; if (k){ // insert after p y->link = p->link; p->link = y; } else{ // insert as first element y->link = first; first = y; } return *this; }

Time Complexity : (k)


http://dis.unal.edu.co/profesores/ypinzon/2016699

17

Testing Chain Class


File chain.cc:
#include <iostream.h> #include "chain.h" void main(void){ try{ Chain<int> L; cout << "Length = " << L.Length() << endl; cout << "IsEmpty = " << L.IsEmpty() << endl; L.Insert(0,2).Insert(1,6); cout << "List is " << L << endl << "IsEmpty = " << L.IsEmpty() << endl; int z; L.Find(1,z); cout << "First element is " << z << endl << "Length = " << L.Length() << endl; L.Delete(1,z); cout << "Deleted element is " << z << endl << "List is " << L << endl; } catch (...){ cerr << "An exception has occurred" << endl; } }

http://dis.unal.edu.co/profesores/ypinzon/2016699

18

File chain.out:

Length = 0 IsEmpty = 1 List is 2 6 IsEmpty = 0 First element is 2 Length = 2 Deleted element is 2 List is 6

http://dis.unal.edu.co/profesores/ypinzon/2016699

19

Compering Array-based and Linked Implementations


Arrays are easy to use, but they have a xed length Can you predict the maximum number of element in the list? Will an array waste storage? (Will you rarely use most of the array indices?) Linked lists do not have a xed length An array-based implementation does not waste space storing pointers to the next item You can access any array item directly with equal access time (average access time is constant), whereas you must traverse a linked list to access the ith node (average access time is proportional to the length of the list)

http://dis.unal.edu.co/profesores/ypinzon/2016699

20

Inserting/Deleting elements in an array based implementation requires the movement of other elements in the array (average insertion/deletion time is proportional to the length of the list) Inseting/Deleting elements in a linked implementation does not require the movement of other elements in the array, however the appropriate position has to be found (which on average is proportional to the length of the list)

If most of the activity is on inserting/deleting elements, there is little dierence in performance (theoretically), although arrays may require more time if the list length exceeds the bounds of the array. If most of the activity is on querying the list by their position, then the array-based implementation will have better performance.

http://dis.unal.edu.co/profesores/ypinzon/2016699

21

He who cannot agree with his enemies is controlled by them. Chinese Proverb

Estructuras de Datos
Sesi on 6
Stack Data Structure
Yoan Pinz on, PhD Profesor Asociado Universidad Nacional de Colombia http://dis.unal.edu.co/profesores/ypinzon c 2009

Previous Session
LinearList Data Structure Linked Representation

http://dis.unal.edu.co/profesores/ypinzon/2016699

Session 6
Stack Data Structure

Formula-based Representation Implementation using Inheritance Customised Implementation Linked Representation Implementation using Inheritance Customised Implementation Applications Parentheses Matching Switchbox Routing

http://dis.unal.edu.co/profesores/ypinzon/2016699

Stacks Data Structure


A stack is a linear list in which insertions (also called additions) and deletions take place at the same end. This end is called the top. The other end is called the bottom.

top

bottom
2 3

e e e
1

... ei

... en- en
1

insertions deletions bottom top


2 3

e e e
1

... ei

... en- en
1

insertions deletions
In other words, a stack is a LIFO (last-in-rst out) list. Lists of this type appear frequently in computing.
http://dis.unal.edu.co/profesores/ypinzon/2016699

Stack Data Structure


Abstract Data Type (ADT) AbstractDataType Stack { instances: linear list of elements; one end called the bottom; the other is the top; operations: Create(): create an empty stack Destroy(): erase the stack IsEmpty(): return true if the stack is empty. false otherwise. IsFull(): return true if the stack is full. false otherwise. Top(): return top element of stack Add(x): add element x to the stack Delete(x): delete top element from stack and put it in x

http://dis.unal.edu.co/profesores/ypinzon/2016699

Stacks Data Structure


Some Observations

Stack is a specialized or restricted version of a more general data object linear list. Every instance of the data object stack is also an instance of the data object linear list. Moreover, all the stack operations can be performed as linear list operations. As a result of these observations, we will dened the stack class as a class which inherit all the data member and function from the linear list class. We will also use two methods of representation. namely, formulabased and linked representation.

http://dis.unal.edu.co/profesores/ypinzon/2016699

Stack Data Structure


Formula-based Representation

Implementation using Inheritance Customised Implementation

http://dis.unal.edu.co/profesores/ypinzon/2016699

Implementing Stack using Inheritance

Basic design decision: designate the left end of the list as the bottom and the right end as the top

http://dis.unal.edu.co/profesores/ypinzon/2016699

Class Denition
template<class T> class Stack : private LinearList<T> { // LIFO objects public: Stack(int MaxStackSize = 10) : LinearList<T> (MaxStackSize) {} bool IsEmpty() const {return LinearList<T>::IsEmpty();} bool IsFull() const {return (Length() == GetMaxSize());} T Top() const {if (IsEmpty()) throw OutOfBounds(); T x; Find(Length(), x); return x;} Stack<T>& Add(const T& x) {Insert(Length(), x); return *this;} Stack<T>& Delete(T& x) {LinearList<T>::Delete(Length(), x); return *this;} }; template<class T> class LinearList{ public: // ... protected: int GetMaxSize() const {return MaxSize;} private: // ... };

http://dis.unal.edu.co/profesores/ypinzon/2016699

Complexity of Operations

Constructor

: : : : :

(1), if T is built-in. O(n), if T is user-dened. (1), if T is built-in. O(n), if T is user-dened. (1)

Destructor

Other operations

http://dis.unal.edu.co/profesores/ypinzon/2016699

Implementing Stack as a Base Class


template<class T> class Stack{ // LIFO objects public: Stack(int MaxStackSize = 10); Stack() {delete [] stack;} bool IsEmpty() const {return top == -1;} bool IsFull() const {return top == MaxTop;} T Top() const; Stack<T>& Add(const T& x); Stack<T>& Delete(T& x); private: int top; // current top of stack int MaxTop; // max value for top T *stack; // element array };

http://dis.unal.edu.co/profesores/ypinzon/2016699

10

Constructor, Top

template<class T> Stack<T>::Stack(int MaxStackSize) { // Stack constructor. MaxTop = MaxStackSize - 1; stack = new T[MaxStackSize]; top = -1; }

template<class T> T Stack<T>::Top() const { // Return top element. if (IsEmpty()) throw OutOfBounds(); // Top fails else return stack[top]; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

11

Add, Delete
template<class T> Stack<T>& Stack<T>::Add(const T& x) { // Add x to stack. if (IsFull()) throw NoMem(); // add fails stack[++top] = x; return *this; }

template<class T> Stack<T>& Stack<T>::Delete(T& x) { // Delete top element and put in x. if (IsEmpty()) throw OutOfBounds(); // delete fails x = stack[top--]; return *this; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

12

Complexity of Operations

Constructor

: : : : :

(1), if T is built-in. O(n), if T is user-dened. (1), if T is built-in. O(n), if T is user-dened. (1)

Destructor

Other operations

http://dis.unal.edu.co/profesores/ypinzon/2016699

13

Stack Data Structure


Linked Representation

Implementation using Inheritance Customised Implementation

In both cases, we have to decide which end of the chain will be the top of the stack and which the bottom.

http://dis.unal.edu.co/profesores/ypinzon/2016699

14

Implementing Stack using Inheritance


template<class T> class LinkedStack : private Chain<T>{ public: bool IsEmpty() const {return Chain<T>::IsEmpty();} bool IsFull() const; T Top() const {if (IsEmpty()) throw OutOfBounds(); T x; Find(1, x); return x;} LinkedStack<T>& Add(const T& x) {Insert(0, x); return *this;} LinkedStack<T>& Delete(T& x) {Chain<T>::Delete(1, x); return *this;} }; template<class T> bool LinkedStack<T>::IsFull() const { //Is stack full? try{ ChainNode<T> *p = new ChainNode<T>; delete p; return false; } catch (NoMem) {return true;} }

http://dis.unal.edu.co/profesores/ypinzon/2016699

15

Complexity of Operations

Constructor Destructor Other operations

: : :

(1) (n) (1)

http://dis.unal.edu.co/profesores/ypinzon/2016699

16

Implementing Stack as a Base Class


template <class T> class Node{ friend LinkedStack<T>; private: T data; Node<T> *link; }; template<class T> class LinkedStack{ public: LinkedStack() {top = 0;} LinkedStack(); bool IsEmpty() const {return top == 0;} bool IsFull() const; T Top() const; LinkedStack<T>& Add(const T& x); LinkedStack<T>& Delete(T& x); private: Node<T> *top; // pointer to top node };

http://dis.unal.edu.co/profesores/ypinzon/2016699

17

Destructor, IsFull
template<class T> LinkedStack<T>::LinkedStack() { // Stack destructor.. Node<T> *next; while (top){ next = top->link; delete top; top = next; } } template<class T> bool LinkedStack<T>::IsFull() const { // Is the stack full? try { Node<T> *p = new Node<T>; delete p; return false; } catch (NoMem) {return true;} }
http://dis.unal.edu.co/profesores/ypinzon/2016699

18

Top, Add

template<class T> T LinkedStack<T>::Top() const { // Return top element. if (IsEmpty()) throw OutOfBounds(); return top->data; }

template<class T> LinkedStack<T>& LinkedStack<T>::Add(const T& x) { // Add x to stack. Node<T> *p = new Node<T>; p->data = x; p->link = top; top = p; return *this; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

19

Delete

template<class T> LinkedStack<T>& LinkedStack<T>::Delete(T& x) { // Delete top element and put it in x. if (IsEmpty()) throw OutOfBounds(); x = top->data; Node<T> *p = top; top = top->link; delete p; return *this; }

Time Complexity of Operations Constructor Destructor Other operations : : : (1) (n) (1)

http://dis.unal.edu.co/profesores/ypinzon/2016699

20

Stack Application
Parentheses Matching

How do we match parentheses in an expression?


(((a+b)*c+d*e)/((f+g)-h+i)) (a*(a+b))/(b+d)

http://dis.unal.edu.co/profesores/ypinzon/2016699

21

Parentheses Matching
Strategy

Scan expression from left to right When a left parenthesis is encountered, add its position to the stack When a right parenthesis is encountered, remove matching position from stack

http://dis.unal.edu.co/profesores/ypinzon/2016699

22

Parentheses Matching
Example


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

- h ) )

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

( ( ( a + b ) * c + d * e ) / (

f + g )

(3 7) (2 14) (17 21) (16 24) (1 25)

http://dis.unal.edu.co/profesores/ypinzon/2016699

23

Parentheses Matching
Implementation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

void PrintMatchedPairs(char *expr){ Stack<int> s(MaxLength); int j, length = strlen(expr); // scan expression expr for ( and ) for (int i = 1; i <= length; i++){ if (expr[i - 1] == () s.Add(i); else if (expr[i - 1] == )) try { s.Delete(j); // unstack match cout << j << << i << endl; } catch (OutOfBounds) { cout << "No match for right parenthesis" << " at " << i << endl; } } // remaining ( in stack are unmatched while (!s.IsEmpty()){ s.Delete(j); cout << "No match for left parenthesis at " << j << endl; } }

http://dis.unal.edu.co/profesores/ypinzon/2016699

24

File paren.cc:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

#include #include #include #include

<iostream.h> <string.h> <stdio.h> "stack.h"

const int MaxLength = 100; // max expression length void PrintMatchedPairs(char *expr){ // Presented in previous page } void main(void){ char expr[MaxLength]; cout << "Type an expression of length at most " << MaxLength << endl; cin.getline(expr, MaxLength); cout <<"The pairs of matching parentheses in" << endl; puts(expr); cout << "are" << endl; PrintMatchedPairs(expr); }

http://dis.unal.edu.co/profesores/ypinzon/2016699

25

Stack Application
Switchbox Routing

The switchbox routing problem arises in the fabrication of computer chips, where certain components need to be connected to other components.
1 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 2 3 4 5 6 7 8 9 10 11 12 13 14

Routing region

15 16 17 18 19 20

http://dis.unal.edu.co/profesores/ypinzon/2016699

26

Switchbox Routing
Example
3 4 5 6 1 2 7 8 9 10

Net={ 1, 2, 3, 4, 4, 3, 2, 5, 5, 1 }
1 10 2 3 4

Routable !
9 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 10 2 3 4

9 8

5 7 6

NOT Routable!

http://dis.unal.edu.co/profesores/ypinzon/2016699

27

Switchbox Routing
Implementation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

bool CheckBox(int net[], int n) { // Determine whether the switch box is routable. Stack<int> *s = new Stack<int> (n); for (int i = 0; i < n; i++) // scan nets clockwise if (!s->IsEmpty()) { // check with top net if (net[i] == net[s->Top()]) { // net[i] routable, delete from stack int x; s->Delete(x); } else s->Add(i); } else s->Add(i); // any unrouted nets left? if (s->IsEmpty()) { // no nets remain delete s; cout << "Switch box is routable" << endl; return true; } delete s; cout << "Switch box is not routable" << endl; return false; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

28

File switch.cc:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

#include <iostream.h> #include "stack.h" bool CheckBox(int net[], int n){ // Presented in previous page } void main(void){ int *net, n; cout << "Type number of pins in switch box " << endl; cin >> n; try{ net = new int [n]; cout << "Type net numbers for pins 1 through " << n << endl; for (int i = 0; i<n; i++) cin >> net[i]; CheckBox(net, n); } catch (NoMem){ cout << "Insufficient memory" << endl; } }

http://dis.unal.edu.co/profesores/ypinzon/2016699

29

A wise man makes his own decisions, an ignorant man follows the public opinion. Chinese Proverb

Estructuras de Datos
Sesi on 7
Queue Data Structure
Yoan Pinz on, PhD Profesor Asociado Universidad Nacional de Colombia http://dis.unal.edu.co/profesores/ypinzon c 2009

Previous Session
Stack Data Structure

Formula-based Representation Implementation using Inheritance Customised Implementation Linked Representation Implementation using Inheritance Customised Implementation Applications Parentheses Matching Switchbox Routing

http://dis.unal.edu.co/profesores/ypinzon/2016699

Session 7
Queue Data Structure Formula-based Representation Linked Representation Applications Image-Component Labeling Lees Wire Router

http://dis.unal.edu.co/profesores/ypinzon/2016699

Queue Data Structure


A queue is a special case of linear list where insertions and deletions take place at dierent ends rear: end at which a new element is added. front: end at which an element is deleted.

front

rear
2 3

e e e
1

... ei

... en- en
1

deletions

insertions

In other words, a queue is a FIFO (rst-in-rst-out) list.

http://dis.unal.edu.co/profesores/ypinzon/2016699

Queue Data Structure


Abstract Data Type (ADT) AbstractDataType Queue { instances: linear list of elements; insertions are performed at the rear; and deletions at the front. operations Create(): create an empty queue Destroy(): erase the queue IsEmpty(): return true if the queue is empty. false otherwise IsFull(): return true if the queue is full. false otherwise First(): return the rst element of the queue Last(): return the last element of the queue Add(x): insert element x to the queue Delete(x): delete the front element of the queue and put it in x

http://dis.unal.edu.co/profesores/ypinzon/2016699

Queue Data Structure


Formula-based Representation

We can use three dierent approaches: 1) Using the formula location(i) = i 1

front

rear

front rear

front

rear

F A T
[0] [1] [2]

...

A T
[0] [1]

...

A T E
[0] [1] [2]

...

Empty queue: rear = -1 Addition:

Deletion:

rear = rear + 1 queue[rear] = new element O(1) time


Shift all elements one position to the left. (n) time

http://dis.unal.edu.co/profesores/ypinzon/2016699

2) Using the formula location(i) = location(1) + i 1

front

rear

front rear

front

rear

F A T
[0] [1] [2]

...
[0]

A T
[1] [2]

...
[0]

A T E
[1] [2] [3]

...

Empty queue: rear < front front = location(1); rear = location(n) Deletions & Insertions: O (1) time

What happens if rear = MaxSize - 1 and front > 0 ?

http://dis.unal.edu.co/profesores/ypinzon/2016699

3) Using the formula

location(i) = (location(1) + i 1)%M axSize

rear

rear

rear

T A F
front front

T A A

T E

front

front points one position before the position of the rst element in the

queue.
Empty queue: front = rear (initially front=rear=0) Full queue: (rear+1)%MaxSize = front

This approach is also called Circular Queue


http://dis.unal.edu.co/profesores/ypinzon/2016699

Class Denition

template<class T> class Queue { // FIFO objects public: Queue(int MaxQueueSize = 10); Queue() {delete [] queue;} bool IsEmpty() const {return front == rear;} bool IsFull() const {return (((rear + 1) % MaxSize == front) ? 1 : 0);} T First() const; // return front element T Last() const; // return last element Queue<T>& Add(const T& x); Queue<T>& Delete(T& x); private: int front; // one counterclockwise from first int rear; // last element int MaxSize; // size of array queue T *queue; // element array };
http://dis.unal.edu.co/profesores/ypinzon/2016699

Constructor, First

template<class T> Queue<T>::Queue(int MaxQueueSize) { // Create an empty queue whose capacity // is MaxQueueSize. MaxSize = MaxQueueSize + 1; queue = new T[MaxSize]; front = rear = 0; } template<class T> T Queue<T>::First() const { // Return first element of queue. Throw // OutOfBounds exception if the queue is empty. if (IsEmpty()) throw OutOfBounds(); return queue[(front + 1) % MaxSize]; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

Last, Add

template<class T> T Queue<T>::Last() const { // Return last element of queue. Throw // OutOfBounds exception if the queue is empty. if (IsEmpty()) throw OutOfBounds(); return queue[rear]; } template<class T> Queue<T>& Queue<T>::Add(const T& x) { // Add x to the rear of the queue. Throw // NoMem exception if the queue is full. if (IsFull()) throw NoMem(); rear = (rear + 1) % MaxSize; queue[rear] = x; return *this; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

10

Delete

template<class T> Queue<T>& Queue<T>::Delete(T& x) { // Delete first element and put in x. Throw // OutOfBounds exception if the queue is empty. if (IsEmpty()) throw OutOfBounds(); front = (front + 1) % MaxSize; x = queue[front]; return *this; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

11

Queue Data Structure


Linked Representation

...

front

rear

...

...

front

rear

front

rear

(a) Addition
Empty queue: front = 0 Deletions & Insertions:

(b) Deletion

O(1) time

http://dis.unal.edu.co/profesores/ypinzon/2016699

12

Class Denition
template<class T> class LinkedQueue{ // FIFO objects public: LinkedQueue() {front = rear = 0;} // constructor LinkedQueue(); // destructor bool IsEmpty() const {return ((front) ? false : true);} bool IsFull() const; T First() const; // return first element T Last() const; // return last element LinkedQueue<T>& Add(const T& x); LinkedQueue<T>& Delete(T& x); private: Node<T> *front; // pointer to first node Node<T> *rear; // pointer to last node };

http://dis.unal.edu.co/profesores/ypinzon/2016699

13

Destructor, IsFull
template<class T> LinkedQueue<T>::LinkedQueue() { // Queue destructor. Delete all nodes. Node<T> *next; while (front){ next = front->link; delete front; front = next; } } [lineskip=-0.02pt] template<class T> bool LinkedQueue<T>::IsFull() const { // Is the queue full? Node<T> *p; try { p = new Node<T>; delete p; return false; } catch (NoMem) {return true;} }
http://dis.unal.edu.co/profesores/ypinzon/2016699

14

First, Last
template<class T> T LinkedQueue<T>::First() const { // Return first element of queue. Throw // OutOfBounds exception if the queue is empty. if (IsEmpty()) throw OutOfBounds(); return front->data; } template<class T> T LinkedQueue<T>::Last() const { // Return last element of queue. Throw // OutOfBounds exception if the queue is empty. if (IsEmpty()) throw OutOfBounds(); return rear->data; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

15

Add, Delete
template<class T> LinkedQueue<T>& LinkedQueue<T>::Add(const T& x) { // Add x to rear of queue. Create node for new element Node<T> *p = new Node<T>; p->data = x; p->link = 0; // add new node to rear of queue if (front) rear->link = p; // queue not empty else front = p; // queue empty rear = p; return *this; } template<class T> LinkedQueue<T>& LinkedQueue<T>::Delete(T& x) { // Delete first element and put it in x. Throw // OutOfBounds exception if the queue is empty. if (IsEmpty()) throw OutOfBounds(); x = front->data; Node<T> *p = front; front = front->link; delete p; return *this; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

16

Queue Application
Image-Component Labelling

1 1 1

2 2 2

(a) Input
1 1 1 1 1 1 1

1 1 1 1

(b) Output
1 1 1 1 4 4 4 4 4 4 4

3 3 3 3

5 5 5 5

Digitised image: m m matrix of pixels (0,1). 0-pixel represents image

background; 1-pixel represents a point on an image component.


Two pixels are adjacent if one is to the left, above, right, or below the

other.
Two 1-pixels (component pixels) that are adjacent belong to the same

image component.
Objective: label the components pixels such that two pixels get the

same label if and only if they are pixels of the same image component.
http://dis.unal.edu.co/profesores/ypinzon/2016699

17

Image-Component Labelling
Implementation
1 2 3 4 5

class Position { friend void Label(); private: int row, col; }; // globals int **pixel, m; void Label(){ // initialize wall of 0 pixels for (int i = 0; i <= m+1; i++) { pixel[0][i] = pixel[m+1][i] = 0; // bottom & top pixel[i][0] = pixel[i][m+1] = 0; // left & right } // initialize offsets Position offset[4]; offset[0].row = 0; offset[0].col = 1; // right offset[1].row = 1; offset[1].col = 0; // down offset[2].row = 0; offset[2].col = -1; // left offset[3].row = -1; offset[3].col = 0; // up int NumOfNbrs = 4; // neighbors of a pixel position

6 7

8 9 10 11 12 13 14 15 16 17 18 19 20 21

http://dis.unal.edu.co/profesores/ypinzon/2016699

18

23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47

LinkedQueue<Position> Q; int id = 1; // component id Position here, nbr; // scan all pixels labeling components for (int r = 1; r <= m; r++) // row r of image for (int c = 1; c <= m; c++) // column c if (pixel[r][c] == 1) {// new component} pixel[r][c] = ++id; // get next id here.row = r; here.col = c; do {// find rest of component for (int i = 0; i < NumOfNbrs; i++) { // check all neighbors of here nbr.row = here.row + offset[i].row; nbr.col = here.col + offset[i].col; if (pixel[nbr.row][nbr.col] == 1) { pixel[nbr.row][nbr.col] = id; Q.Add(nbr);}} // end of if and for // any unexplored pixels in component? if (Q.IsEmpty()) break; Q.Delete(here); // a component pixel } while(true); } // end of if, for c, and for r }

http://dis.unal.edu.co/profesores/ypinzon/2016699

19

File image.cc:
// label image components #include <iostream.h> #include "lqueue.h" #include "make2db.h" void InputImage(); void Label(); void OutputImage(); void main(void){ InputImage(); cout << "The input image is" << endl; OutputImage(); Label(); cout << "The labeled image is" << endl; OutputImage(); }

http://dis.unal.edu.co/profesores/ypinzon/2016699

20

$ $ $ 7 0 0 0 0 1 1 1

g++ -o image image.cc ./image < image.dat > image.out cat image.dat 0 0 0 0 0 1 1 1 1 0 0 0 1 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

http://dis.unal.edu.co/profesores/ypinzon/2016699

21

File image.out:
Enter image size The input image is 0010000 0011000 0000100 0001100 1000100 1110000 1110000 The labeled image is 0020000 0022000 0000300 0003300 4000300 4440000 4440000

File image.dat:
7 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 1 0 0 0 1 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

http://dis.unal.edu.co/profesores/ypinzon/2016699

22

Queue Application
Lees Wire Router

Find a path from S to T by wave propagation.

S T
5 6 2 4 1 3 2 1 S 3 2 1 6 5 6 3 4 5 6 2 1 2 3 3 T 4 5 6 5 6 2 4 1 3 2 1 S 3 2 1 6 5 6 3 4 5 6 2 1 2 3 3 T 4 5 6

(a) Filing

(b) Retrace
http://dis.unal.edu.co/profesores/ypinzon/2016699

23

Lees Wire Router


1 2 3 4 5 6 7

Implementation class Position { friend void InputGrid(Position&, Position&); friend void OutputPath(int, Position *); friend bool FindPath(Position, Position, int&, Position * &); private: int row, col; }; int **grid, m; bool FindPath(Position start, Position finish, int& PathLen, Position * &path) { // Find a path from start to finish. // Return true if successful, false if impossible. if ((start.row == finish.row) && (start.col == finish.col)) {PathLen = 0; return true;} // start = finish // initialize wall of blocks around grid for (int i = 0; i <= m+1; i++) { grid[0][i] = grid[m+1][i] = 1; // bottom & top grid[i][0] = grid[i][m+1] = 1; // left & right } // initialize offsets Position offset[4]; offset[0].row = 0; offset[0].col = 1; // right offset[1].row = 1; offset[1].col = 0; // down offset[2].row = 0; offset[2].col = -1; // left offset[3].row = -1; offset[3].col = 0; // up

9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

http://dis.unal.edu.co/profesores/ypinzon/2016699

24

25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51

int NumOfNbrs = 4; // neighbors of a grid position Position here, nbr; here.row = start.row; here.col = start.col; grid[start.row][start.col] = 2; // block // label reachable grid positions LinkedQueue<Position> Q; do {// label neighbors of here for (int 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) { // unlabeled nbr, label it grid[nbr.row][nbr.col] = grid[here.row][here.col] + 1; if ((nbr.row == finish.row) && (nbr.col == finish.col)) break; // done Q.Add(nbr);} // end of if } // end of for // have we reached finish? if ((nbr.row == finish.row) && (nbr.col == finish.col)) break; // done // finish not reached, can we move to a nbr? if (Q.IsEmpty()) return false; // no path Q.Delete(here); // get next position } while(true);

http://dis.unal.edu.co/profesores/ypinzon/2016699

25

52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69

// construct path PathLen = grid[finish.row][finish.col] - 2; path = new Position [PathLen]; // trace backwards from finish here = finish; for (int j = PathLen-1; j >= 0; j--) { path[j] = here; // find predecessor position for (int 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 = nbr; // move to predecessor } return true; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

26

File wire.cc:

// Lees wire router #include #include #include #include <iostream.h> <stdlib.h> "lqueue.h" "make2db.h"

void InputGrid(Position &start, Position &finish); bool FindPath(Position start, Position finish, int& PathLen, Position * &path); void main(void){ Position s,f, *p; int l; InputGrid(s,f); if (FindPath(s,f,l,p)) OutputPath(l,p); else cout << "No path" << endl; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

27

$ $ $ 7 3 4 0 0 0 0 1 1 1

g++ -o wire wire.cc ./wire < wire.dat > wire.out cat wire.dat 2 6 0 0 0 0 0 1 1

1 1 0 0 0 1 1

0 1 0 1 0 0 0

0 0 1 1 1 0 0

0 0 0 0 0 0 0

0 0 0 0 0 0 0

http://dis.unal.edu.co/profesores/ypinzon/2016699

28

File wire.out: File wire.dat:


7 3 4 0 0 0 0 1 1 1 2 6 0 0 0 0 0 1 1 Enter grid size Enter start Enter finish Enter wiring grid The wire path is 42 52 53 54 64 65 66 56 46

1 1 0 0 0 1 1

0 1 0 1 0 0 0

0 0 1 1 1 0 0

0 0 0 0 0 0 0

0 0 0 0 0 0 0

http://dis.unal.edu.co/profesores/ypinzon/2016699

29

Behind every able man, there are always other able men. Chinese Proverb

Estructuras de Datos
Sesi on 8
Tree Data Structure
Yoan Pinz on, PhD Profesor Asociado Universidad Nacional de Colombia http://dis.unal.edu.co/profesores/ypinzon c 2009

Previous Session
Queue Data Structure Formula-based Representation Linked Representation Applications Image-Component Labeling Lees Wire Router

http://dis.unal.edu.co/profesores/ypinzon/2016699

Session 8
Tree Data Structure Terminology Binary Trees Properties Formula-based Representation Linked Representation Traversals An Application Binary Search Trees

http://dis.unal.edu.co/profesores/ypinzon/2016699

Tree Data Structure


Until now: linear and tabular data How can we represent hierarchical data? somebodys descendants governmental/company subdivisions modular decomposition of programs Answer: Tree Data Structure. A tree is a data structure that organizes information like an upsidedown tree.

http://dis.unal.edu.co/profesores/ypinzon/2016699

Terminology
A tree is a nite nonempty set of elements

root
level 1

x, y are children of v ; v is a parent of x, y x, y are siblings.

v
Elements with no children are called leaves.

y
Level: root=level 1; children=level 2,3, ...

subtree subtree

Degree of an element: number of children. Height or Depth: number of levels.

http://dis.unal.edu.co/profesores/ypinzon/2016699

Binary Trees
A binary tree is a tree (possible empty) in which every element has degree 2, except for the leaves.

http://dis.unal.edu.co/profesores/ypinzon/2016699

Properties of Binary Trees


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.

P2:

The number of elements at level i is 2i1, i > 0.

Proof: By induction on i. Basis: i = 1; number of elements = 1 = 20 Ind. Hypothesis: i = k; number of elements at level k 2k1. Look at level i = k + 1 (number of elements at level k + 1) 2(number of elements at level k) 2 2k1 = 2k .

http://dis.unal.edu.co/profesores/ypinzon/2016699

P3: A binary tree of height h, h > 0, has at least h and at most h 2 1 elements. Poof: Let n be the number of elements. must be 1 elements at each level, hence, n h. Now, if h = 0, then n = 0 = 20 1. For h > 0, we have by P2 that
h

n
i=1

2i1 = 2h 1

P4: Let h be the height of an n-elements binary tree, n 0. Then, log2(n + 1) h n Proof: must be 1 element at each level, hence, h n. P3 n 2h 1 2h n + 1 h log2(n + 1). Since h is an integer, we have that h log2(n + 1).
http://dis.unal.edu.co/profesores/ypinzon/2016699

Full binary tree: A binary tree of height h is full if contains exactly 2h 1 elements.

2 4 5 6

3
7

Complete binary tree: Is a binary tree of height h in which all levels (except perhaps for the last) have a maximum number of elements.

2 4 5 6

Number the elements from 1 through 2h k, starting from level 1 and proceed in a left-to-right fashion, for some k 1.
http://dis.unal.edu.co/profesores/ypinzon/2016699

P5: Let i, 1 i n, be the number assigned to an element v of a complete binary tree. Then: (i) If i = 1, then v is the root. If i > 1, then the parent of v has been assigned the number i/2. (ii) If 2i > n, then v has no left child. Otherwise, its left child has been assigned the number 2i. (iii) If 2i + 1 > n, then v has no right child. Otherwise, its right child has been assigned the number 2i + 1. Proof: By induction on i.

http://dis.unal.edu.co/profesores/ypinzon/2016699

Binary Tree Data Structure


Formula-based Representation

Uses P5
1

A
2

B
5

C
7

A B C

Note: An nelement binary tree may require an array of size 2n 1 for its representation. Can be a waste of space.
http://dis.unal.edu.co/profesores/ypinzon/2016699

10

Binary Tree Data Structure


Linked Representation

The most popular way to represent a binary tree is by using links or pointers. Each node is represented by three elds:

root LeftChild
data LeftChild RightChild

RightChild data

data

data

http://dis.unal.edu.co/profesores/ypinzon/2016699

11

Binary Tree Traversal


There are four common ways to traverse a binary tree:

Preorder: Visit-Left-Right (VLR) Inorder: Left-Visit-Right (LVR) Postorder: Left-Right-Visit (LRV) Level order

Example:

A B D
Preorder: ABDECF Inorder: DBEAFC

C E F
Postorder: DEBFCA Level order: ABCDEF
http://dis.unal.edu.co/profesores/ypinzon/2016699

12

Binary Tree Data Structure


Abstract Data Type (ADT) AbstractDataType BinaryTree { instances: collection of elements; if not empty, the collection is partitioned into a root, left subtree, and right subtree; each subtree is also a binary tree. operations Create(): create an empty binary tree IsEmpty(): return true if empty, false otherwise Root(x): assigns the root element to x and returns true; it returns false if there is no root element MakeTree(root, left, right): creates a binary tree root as the root element, and left (right) as the left (right) subtree. BreakTree(root, left, right): inverse of MakeTree PreOrder: InOrder: PostOrder: LevelOrder: preorder traversal of the binary tree inorder traversal of the binary tree postorder traversal of the binary tree level-order traversal of the binary tree

http://dis.unal.edu.co/profesores/ypinzon/2016699

13

Class Denition of BinaryTreeNode

class BinaryTreeNode{ public: BinaryTreeNode() {LeftChild = RightChild = 0;} BinaryTreeNode(const T& e) {data = e; LeftChild = RightChild = 0;} BinaryTreeNode(const T& e, BinaryTreeNode *l, BinaryTreeNode *r) {data = e; LeftChild = l; RightChild = r;} private: T data; BinaryTreeNode<T> *LeftChild, // left subtree *RightChild; // right subtree };

http://dis.unal.edu.co/profesores/ypinzon/2016699

14

Class Denition of BinaryTree


class BinaryTree{ public: BinaryTree() {root = 0;}; BinaryTree(){}; bool IsEmpty() const {return ((root) ? false : true);} bool Root(T& x) const; void MakeTree(const T& element, BinaryTree<T>& left, BinaryTree<T>& right); void BreakTree(T& element, BinaryTree<T>& left, BinaryTree<T>& right); void PreOrder(void(*Visit)(BinaryTreeNode<T> *u)) {PreOrder(Visit, root);} void InOrder(void(*Visit)(BinaryTreeNode<T> *u)) {InOrder(Visit, root);} void PostOrder(void(*Visit)(BinaryTreeNode<T> *u)) {PostOrder(Visit, root);} private: BinaryTreeNode<T> *root; // pointer to root void PreOrder(void(*Visit)(BinaryTreeNode<T> *u), BinaryTreeNode<T> *t); void InOrder(void(*Visit)(BinaryTreeNode<T> *u), BinaryTreeNode<T> *t); void PostOrder(void(*Visit)(BinaryTreeNode<T> *u), BinaryTreeNode<T> *t); };

http://dis.unal.edu.co/profesores/ypinzon/2016699

15

Root, MakeTree
BinaryTree<T>::Root(T& x) const { // Return root data in x. Return false if no root. if (root){ x = root->data; return true; } else return false; // no root } void BinaryTree<T>::MakeTree(const T& element, BinaryTree<T>& left, BinaryTree<T>& right) { // Combine left, right, and element to make new tree. // left, right, and this must be different trees. // create combined tree root = new BinaryTreeNode<T>(element, left.root, right.root); // deny access from trees left and right left.root = right.root = 0; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

16

BreakTree
void BinaryTree<T>::BreakTree(T& element, BinaryTree<T>& left, BinaryTree<T>& right) { // left, right, and this must be different trees. // check if empty if (!root) throw BadInput(); // tree empty // break the tree element = root->data; left.root = root->LeftChild; right.root = root->RightChild; delete root; root = 0; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

17

PreOrder, InOrder
void BinaryTree<T>::PreOrder(void(*Visit)(BinaryTreeNode<T> *u), BinaryTreeNode<T> *t) { // Preorder traversal. if (t){ Visit(t); PreOrder(Visit, t->LeftChild); PreOrder(Visit, t->RightChild); } } void BinaryTree<T>::InOrder(void(*Visit)(BinaryTreeNode<T> *u), BinaryTreeNode<T> *t) { // Inorder traversal. if (t){ InOrder(Visit, t->LeftChild); Visit(t); InOrder(Visit, t->RightChild); } }

http://dis.unal.edu.co/profesores/ypinzon/2016699

18

PostOrder, LevelOrder
template <class T> void BinaryTree<T>::PostOrder(void(*Visit)(BinaryTreeNode<T> *u), BinaryTreeNode<T> *t) { // Postorder traversal. if (t){ PostOrder(Visit, t->LeftChild); PostOrder(Visit, t->RightChild); Visit(t); } } template <class T> void BinaryTree<T>::LevelOrder(void(*Visit)(BinaryTreeNode<T> *u)) { // Level-order traversal. LinkedQueue<BinaryTreeNode<T>*> Q; BinaryTreeNode<T> *t; t = root; while (t) { Visit(t); if (t->LeftChild) Q.Add(t->LeftChild); if (t->RightChild) Q.Add(t->RightChild); try {Q.Delete(t);} catch (OutOfBounds) {return;} } }

http://dis.unal.edu.co/profesores/ypinzon/2016699

19

Visit, Height
void Visit(BinaryTreeNode<T> *x) {// Visit node *x, just output data field. cout << x->data << ; } int BinaryTree<T>::Height(BinaryTreeNode<T> *t) const { // Return height of tree *t. if (!t) return 0; // empty tree int hl = Height(t->LeftChild); // height of left int hr = Height(t->RightChild); // height of right if (hl > hr) return ++hl; else return ++hr; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

20

File binary.cc
#include <iostream.h> #include "binary.h" int count = 0; BinaryTree<int> a,x,y,z; template<class T> void ct(BinaryTreeNode<T> *t) {count++;} void main(void){ y.MakeTree(1,a,a); z.MakeTree(2,a,a); x.MakeTree(3,y,z); y.MakeTree(4,x,a); cout << "Preorder sequence is "; y.PreOutput(); cout << "Inorder sequence is "; y.InOutput(); cout << "Postorder sequence is "; y.PostOutput(); y.PreOrder(ct); cout << "Count of nodes is " << count << endl; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

21

$ g++ -o binary binary.cc $ ./binary Preorder sequence is 4 3 1 2 Inorder sequence is 1 3 2 4 Postorder sequence is 1 2 3 4 Count of nodes is 4

http://dis.unal.edu.co/profesores/ypinzon/2016699

22

Binary Tree Application


Expression Trees

+ +
(a*b)+(c/d)

* a b c

/ d

*
(((a-b)*c)+d)

d c

a b

Inx form: Prex form: Postx form:

a*b+c/d +*ab/cd ab*cd/+

a-b*c+d +*-abcd ab-c*d+

Inx: ambiguous; pre/postx: unambiguous Postx evaluation:

Scan left-to-right Put operator to a stack Apply the encountered operator to the operands in the stack and delete them from the stack.
http://dis.unal.edu.co/profesores/ypinzon/2016699

23

Binary Search Trees (BST)


Can we nd an element in a binary tree without examining every single node? Answer: Using a BST A BST is a binary tree where for every node v , all the elements in the left (right) subtree of v are smaller (larger) than v .

20

16 6 2
10 12

43 18 35 45
46 48 50

An in-order traversal produces the elements in sorted order: 2, 6, 10, 12, 16, 18, 20, 35, 43, 45, 46, 48, 50.

http://dis.unal.edu.co/profesores/ypinzon/2016699

24

Searching for an element with key k Start at root. If k equals the key of the root, then stop. If the key is less (greater) than the key of the root, then search the left (right) subtree. Time Complexity: O(h) Inserting an element with key k Search if there is an element with the same key. If the search is unsuccessful, then insert the element at the point where the search was terminated. Time Complexity: O(h)

http://dis.unal.edu.co/profesores/ypinzon/2016699

25

Deleting an element with key k Search if there is an element e with the same key. If the search is successful, consider: e is a leaf delete this node. e has exactly one nonempty subtree If e is the root, then it is deleted and the root of its single subtree becomes the new root. Otherwise, change the pointer from the parent p(e) of e so that it points to the es only child, and delete e. e has exactly two nonempty subtrees replace this element either with the largest element in its left subtree, or with the smallest element in its right subtree. To nd the largest (smallest) element in the left (right) subtree simply follow the right-child (left-child) pointers from the root of the subtree until a node with null rightchild (left-child) pointer is reached. Time Complexity: O(h)

http://dis.unal.edu.co/profesores/ypinzon/2016699

26

Class Denition of BSTree


class BSTree : public BinaryTree<E>{ public: bool Search(const K& k, E& e) const; BSTree<E,K>& Insert(const E& e); BSTree<E,K>& Delete(const K& k, E& e); void Ascend() {InOutput();} };

Search
bool BSTree<E,K>::Search(const K& k, E &e) const { // Search for element that matches k. Pointer p starts at the root and // moves through the tree looking for an element with key k BinaryTreeNode<E> *p = root; while (p) // examine p->data if (k < p->data) p = p->LeftChild; else if (k > p->data) p = p->RightChild; else {e = p->data; return true;} // found element return false; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

27

Insert
template<class E, class K> BSTree<E,K>& BSTree<E,K>::Insert(const E& e) { // Insert e if not duplicate. BinaryTreeNode<E> *p = root, // search pointer *pp = 0; // parent of p // find place to insert while (p) {// examine p->data pp = p; // move p to a child if (e < p->data) p = p->LeftChild; else if (e > p->data) p = p->RightChild; else throw BadInput(); // duplicate } // get a node for e and attach to pp BinaryTreeNode<E> *r = new BinaryTreeNode<E> (e); if (root) {// tree not empty if (e < pp->data) pp->LeftChild = r; else pp->RightChild = r;} else // insertion into empty tree root = r; return *this; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

28

Delete
template<class E, class K> BSTree<E,K>& BSTree<E,K>::Delete(const K& k, E& e) { // Delete element with key k and put it in e. BinaryTreeNode<E> *p = root, *pp = 0; // parent of p while (p && p->data != k){// move to a child of p pp = p; if (k < p->data) p = p->LeftChild; else p = p->RightChild;} if (!p) throw BadInput(); // no element with key k e = p->data; // save element to delete // restructure tree if (p->LeftChild && p->RightChild) {// two children // find largest element in left subtree of p BinaryTreeNode<E> *s = p->LeftChild, *ps = p; while (s->RightChild) {ps = s; s = s->RightChild;} // move to larger element p->data = s->data; p = s; pp = ps;} BinaryTreeNode<E> *c; if (p->LeftChild) c = p->LeftChild; else c = p->RightChild; if (p == root) root = c; else {// is p left or right child of pp? if (p == pp->LeftChild) pp->LeftChild = c; else pp->RightChild = c;} delete p; return *this; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

29

If you are planning for a year, sow rice; if you are planning for a decade, plant trees; if you are planning for a lifetime, teach people. Chinese Proverb

Estructuras de Datos
Sesi on 9
Priority Queue Data Structure
Yoan Pinz on, PhD Profesor Asociado Universidad Nacional de Colombia http://dis.unal.edu.co/profesores/ypinzon c 2009

Previous Session
Tree Data Structure Terminology Binary Trees Properties Formula-based Representation Linked Representation Traversals An Application Binary Search Trees

http://dis.unal.edu.co/profesores/ypinzon/2016699

Session 9
Priority Queue Data Structure Max Priority Queues Heaps An Application

http://dis.unal.edu.co/profesores/ypinzon/2016699

Priority Queue Data Structure


Priority Queues: FIFO structure where elements are deleted in in-

creasing (decreasing) order of priority rather than in the order in which they arrived in the queue.

Max Priority Queues: The Find/Delete operations apply to the ele-

ment of maximum priority.

Min Priority Queues: The Find/Delete operations apply to the ele-

ment of minimum priority.

http://dis.unal.edu.co/profesores/ypinzon/2016699

Priority Queue Data Structure


Abstract Data Type (ADT)

AbstractDataType MaxPriorityQueue { instances: nite collection of elements, each with a priority. operations: Create(): creates an empty priority queue Size(): returns the number of elements in the queue Max(): returns the element of maximum priority Insert(x): inserts x in the queue DeleteMax(x): deletes the element of maximum priority and returns it to x.

http://dis.unal.edu.co/profesores/ypinzon/2016699

Representation of a Max Priority Queue

Linear list.

Heap.

http://dis.unal.edu.co/profesores/ypinzon/2016699

Heaps
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 12 10 8 6 7 10 7 8

2 4 6

(a) MaxHeap

(b) MinHeap

http://dis.unal.edu.co/profesores/ypinzon/2016699

Representation of a Heap

Formula-based, since it is a complete Binary tree.

Use of property P5.

A heap with n elements has height log2 (n + 1)

http://dis.unal.edu.co/profesores/ypinzon/2016699

Insertion

Insert a new element as a leaf of the heap.

Walk up to the root to restore the heap properties.

Time Complexity: O(log n)

http://dis.unal.edu.co/profesores/ypinzon/2016699

Example: Insert 5.

20 15 14 10 2 14 15 10

20 2 5 14 15 10

20 5 2

http://dis.unal.edu.co/profesores/ypinzon/2016699

Example: Insert 21.

20 15 14 10 2 5 14 15 10

20 5 2 21 14 15 10

20 21 2 5

21 15 14 10 2 20 5

http://dis.unal.edu.co/profesores/ypinzon/2016699

10

Deletion

Delete the root element.

Delete the rightmost leaf at the highest level and put it in the root.

Restore the heap properties by walking down from root to a leaf by

following the path determined by the child having the largest value.

Time Complexity: O(log n)

http://dis.unal.edu.co/profesores/ypinzon/2016699

11

Example: Delete 21.

21 15 14 10 2 20 14 15 10 2 20 14 15 10

2 20

20 15 14 10 2

http://dis.unal.edu.co/profesores/ypinzon/2016699

12

Example: Delete 20.

20 15 14 10 2 14 15 10 2 14 15

10 2

15 14 10 2 14 10

15 2

http://dis.unal.edu.co/profesores/ypinzon/2016699

13

Initializing a Max Head

n insert operations. Time O (n log n).

Playing a tournament. Time O (n).

http://dis.unal.edu.co/profesores/ypinzon/2016699

14

Class Denition of MaxHeap

template<class T> class MaxHeap{ public: MaxHeap(int MaxHeapSize = 10); MaxHeap() {delete [] heap;} int Size() const {return CurrentSize;} T Max() {if (CurrentSize == 0) throw OutOfBounds(); return heap[1];} MaxHeap<T>& Insert(const T& x); MaxHeap<T>& DeleteMax(T& x); void Initialize(T a[], int size, int ArraySize); void Deactivate() {heap = 0;} void Output() const; private: int CurrentSize; int MaxSize; T *heap; // element array };

http://dis.unal.edu.co/profesores/ypinzon/2016699

15

Constructor, Insert
template<class T> MaxHeap<T>::MaxHeap(int MaxHeapSize) { // Max heap constructor. MaxSize = MaxHeapSize; heap = new T[MaxSize+1]; CurrentSize = 0; } template<class T> MaxHeap<T>& MaxHeap<T>::Insert(const T& x) { // Insert x into the max heap. if (CurrentSize == MaxSize) throw NoMem(); // no space // find place for x, i starts at new leaf and moves up tree int i = ++CurrentSize; while (i != 1 && x > heap[i/2]){ // cannot put x in heap[i] heap[i] = heap[i/2]; // move element down i /= 2; // move to parent } heap[i] = x; return *this; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

16

Delete
template<class T> MaxHeap<T>& MaxHeap<T>::DeleteMax(T& x) { // Set x to max element and delete // max element from heap. Check if heap is empty if (CurrentSize == 0) throw OutOfBounds(); // empty x = heap[1]; // max element T y = heap[CurrentSize--]; // last element // find place for y starting at root int i = 1, // current node of heap ci = 2; // child of i while (ci <= CurrentSize){ // heap[ci] should be larger child of i if (ci < CurrentSize && heap[ci] < heap[ci+1]) ci++; // can we put y in heap[i]? if (y >= heap[ci]) break; // yes // no heap[i] = heap[ci]; // move child up i = ci; // move down a level ci *= 2; } heap[i] = y; return *this; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

17

Initialize
template<class T> void MaxHeap<T>::Initialize(T a[], int size, int ArraySize) { // Initialize max heap to array a. delete [] heap; heap = a; CurrentSize = size; MaxSize = ArraySize; // make into a max heap for (int i = CurrentSize/2; i >= 1; i--){ T y = heap[i]; // root of subtree // find place to put y int c = 2*i; // parent of c is target location for y while (c <= CurrentSize) { // heap[c] should be larger sibling if (c < CurrentSize && heap[c] < heap[c+1]) c++; // can we put y in heap[c/2]? if (y >= heap[c]) break; // yes // no heap[c/2] = heap[c]; // move child up c *= 2; // move down a level } heap[c/2] = y; } }

http://dis.unal.edu.co/profesores/ypinzon/2016699

18

Priority Queue Application


Heap Sort

A heap can be used to sort n elements in O(n log n) time. 1) Initialize a max heap with n elements (time O(n)) 2) Extract (i.e. delete) elements from the heap one at a time. Each deletion takes O(log n) time, so the total time is O(n log n)

http://dis.unal.edu.co/profesores/ypinzon/2016699

19

#include <iostream.h> #include "maxheap.h" template <class T> void HeapSort(T a[], int n) { // create a max heap of the elements MaxHeap<T> H(1); H.Initialize(a,n,n); // extract one by one from the max heap T x; for (int i = n-1; i >= 1; i--) {H.DeleteMax(x); a[i+1] = x;} // save array a from heap destructor H.Deactivate(); } void main(void){ int a[11], i, n = 10; // initialize descending data for (i = 1; i <= 10; i++) a[i] = n - i + 1; HeapSort(a,10); // output sorted data for (i = 1; i <= n; i++) cout << a[i] << ; cout << endl; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

20

You cannot prevent the birds of sorrow from ying over your head, but you can prevent them from building nests in your hair. Chinese Proverb

Estructuras de Datos
Sesi on 10
Dictionary Data Structure
Yoan Pinz on, PhD Profesor Asociado Universidad Nacional de Colombia http://dis.unal.edu.co/profesores/ypinzon c 2009

Previous Session
Priority Queue Data Structure Max Priority Queues Heaps An Application

http://dis.unal.edu.co/profesores/ypinzon/2016699

Session 10
Dictionary Data Structure BST Representation Linear List Representation Skip List Representation Hash Table Representation

http://dis.unal.edu.co/profesores/ypinzon/2016699

Dictionary Structure
Dictionary: collection of elements, where each element has a eld called key, supporting the following operations:
Insert an element with a specic key values. Search the dictionary for an element with a specic key value. Delete an element with a specic key value.

http://dis.unal.edu.co/profesores/ypinzon/2016699

Dictionary Data Structure


Abstract Data Type (ADT) AbstractDataType Dictionary { instances: collection of elements with distinct keys. operations: Create(): creates an empty dictionary Search(k, x): return element with key k in x; returns false if the operation fails, true otherwise Insert(x): insert x into the dictionary Delete(k, x): delete element with key k and return it in x.

http://dis.unal.edu.co/profesores/ypinzon/2016699

Dictionary Data Structure


BST Representation

A dictionary is maintained as a binary search tree, where the nodes eis are dictionary elements and all keys are distinct.

http://dis.unal.edu.co/profesores/ypinzon/2016699

Dictionary Data Structure


Linear List Representation

A dictionary is maintained as an ordered linear list (e1, e2, . . .), where the eis are dictionary elements and their keys increase from left to right. Using the linked representation, the class denition for a dictionary looks as follow:

http://dis.unal.edu.co/profesores/ypinzon/2016699

Class Denition of SortedChain


template <class E, class K> class SortedChainNode{ friend SortedChain<E,K>; private: E data; SortedChainNode<E,K> *link; }; template<class E, class K> class SortedChain{ public: SortedChain() {first = 0;} SortedChain(); bool IsEmpty() const {return first == 0;} int Length() const; bool Search(const K& k, E& e) const; SortedChain<E,K>& Delete(const K& k, E& e); SortedChain<E,K>& Insert(const E& e); void Output(ostream& out) const; private: // pointer to first node SortedChainNode<E,K> *first; };

http://dis.unal.edu.co/profesores/ypinzon/2016699

Search
template<class E, class K> bool SortedChain<E,K>::Search(const K& k, E& e) const { // Put element that matches k in e. // Return false if no match. SortedChainNode<E,K> *p = first; // search for match with k while (p && p->data < k) p = p->link; // verify match if (p && p->data == k) // yes, found match { e = p->data; return true; } return false; // no match }

http://dis.unal.edu.co/profesores/ypinzon/2016699

Delete
template<class E, class K> SortedChain<E,K>& SortedChain<E,K>::Delete(const K& k, E& e) { // Delete element that matches k. // Put deleted element in e. // Throw BadInput exception if no match. SortedChainNode<E,K> *p = first, *tp = 0; // trail p // search for match with k while (p && p->data < k) { tp = p; p = p->link; } // verify match if (p && p->data == k) { // found a match e = p->data; // save data // remove p from chain if (tp) tp->link = p->link; else first = p->link; // p is first node delete p; return *this; } throw BadInput(); // no match }

http://dis.unal.edu.co/profesores/ypinzon/2016699

Insert
template<class E, class K> SortedChain<E,K>& SortedChain<E,K>::Insert(const E& e) { // Insert e, throw an exception if no space. SortedChainNode<E,K> *p = first, *tp = 0; // trail p // move tp so that e can be inserted after tp while (p && p->data < e){ tp = p; p = p->link; } // setup a new node *q for e SortedChainNode<E,K> *q = new SortedChainNode<E,K>; q->data = e; // insert node just after tp q->link = p; if (tp) tp->link = q; else first = q; return *this; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

10

Dictionary Data Structure


Skip List Representation

Searching for a given element in a dictionary of size n represented as a sorted chain may required up to n comparisons. Can we do better? Number of comparisons can be reduced to n/2+1 if we keep a pointer to the middle element: Compare rst the given element to the middle one. If it is smaller, look at the left half of the chain; otherwise, look at the right half. Apply this idea recursively to each half of the chain.

http://dis.unal.edu.co/profesores/ypinzon/2016699

11

In general we generate chains at various levels: Level 0 chain includes all n elements. Level 1 chain includes every second element. Level 2 chain includes every fourth element. Level i chain includes every 2i th element. An element is a level i element i it is in the chain for level 0 through i and it is not on the level i + 1 chain. The above data structure is called skip list.

head

tail

20

24

30

40

60

75

80

http://dis.unal.edu.co/profesores/ypinzon/2016699

12

Insertions and Deletions

When insertion and deletion occur, we cannot maintain the regular structure of a skip list without doing O(n) work. However, we can approximate this structure. Observation: there are n/2i level i element. Hence, when insertion occurs, the element level is i with probability 1/2i. In general, we can allow any probability to be used: the newly inserted element is assigned to level i with probability pi , for some 0 < p < 1. Number of chain levels is log1/p n + 1. Level i includes every 1/pth element of level i 1.

http://dis.unal.edu.co/profesores/ypinzon/2016699

13

Insertion of an element with value K

1. First search to check that no element with value K is present. 2. During the search determine those pointers of elements at various levels that could break after the insertion. 3. Make the insertion by assigning a level to the new element. This assignment can be made using a random number generator.

http://dis.unal.edu.co/profesores/ypinzon/2016699

14

Example:

head 20 head 24 30 40 60 75 80

tail

(a) A sorted chain with head and tail nodes tail

20 head

24

30

40

60

75

80 tail

(b) Pointers to middle and every second node added

20

24

30

40

60

75

77

80

(c) 77 Inserted
http://dis.unal.edu.co/profesores/ypinzon/2016699

15

Deletion of an element with value K 1. First search to nd the element with value K . 2. During the search determine those pointers of elements at various levels that need to be updated after the deletion. 3. Let the element to be delete be at level i chain. Then, the pointers determined during step 2 and belong to levels i to 0 should made to point to element after the one to be deleted.

http://dis.unal.edu.co/profesores/ypinzon/2016699

16

Assigning Levels Observation: in a regular skip list a fraction p of elements on the level i 1 chain are also on the level i chain. Hence, Pr[e level i 1 and e level i]=p. Assume that we have a uniform random number generator that generates numbers in the range 0 trough RAND MAX. Let CutOff = p RAND MAX. Then, Pr[next random number CutOff] = p. The above suggest the following method: 1. Generate a random number. If it is CutOff, then the new element should be at level 1 chain. 2. Generate another random number. If it is again CutOff, then the new element is also at level 2 chain. 3. Repeat the above steps until a random number > CutOff is generated. In C++ :
int lev=0; while (rand() <= CutOff) lev++;

http://dis.unal.edu.co/profesores/ypinzon/2016699

17

Class Denition of SkipNode

template<class E, class K> class SkipNode{ friend SkipList<E,K>; private: SkipNode(int size){link = new SkipNode<E,K> *[size];} SkipNode(); {delete [] link;} E data; SkipNode<E,K> **link; // 1D array of pointers };

http://dis.unal.edu.co/profesores/ypinzon/2016699

18

Class Denition of SkipList


template<class E, class K> class SkipList{ public: SkipList(K Large, int MaxE = 10000, float p = 0.5); SkipList(); bool Search(const K& k, E& e) const; SkipList<E,K>& Insert(const E& e); SkipList<E,K>& Delete(const K& k, E& e); void Output(); private: int Level(); SkipNode<E,K> *SaveSearch(const K& k); int MaxLevel; // max permissible chain level int Levels; // max current nonempty chain int CutOff; // used to decide level number K TailKey; // a large key SkipNode<E,K> *head; // head node pointer SkipNode<E,K> *tail; // tail node pointer SkipNode<E,K> **last; // array of pointers };

http://dis.unal.edu.co/profesores/ypinzon/2016699

19

Constructor
template<class E, class K> SkipList<E,K>::SkipList(K Large, int MaxE, float p) { // Constructor. CutOff = p * RAND_MAX; MaxLevel = ceil(log(MaxE) / log(1/p)) - 1; TailKey = Large; Levels = 0; // initial number of levels // create head & tail nodes and last array head = new SkipNode<E,K> (MaxLevel+1); tail = new SkipNode<E,K> (0); last = new SkipNode<E,K> *[MaxLevel+1]; tail->data = Large; // head points to tail at all levels as empty for (int i = 0; i <= MaxLevel; i++) head->link[i] = tail; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

20

Destructor
template<class E, class K> SkipList<E,K>::SkipList() { // Delete all nodes and array last. SkipNode<E,K> *next; // delete all nodes by deleting level 0 while (head != tail){ next = head->link[0]; delete head; head = next; } delete tail; delete [] last; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

21

Search
template<class E, class K> bool SkipList<E,K>::Search(const K& k, E& e) const { // Search for element that matches k. // Put matching element in e. // Return false if no match. if (k >= TailKey) return false; // position p just before possible node with k SkipNode<E,K> *p = head; for (int i = Levels; i >= 0; i--) // go down levels while (p->link[i]->data < k) // follow level i p = p->link[i]; // pointers // check if next node has key k e = p->link[0]->data; return (e == k); }

http://dis.unal.edu.co/profesores/ypinzon/2016699

22

SaveSearch, Level Assignment


template<class E, class K> SkipNode<E,K> * SkipList<E,K>::SaveSearch(const K& k) { // Search for k and save last position // visited at each level. // position p just before possible node with k SkipNode<E,K> *p = head; for (int i = Levels; i >= 0; i--){ while (p->link[i]->data < k) p = p->link[i]; last[i] = p; // last level i node seen } return (p->link[0]); } template<class E, class K> int SkipList<E,K>::Level() { // Generate a random level number <= MaxLevel. int lev = 0; while (rand() <= CutOff) lev++; return (lev <= MaxLevel) ? lev : MaxLevel; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

23

Insert
template<class E, class K> SkipList<E,K>& SkipList<E,K>::Insert(const E& e) { // Insert e if not duplicate. K k = e; // extract key if (k >= TailKey) throw BadInput(); // too large // see if duplicate SkipNode<E,K> *p = SaveSearch(k); if (p->data == e) throw BadInput(); // duplicate // not duplicate, determine level for new node int lev = Level(); // level of new node // fix lev to be <= Levels + 1 if (lev > Levels) {lev = ++Levels; last[lev] = head;} // get and insert new node just after p SkipNode<E,K> *y = new SkipNode<E,K> (lev+1); y->data = e; for (int i = 0; i <= lev; i++) { // insert into level i chain y->link[i] = last[i]->link[i]; last[i]->link[i] = y; } return *this; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

24

Delete
template<class E, class K> SkipList<E,K>& SkipList<E,K>::Delete(const K& k, E& e) { // Delete element that matches k. Put deleted // element in e. Throw BadInput if no match. if (k >= TailKey) throw BadInput(); // too large // see if matching element present SkipNode<E,K> *p = SaveSearch(k); if (p->data != k) throw BadInput(); // not present // delete node from skip list for (int i = 0; i <= Levels && last[i]->link[i] == p; i++) last[i]->link[i] = p->link[i]; // update Levels while (Levels > 0 && head->link[Levels] == tail) Levels--; e = p->data; delete p; return *this; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

25

Dictionary Data Structure


Hash Table Representation

It uses a hash function f to map keys into positions in a table called the hash table. Let K be the domain of all keys and let K be the set of natural numbers. Then, f : K N . The element with key k is stored in position f (k) of the hash table.

http://dis.unal.edu.co/profesores/ypinzon/2016699

26

Search for an element with key k: Compute f (k) and see if there is an element at position f (k) of the table. Delete an element with key k: Search for the element. If found, then make the position f (k) of the table empty. Insert an element with key k: Search for the element. If not found, i.e., position f (k) of the table is empty, then place the element at that position.

http://dis.unal.edu.co/profesores/ypinzon/2016699

27

If the key range is small, then we can easily implement hashing. E.g., let keys for a student record dictionary be 6 digit ID numbers, and that we have 1000 students with IDs ranging from 771000 to 772000. Then, f (k) = k 771000 maps IDs to positions 0 through 1000 of the hash table. The above situation is called ideal hashing. However, what we do when the key range is large? E.g., keys are 12-character strings; each key has to be covered into a numeric value by say mapping a blank to 0, an A to 1, . . ., and a Z to 26. This conversion maps the keys into integers in the range [1, 2712 1].

http://dis.unal.edu.co/profesores/ypinzon/2016699

28

Hashing with Linear Open Addressing The size of the hash is smaller than the key range. Find a hash function which maps several keys into the same position of the hash table. A commonly used such function is f (k) = k%D where D is the size of the hash table. If the keys are not of an integral type, then they have to be converted to non-negative integers before f (k) is computed. E.g., a long string can be converted into an unsigned integer by selecting two of its characters, or to an unsigned long integer by selecting four of its characters. Each position of the hash table is called a bucket.

http://dis.unal.edu.co/profesores/ypinzon/2016699

29

What happens if f (k1 ) = f (k2 ), for k1 = k2, i.e., a so-called collision has occurred. If the relevant bucket has space to store an additional element, then we are done. Otherwise, we have an overow problem. How do we overcome overows? Search the table (sequentially) to nd the next available bucket to store the new element. The above idea implements the Insert operation.

http://dis.unal.edu.co/profesores/ypinzon/2016699

30

Search for element with key k Search starting from the home bucket f (k) and by examining successive buckets (and considering the table as circular) until one of the following happens: 1. A bucket containing the element with the key k is found. 2. An empty bucket is reached. 3. We returned to the home bucket. In case 1, we have found the element we are looking for. In the other two cases, the table doesnt contain the requested element.

http://dis.unal.edu.co/profesores/ypinzon/2016699

31

Deleting the element with key k Deletion needs special care: if we simply make table position empty, then we may invalidate the correctness of the Search method. This implies that deletion may require to move several elements in order to leave the table in a state appropriate for the Search method. Alternative solution: introduce a eld NeverUsed in each bucket. Initially this is set to true. When an element is placed into a bucket, its NeverUsed eld becomes false. Case 2 of Search is replaced by: a bucket with NeverUsed eld equal to true is reached. Deletion is accomplished by simply vacating the relevant bucket. The alternative solution requires the organization of the hash table when the number of buckets with false NeverUsed is large.

http://dis.unal.edu.co/profesores/ypinzon/2016699

32

Class Denition of HashTable


template<class E, class K> class HashTable{ public: HashTable(int divisor = 11); HashTable() {delete [] ht; delete [] empty;} bool Search(const K& k, E& e) const; HashTable<E,K>& Insert(const E& e); void Output();// output the hash table private: int hSearch(const K& k) const; int D; // hash function divisor E *ht; // hash table array bool *empty; // 1D array };

http://dis.unal.edu.co/profesores/ypinzon/2016699

33

Constructor
template<class E, class K> HashTable<E,K>::HashTable(int divisor) { // Constructor. D = divisor; ht = new E [D]; // allocate hash table arrays empty = new bool [D]; // set all buckets to empty for (int i = 0; i < D; i++) empty[i] = true; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

34

Search
template<class E, class K> int HashTable<E,K>::hSearch(const K& k) const { // Search an open addressed table. Return location of k if present. // Otherwise return insert point if there is space. int i = k % D; // home bucket int j = i; // start at home bucket do{ if (empty[j] || ht[j] == k) return j; j = (j + 1) % D; // next bucket } while (j != i); // returned to home? return j; // table full } template<class E, class K> bool HashTable<E,K>::Search(const K& k, E& e) const { // Put element that matches k in e. // Return false if no match. int b = hSearch(k); if (empty[b] || ht[b] != k) return false; e = ht[b]; return true; }

http://dis.unal.edu.co/profesores/ypinzon/2016699

35

Insert
template<class E, class K> HashTable<E,K>& HashTable<E,K>::Insert(const E& e) { // Hash table insert. K k = e; // extract key int b = hSearch(k); // check if insert is to be done if (empty[b]){ empty[b] = false; ht[b] = e; return *this; } // no insert, check if duplicate or full if (ht[b] == k) throw BadInput(); // duplicate throw NoMem(); // table full }

http://dis.unal.edu.co/profesores/ypinzon/2016699

36

S-ar putea să vă placă și