data structures mugurel ionu andreica spring 2012
TRANSCRIPT
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
– int– char– float– double– void – only for function return values
• Structured data types– struct s { int x; char y[2], z; double w };
• Classes• Pointer types
– 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 classdestructor // ~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; }
T getPrivateObject() { return privateObject; }
MyGenericContainer(T value) { privateObject = value; }};
struct mystruct { int x; char y[32]; double z;};
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());
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;
}
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
#include <stdio.h>
int numCalls = 0;
int fibo(int n) { numCalls++;
if (n <= 1) return 1; else return 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;}
#include <stdio.h>
#define NMAX 50
int numCalls = 0;
int memoFib[NMAX];
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 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;
}
• F(0)=F(1)=1• F(n≥2)=F(n-1)+F(n-2)• 1, 1, 2, 3, 5, 8, 13, ...
V1
V2
The Fibonacci Sequence (cont.)
fibo(4)
fibo(3) fibo(2)
fibo(2) fibo(1) fibo(1) fibo(0)
fibo(1) fibo(0)
call call
call call call call
call callreturn 1 return 1
return 2 return 1return 1return 1
return 2return 3
call return 5
• 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) :
fibo(4)
fibo(3) fibo(2)
fibo(2) fibo(1)
fibo(1) fibo(0)
call call
call call
call callreturn 1 return 1
return 2 return 1
return 2return 3
call return 5
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;
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;}
V3
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