Transcript Document

Data Structures
Mugurel Ionuț Andreica
Spring 2012
Grading
• Activity during the Laboratory – 10%
• Homework Assignments – 40%
– 4 homework assignments – 10% each
• Exam – 50%
• [optional] Course Tests (bonus: up to 10% of the
final grade; maybe less)
• Must obtain at least 25% of the final grade (from
Lab Activity + Homework Assignments + Course
Tests) in order to be allowed to participate in the
exam
Course Topics
•
•
•
•
•
•
•
•
Introduction to C++ Programming
Abstract Data Type – concept
Stack
Queue
Linked Lists
Graphs
Hash Tables
Trees (Binary Trees, Binary Search Trees, Balanced
Binary Search Trees)
• Heaps
• Disjoint Sets
• Other Advanced Topics [ if time allows ] – not for exam
Introduction to C++ Programming
• Similar to C Programming
–
–
–
–
–
Inclusion of headers
Definition of types/classes
Declaration of global variables
Definition of functions
The main function
• Extra C++ Concepts:
– C++ classes
• May contain both variables (fields) and functions with
public/private/protected access specifications
• Inheritance (only very basic aspects – the rest is handled in the
OOP course)
– Templates (generalized classes, functions, variables, etc.)
• Usually used for specifying data types
Common C/C++ Types
•
Basic types
–
–
–
–
–
•
Structured data types
–
•
•
struct s { int x; char y[2], z; double w };
Classes
Pointer types
–
–
–
–
–
–
–
•
int
char
float
double
void – only for function return values
int*, int**, ...
char*, char**, ...
float*, float**, ...
double*, double**, ...
void*, void**, ...
Pointers to structs
Pointers to classes
Defining (multidimensional) arrays
–
–
–
–
–
–
int v[100] // a static array named v with 100 elements, indexed from 0 to 99
int u[100][150], v[10][20][30], w[10][20][30][40], ...
char u[100], v[10][20], w[10][20][30], ...
float u[100], v[10][20], w[10][20][30], ...
struct s u[100], v[10][20], w[10][20][30], ...
...
Classes in C++
• class class_name {
access_specifier_1:
members;
methods;
access_specifier_2:
members;
methods;
...
constructor // same name as the class
destructor // ~class_name
}
• Access specifier = public / private / protected
• A class may contain variables and methods
Sample C++ Program with Classes
#include <stdio.h>
class MyClass {
private:
int x, cnt;
double v[100];
public:
int y;
void setX(int value) {
x = value; }
int getX() {
return x; }
void addToV(double value) {
v[cnt] = value;
cnt++; }
double getFromV(int pos) {
return v[pos]; }
MyClass(int value) {
printf("Calling the constructor\n");
x = value;
cnt = 0; }
~MyClass() {
printf("Calling the destructor\n");}
};
int main() {
int i;
MyClass c(7);
printf("%d\n", c.getX());
c.setX(19);
c.y = 17;
printf("%d\n", c.getX());
for (i = 0; i < 10; i++) c.addToV((double) i);
for (i = 9; i >= 0; i--)
printf("%.3lf\n", c.getFromV(i));
return 0;
}
Abstract Data Type
• A collection of axioms + operations
• Operations = what actions can be performed upon the
data type (implemented as functions in C/C++)
– for each operation we know:
• its name
• its arguments (types and, possibly, names)
• its return type
• Axioms specify connections between operations (i.e. the
operations are related to one another)
• Does not contain information regarding the
implementation of the operations
• Similar to a Java interface (except that only the
operations are specified in an interface and no axioms)
Abstract Data Types - examples
• Stack
– Operations: push, pop, peek, isEmpty
– Axioms: a pop() call returns the argument x of the most
recent push(x) operation called on the data type for
which no corresponding pop() has been called before
(or an error, otherwise)
• Queue
– Operations: enqueue, dequeue, peek, isEmpty
– Axioms: a dequeue() call returns the argument x of the
oldest enqueue(x) call for which no corresponding
dequeue() was called (or an error, otherwise)
From Abstract Data Types to Data
Structures
• Data structures will be initially handled as abstract data
types
• First we will specify the operations and axioms (many
times, the axioms will be given implicitly)
• Then we will discuss possible implementations
(occasionally more than just one)
• Data structures store elements
– Sometimes, the elements may have any type
– Other times, the elements must obey some specific properties
(e.g. they must be comparable)
• In order to store any type of elements => we will use
class templates (in C++)
Class Templates
• template<typename T> class class_name { ... }
– A normal class definition will be prefixed by
template<typename T>
– The type T can now be used as a valid type within the
class
• we can have variables, function arguments and function
return values of type T
• The class class_name is parameterized with the
type T
• Most of the times: T=the type of the elements
stored by the data structure
• Similar to Java generics
Class Templates - Example
#include <stdio.h>
template<typename T> class MyGenericContainer {
private:
T privateObject;
public:
void setPrivateObject(T value) {
privateObject = value;
}
int main() {
MyGenericContainer<int> c1(7);
printf("%d\n", c1.getPrivateObject());
c1.setPrivateObject(9);
printf("%d\n", c1.getPrivateObject());
MyGenericContainer<double> c2(7.9);
printf("%.3lf\n", c2.getPrivateObject());
c2.setPrivateObject(9.902);
printf("%.3lf\n", c2.getPrivateObject());
T getPrivateObject() {
return privateObject;
}
struct mystruct a;
a.x = 3; a.y[4] = 'z'; a.y[5] = 90;
a.z = 90.234;
MyGenericContainer<struct mystruct> c3(a);
printf("%.3lf\n", (c3.getPrivateObject()).z);
a.z++;
c3.setPrivateObject(a);
printf("%.3lf\n", (c3.getPrivateObject()).z);
return 0;
MyGenericContainer(T value) {
privateObject = value;
}
};
struct mystruct {
int x;
char y[32];
double z;
};
}
Recursion
• Very important in the implementation of several
data structures (usually the “tree-like” ones)
– E.g. in order to perform an operation on a tree node,
the same operation must first be called on the node’s
children
• Simple functions:
– Factorial
– Fibonacci
• Sorting functions (with good time complexities)
– Merge sort
– Quick sort
The Fibonacci Sequence
• F(0)=F(1)=1
• F(n≥2)=F(n-1)+F(n-2)
• 1, 1, 2, 3, 5, 8, 13, ...
#include <stdio.h>
#define NMAX 50
int numCalls = 0;
int memoFib[NMAX];
V2
#include <stdio.h>
int numCalls = 0;
V1
int fibo(int n) {
numCalls++;
if (n <= 1)
return 1;
else
return fibo(n-1) + fibo(n-2);
int fibo(int n) {
numCalls++;
if (memoFib[n] >= 0)
return memoFib[n];
if (n <= 1)
return (memoFib[n] = 1);
else
return (memoFib[n] = fibo(n-1) + fibo(n-2));
}
}
int main() {
int n;
scanf("%d", &n);
printf("Fibonacci(%d)=%d\n", n, fibo(n));
printf("Total number of calls=%d\n", numCalls);
return 0;
}
int main() {
int i, n;
scanf("%d", &n);
for (i = 0; i <= n; i++) memoFib[i] = -1;
printf("Fibonacci(%d)=%d\n", n, fibo(n));
printf("Total number of calls=%d\n", numCalls);
return 0;
}
The Fibonacci Sequence (cont.)
•
•
•
V1
– Fibonacci(20) = 10946
– numCalls = 21891
Tree of Calls for V1 (n=4) :
•
V2
– Fibonacci(20) = 10946
– numCalls = 39
Tree of Calls for V2 (n=4) :
call return 5
call return 5
fibo(4)
return 3
call
fibo(3)
return 2
call
return 1
call
fibo(1)
fibo(1)
return 1
call
fibo(0)
return 3
call
return 2
call
fibo(2)
return 1
call
fibo(2)
fibo(4)
return 1
call
fibo(1)
fibo(3)
return 1
call
return 2
call
fibo(0)
return 1
call
fibo(1)
fibo(2)
return 1
call
fibo(2)
fibo(1)
return 1
call
fibo(0)
return 2
call
The Fibonacci Sequence (cont.)
• What if we change the
order of the calls
fibo(n-1) and fibo(n-2)
?
– We use: fibo(n-2) +
fibo(n-1)
– Does the resut change
? (V1, V2)
– Does the total number
of calls change ? (V1,
V2)
• A non-recursive
function on the right
#include <stdio.h>
int fibo(int n) {
int i, fminus1, fminus2, fcurr;
fminus1 = 1;
fcurr = 1;
i = 1;
V3
while (i < n) {
i++;
fminus2 = fminus1;
fminus1 = fcurr;
fcurr = fminus1 + fminus2;
}
return fcurr;
}
int main() {
int i, n;
scanf("%d", &n);
printf("Fibonacci(%d)=%d\n", n, fibo(n));
return 0;
}
Generic Merge Sort
• Explanations on the blackboard
• See source code afterwards
Generic QuickSort
• Quicksort(int pstart, int pstop): sort all the
elements between pstart and pstop (inclusively)
from the array of elements
• Choose a pivot among the elements between
pstart and pstop
– The pivot should be smaller than the maximum
element within that range
• Repeatedly swap the elements between pstart
and pstop until all the elements <= pivot are
located to the left of all the elements > pivot
Generic QuickSort (cont.)
• Use two indices, i and j
• Initially, i=pstart and j=pstop
• During the swapping phase: all the elements to
the left of i are <= pivot and all the elements to
the right of j are > pivot
• While (i<=j):
– If (v[i] <= pivot) i++;
– Else if (v[j] > pivot) j--;
– Else:
• Swap v[i] and v[j]
• i++;
• j--;
Generic QuickSort (cont.)
• Then, recursively call:
– Quicksort(pstart, i-1)
• i.e. sort all the elements <= pivot
– Quicksort(i, pstop)
• i.e. sort all the elements > pivot
• See source code
Generic QuickSort (cont.)
•
•
•
•
•
•
•
•
•
Example: 7 9 2 4 7 3 8 2 1
Choose pivot=3
i=0, j=8, 7 9 2 4 7 3 8 2 1
i=1, j=7, 1 9 2 4 7 3 8 2 7
i=2, j=6, 1 2 2 4 7 3 8 9 7
i=3, j=6, 1 2 2 4 7 3 8 9 7
i=3, j=5, 1 2 2 4 7 3 8 9 7
i=4, j=4, 1 2 2 3 7 4 8 9 7
i=4, j=3, 1 2 2 3 7 4 8 9 7