1 / 48

Data Structure & Abstract Data Type

Data Structure & Abstract Data Type. C and Data Structures Baojian Hua bjhua@ustc.edu.cn. 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:

Download Presentation

Data Structure & Abstract Data Type

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Data Structure &Abstract Data Type C and Data Structures Baojian Hua bjhua@ustc.edu.cn

  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. n i “nat” Implementation // in file “nat.c” #include <stdlib.h> #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; }

  11. n i “nat” Implementation // in file “nat.c” #include <stdlib.h> #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; }

  12. n1 n2 n i i n1->i + n2->i “nat” Implementation // in file “nat.c” #include <stdlib.h> #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; }

  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 <stdlib.h> #include <stdio.h> #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. t n1 n2 “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; }

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

  23. t1 t2 n1 n1 n2 n2 “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); }

  24. t1 t2 n1 n1 n2 n2 “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)); }

  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. n1 n2 i i Change to the “nat” Implementation // in file “nat.c” #include <stdlib.h> #include <stdio.h> #include “nat.h” struct nat { int i; }; int natEquals (nat n1, nat n2) { return (n1->i == n2->i); }

  27. t1 t2 n1 n1 n2 n2 “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)); }

  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. t x y “tuple” ADT Implementation // in file “tuple.c” #include <stdlib.h> #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; }

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

  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. equals t1->x …… t1 x y 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, thenthe code // could just be written: return (t1->x->equals (t1->x, t2->x) && t1->y->equals (t1->y,t2->y)); }

  44. equals n i 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; }

  45. equals t2->x t1->x i i 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)); }

  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

More Related