Download presentation

Presentation is loading. Please wait.

Published byHoward Mulberry Modified about 1 year ago

1
Data Structure & Abstract Data Type C and Data Structures Baojian Hua

2
Data Types A data type consists of: A collection of data elements (a type) A set of operations on these data elements Data types in languages: predefined: any language defines a group of predefined data types (In C) int, char, float, double, … user-defined: allow programmers to define their own (new) data types (In C) struct, union, …

3
Data Type Examples Predefined: type: int elements: …, -2, -1, 0, 1, 2, … operations: +, -, *, /, %, … User-defined: type: complex elements: 1+3i, -5+8i, … operations: newComplex, add, distance, …

4
Abstract Data Types An abstract data type: separates data type definition from representation separates function declaration (prototypes) from implementation Example of abstract data types in languages interfaces in Java signatures in ML (roughly) header files & typedef in C

5
Data Structures Data structure studies the organization of data in computers, consisting of the (abstract) data types (definition and repr ’ ) relationship between elements of this type operations on data types Algorithms: methods to operate on data structures tradeoff between efficiency and simplicity subtle interplay with data structure design Slogan: program = data structures+algorithm

6
What will this course cover? Linear structure: Linked list, stack, queue, extensible array, functional string Tree & forest: binary tree, binary search tree Graph Hash Searching

7
More on Modules and Abstract Data Types Consider a data type to represent natural number n: a data type called “ nat ” elements: 0, 1, 2, 3, … operations: newNat, add, sub, … How to represent this (abstract) data type in C?

8
“ nat ” ADT in C (Interface) // in file “nat.h” #ifndef NAT_H #define NAT_H typedef struct nat *nat; nat newNat (int i); nat natAdd (nat n1, nat n2); // other function prototypes are similar #endif

9
Client Code // in file “main.c” #include “nat.h” int main () { nat n1, n2, n3; n1 = newNat (8); n2 = newNat (9); n3 = natAdd (n1, n2); return 0; }

10
“ nat ” Implementation // in file “nat.c” #include #include “nat.h” struct nat { int i; // the concrete internal representation }; nat newNat (int i) { nat n = malloc (sizeof (*n)); n->i = i; return n; } i n

11
“ nat ” Implementation // in file “nat.c” #include #include “nat.h” struct nat { int i; // the concrete internal representation }; nat newNat (int i) { if (i<0) error (“invalid arg\n”); nat n = malloc (sizeof (*n)); n->i = i; return n; } i n

12
“ nat ” Implementation // in file “nat.c” #include #include “nat.h” struct nat { int i; // the concrete internal representation }; nat natAdd (nat n1, nat n2) { nat n = malloc (sizeof (*n)); n->i = n1->i + n2->i; return n; } i n1 i n2 n1->i + n2->i n

13
Client Code // in file “main.c” #include “nat.h” int main () { nat n1, n2, n3; n1 = newNat (8); n2 = newNat (9); n3 = natAdd (n1, n2); // but what if we want to print nat? Is it: // printf (“”, n3) ???? return 0; }

14
Change to the Interface // in file “nat.h” #ifndef NAT_H #define NAT_H typedef struct nat *nat; nat newNat (int i); nat natAdd (nat n1, nat n2); void natPrint (nat n); // other function prototypes are similar #endif

15
Change to the Implementation // in file “nat.c” #include #include “nat.h” struct nat { int i; // the concrete internal representation }; void natPrint (nat n) { printf (“%d”, n->i); return; }

16
Client Code // in file “main.c” #include “nat.h” int main () { nat n1, n2, n3; n1 = newNat (8); n2 = newNat (9); n3 = natAdd (n1, n2); // but what if we want to print nat? Is it: natPrint (n3); return 0; }

17
More on Modules and Abstract Data Types A tuple type has the form: (x, y) x and y may have different types Tx, Ty Tx, Ty unknown in advance and may be different operations: newTuple (x, y); // create a new tuple with x and y equals (t1, t2); // equality testing first (t); // get the first element second (t); // get the second element … How to represent this abstract data type in computers (using C)?

18
The Tuple ADT Next, we first consider a monomorphic tuple type called “ natTuple ” : both the first and second components are of “ nat ” type (2, 3), (8, 9), … The natTuple ADT: type: natTuple elements: (2, 3), (8, 9), … Operations: tuple newNatTuple (nat x, nat y); nat first (nat t); Ty second (tuple t); bool equals (tuple t1, tuple t2); …

19
“ natTuple ” Interface // in file “natTuple.h” #ifndef NAT_TUPLE_H #define NAT_TUPLE_H #include “nat.h” typedef struct natTuple *natTuple; natTuple newNatTuple (nat n1, nat n2); nat first (natTuple t); nat second (natTuple t); int equals (natTuple t1, natTuple t2); #endif

20
Client Code // in file “main.c” #include “nat.h” #include “natTuple.h” int main () { nat n1 = newNat (3); nat n2 = newNat (5); natTuple t1 = newNatTuple (n1, n2); return 0; }

21
“ natTuple ” Implementation // in file “natTuple.c” #include “natTuple.h” struct natTuple { nat n1; nat n2; }; natTuple newNatTuple (nat x, nat y) { natTuple t = malloc (sizeof (*t)); t->n1 = x; t->n2 = y; return t; } n1 n2 t

22
“ natTuple ” Implementation // in file “natTuple.c” #include “natTuple.h” struct natTuple { nat n1; nat n2; }; nat first (natTuple t) { return t->n1; } n1 n2 t

23
“ natTuple ” Implementation // in file “natTuple.c” #include “natTuple.h” struct natTuple { nat n1; nat n2; }; int equals (natTuple t1, natTuple t2) { // the first try (it’s wrong!!): return (t1->n1 == t2->n1 && t1->n2 == t2->n2); } n1 n2 t1 n1 n2 t2

24
“ natTuple ” Implementation // in file “natTuple.c” #include “natTuple.h” struct natTuple { nat n1; nat n2; }; int equals (natTuple t1, natTuple t2) { // the second try: return (natEquals (t1->n1, t2->n1) && natEquals (t1->n2, t2->n2)); } n1 n2 t1 n1 n2 t2

25
Change to the “ nat ” Interface // in file “nat.h” #ifndef NAT_H #define NAT_H typedef struct nat *nat; nat newNat (int i); nat natAdd (nat n1, nat n2); void natPrint (nat n); int natEquals (nat n1, nat n2); // other function prototypes are similar #endif

26
Change to the “ nat ” Implementation // in file “nat.c” #include #include “nat.h” struct nat { int i; }; int natEquals (nat n1, nat n2) { return (n1->i == n2->i); } i n1 i n2

27
“ natTuple ” Implementation // in file “natTuple.c” #include “natTuple.h” struct natTuple { nat n1; nat n2; }; int equals (natTuple t1, natTuple t2) { // the second try: return (natEquals (t1->n1, t2->n1) && natEquals (t1->n2, t2->n2)); } n1 n2 t1 n1 n2 t2

28
The Tuple ADT Finally, we consider a polymorphic tuple type called “ tuple ” : “ poly ” : may take various forms Every components of tuple may be of different types (2, 3.14), ( “ 8 ”, ‘ a ’ ), ( ‘ \0 ’, 99), … The “ tuple ” ADT: type: tuple elements: (2, 3.14), ( “ 8 ”, ‘ a ’ ), ( ‘ \0 ’, 99), …

29
The Tuple ADT What about operations? tuple newTuple (??? x, ??? y); ??? first (tuple t); ??? second (tuple t); int equals (tuple t1, tuple t2); …

30
Polymorphic Type To cure this, C offer a polymorphic type “ void * ” “ void * ” is a pointer which can point to “ any ” concrete types (i.e., it ’ s compatible with any pointer type) think a box or a mask can not be used directly, use ugly cast similar to constructs in others language, such as “ Object ”

31
The Tuple ADT What about operations? tuple newTuple (void *x, void *y); void *first (tuple t); void *second (tuple t); int equals (tuple t1, tuple t2); …

32
“ tuple ” Interface // in file “tuple.h” #ifndef TUPLE_H #define TUPLE_H typedef void *poly; typedef struct tuple *tuple; tuple newTuple (poly x, poly y); poly first (tuple t); poly second (tuple t); int equals (tuple t1, tuple t2); #endif TUPLE_H

33
Client Code // in file “main.c” #include “complex.h” #include “nat.h” #include “tuple.h” int main () { complex c = newComplex (1.0, 2.0); nat n1 = newNat (8); nat n2 = newNat (6); tuple t1 = newTuple (n1, c); tuple t2 = newTuple (n2, c); return 0; }

34
“ tuple ” ADT Implementation // in file “tuple.c” #include #include “tuple.h” struct tuple { poly x; poly y; }; tuple newTuple (poly x, poly y) { tuple t = malloc (sizeof (*t)); t->x = x; t->y = y; return t; } x y t

35
“ tuple ” ADT Implementation // in file “tuple.c” #include #include “tuple.h” struct tuple { poly x; poly y; }; poly first (tuple t) { return t->x; } x y t

36
Client Code // in file “main.c” #include “complex.h” #include “nat.h” #include “tuple.h” int main () { complex c = newComplex (1.0, 2.0); nat n1 = newNat (8); nat n2 = newNat (6); tuple t1 = newTuple (n1, c); tuple t2 = newTuple (n2, c); nat temp = (nat)first (t1); // type cast return 0; }

37
“ equals ” ? struct tuple { poly x; poly y; }; // The first try: int equals (tuple t1, tuple t2) { return ((t1->x) == (t2->x) && (t1->y) == (t2->y)) // Wrong!! }

38
“ equals ” ? struct tuple { poly x; poly y; }; // The second try: int equals (tuple t1, tuple t2) { return (equalsXXX (t1->x, t2->x) && equalsYYY (t1->y, t2->y)) // but what are “equalsXXX” and “equalsYYY”? }

39
Function as Arguments // So instead of guessing the types of t->x and // t->y in the body of “equals” function, we // require the callers of “equals” supply the // necessary equality testing functions. // The second try: // typedef int (*fun)(poly, poly); int equals (tuple t1, tuple t2, fun eqx, fun eqy) { return (eqx (t1->x, t2->x) && eqy (t1->y, t2->y)); }

40
Change to “ tuple ” Interface // in file “tuple.h” #ifndef TUPLE_H #define TUPLE_H typedef void *poly; typedef int (*fun)(poly, poly); typedef struct tuple *tuple; tuple newTuple (poly x, poly y); poly first (tuple t); poly second (tuple t); int equals (tuple t1, tuple t2, fun eqx, fun eqy); #endif TUPLE_H

41
Client Code // in file “main.c” #include “complex.h” #include “nat.h” #include “tuple.h” int main () { complex c = newComplex (1.0, 2.0); nat n1 = newNat (8); nat n2 = newNat (6); tuple t1 = newTuple (n1, c); tuple t2 = newTuple (n2, c); equals (t1, t2, natEquals, complexEquals); return 0; }

42
Moral void* serves as polymorphic type in C mask all pointer types (think Object type in Java) Pros: code reuse: write once, used in arbitrary context we ’ d see more examples later in this course Cons: Polymorphism doesn ’ t come for free boxed data: data heap-allocated (to cope with void *) no static or runtime checking (at least in C) clumsy code extra function pointer arguments

43
Function Pointer in Data typedef int (*fun)(poly, poly); int equals (tuple t1, tuple t2) { // note that if t1->x or t1->y has carried the // equality testing functions, then the code // could just be written: return (t1->x->equals (t1->x, t2->x) && t1->y->equals (t1->y,t2->y)); } …… equals x y t1 t1->x

44
Function Pointer in Data // To cope with this, we should modify other // modules. For instance, the “nat” ADT: struct nat { int (*equals) (poly, poly); int i; }; nat newNat (int i) { nat n = malloc (sizeof (*n)); n->equals = natEquals; n->i = i; return n; } i n equals

45
The Call typedef int (*fun)(poly, poly); int equals (tuple t1, tuple t2) { return (t1->x->equals (t1->x, t2->x) && t1->y->equals (t1->y,t2->y)); } i t1->x equals i t2->x

46
Client Code // in file “main.c” #include “complex.h” #include “nat.h” #include “tuple.h” int main () { complex c = newComplex (1.0, 2.0); nat n1 = newNat (8); nat n2 = newNat (6); tuple t1 = newTuple (n1, c); tuple t2 = newTuple (n2, c); equals (t1, t2); // dirty simple! :-P return 0; }

47
Function Pointers in Data Data elements with function pointers is the simplest form of objects object = virtual functions + private data With such facilities, we can in principal model object programming In fact, early C++ compilers compiles to C That ’ s partly why I don ’ t love object- oriented languages

48
Summary Data structure studies data representation and operations direct interplay with algorithm design Abstract data types enable modular programming clear separation between interface and implementation interface and implementation should design and evolve together Polymorphism enables code reuse See the course web page for programming assignments

Similar presentations

© 2017 SlidePlayer.com Inc.

All rights reserved.

Ads by Google