abstract data type

48
Abstract Data Type C and Data Structures Baojian Hua [email protected]

Upload: gabriel-albert

Post on 31-Dec-2015

36 views

Category:

Documents


5 download

DESCRIPTION

Abstract Data Type. C and Data Structures Baojian Hua [email protected]. 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 - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Abstract Data Type

Abstract Data Type

C and Data StructuresBaojian Hua

[email protected]

Page 2: Abstract Data Type

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 C e.g.: int, char, float, double, …

user-defined: allow programmers to define their own (new) data typ

es C e.g.: struct, union, …

Page 3: Abstract Data Type

Data Type Examples Predefined:

type: int elements: …, -2, -1, 0, 1, 2, … operations: +, -, *, /, %, …

User-defined: type: complex elements: 1+3i, -5+8i, … operations: new, add, sub, distance, …

Page 4: Abstract Data Type

Concrete Data Types (CDT)

An concrete data type: both concrete representations and their

operations are available Almost all C predefined types are CDT

For instance, “int” is a 32-bit double-word, and +, -, …

Knowing this can do dirty hacks See demo…

Page 5: Abstract Data Type

Abstract Data Types (ADT) An abstract data type:

separates data type declaration from representation

separates function declaration (prototypes) from implementation (definitions)

A language must some form of mechanism to support ADT interfaces in Java signatures in ML (roughly) header files & typedef in C

Page 6: Abstract Data Type

Case Study

Suppose we’d design a new data type to represent complex number c: a data type “complex” elements: 3+4i, -5-8i, … operations:

new, add, sub, distance, …

How to represent this data type in C (CDT, ADT or …)?

Page 7: Abstract Data Type

Complex Number// Recall the definition of a complex number c: c = x + yi, where x,y \in R, and i=sqrt(-1);

// Some typical operations:complex Complex_new (double x, double y);complex Complex_add (complex c1, complex c2); complex Complex_sub (complex c1, complex c2);complex Complex_mult (complex c1, complex c2);complex Complex_divide (complex c1, complex c2);// Next, we’d discuss several variants of rep’s:// CDT, ADT.

Page 8: Abstract Data Type

CDT of Complex:Interface—Types// In file “complex.h”:#ifndef COMPLEX_H#define COMPLEX_H

struct Complex_t{

double x;double y;

};typedef struct Complex_t Complex_t;

Complex_t Complex_new (double x, double y);// other function prototypes are similar …#endif

Page 9: Abstract Data Type

Client Code// With this interface, we can write client codes // that manipulate complex numbers. File “main.c”:#include “complex.h”

int main (){ Complex_t c1, c2, c3;

c1 = Complex_new (3.0, 4.0); c2 = Complex_new (7.0, 6.0); c3 = Complex_add (c1, c2); Complex_output (c3); return 0;}

Do we know c1, c2, c3’s concrete representation?How?

Page 10: Abstract Data Type

CDT Complex: Implementation// In a file “complex.c”:#include “complex.h”

Complex_t Complex_new (double x, double y){

Complex_t c = {.x = x, .y = y};

return c;}// other functions are similar. See Lab1

Page 11: Abstract Data Type

Problem #1int main (){ Complex_t c;

c = Complex_new (3.0, 4.0);

// Want to do this: c = c + (5+i6);// Ooooops, this is legal:c.x += 5;c.y += 6;

return 0;}

Page 12: Abstract Data Type

Problem #2#ifndef COMPLEX_H#define COMPLEX_H

struct Complex_t{

// change to a more fancy one? Anger “main”…double a[2];

};typedef struct Complex_t Complex_t;

Complex_t Complex_new (double x, double y);// other function prototypes are similar …

#endif

Page 13: Abstract Data Type

Problems with CDT? Operations are transparent.

user code have no idea of the algorithm Good!

Data representations dependence Problem #1: Client code can access data

directly kick away the interface safe?

Problem #2: make code rigid easy to change or evolve?

Page 14: Abstract Data Type

ADT of Complex:Interface—Types// In file “complex.h”:#ifndef COMPLEX_H#define COMPLEX_H

// note that “struct complexStruct” not giventypedef struct Complex_t *Complex_t;

Complex_t Complex_new (double x, double y);// other function prototypes are similar …

#endif

Page 15: Abstract Data Type

Client Code// With this interface, we can write client codes // that manipulate complex numbers. File “main.c”:#include “complex.h”

int main (){ Complex_t c1, c2, c3;

c1 = Complex_new (3.0, 4.0); c2 = Complex_new (7.0, 6.0); c3 = Complex_add (c1, c2); Complex_output (c3); return 0;}

Can we still know c1, c2, c3’s concrete representation?Why?

Page 16: Abstract Data Type

ADT Complex: Implementation#1—Types// In a file “complex.c”:#include “complex.h”

// We may choose to define complex type as:struct Complex_t{ double x; double y;};// which is hidden in implementation.

Page 17: Abstract Data Type

ADT Complex: Implementation Continued// In a file “complex.c”:#include “complex.h”

Complex_t Complex_new (double x, double y){

Complex_t c;

c = malloc (sizeof (*c));c->x = x; c->y = y; return c;

}// other functions are similar. See Lab1

Page 18: Abstract Data Type

ADT Summary

Yes, that’s ADT! Algorithm is hidden Data representation is hidden

client code can NOT access it thus, client code independent of the impl’

Interface and implementation Do Lab1

Page 19: Abstract Data Type

Polymorphism To explain polymorphism, we start with a n

ew data type “tuple” A tuple is of the form: (x, y)

xA, yB (aka: A*B) A, B may be unknown in advance and may be dif

ferent E.g:

A=int, B=int: (2, 3), (4, 6), (9, 7), …

A=char *, B=double: (“Bob”, 145.8), (“Alice”, 90.5), …

Page 20: Abstract Data Type

Polymorphism From the data type point of view, two

types: A, B

operations: new (x, y); // create a new tuple with x and

y equals (t1, t2); // equality testing first (t); // get the first element of t second (t); // get the second element of t …

How to represent this type in computers (using C)?

Page 21: Abstract Data Type

Monomorphic Version We start by studying a monomorphic tuple type cal

led “intTuple”: both the first and second components are of “int” type (2, 3), (8, 9), …

The intTuple ADT: type: intTuple elements: (2, 3), (8, 9), … Operations:

tuple new (int x, int y); int first (int t); int second (tuple t); int equals (tuple t1, tuple t2); …

Page 22: Abstract Data Type

“IntTuple” CDT// in a file “int-tuple.h”#ifndef INT_TUPLE_H#define INT_TUPLE_H

struct IntTuple_t{

int x;int y;

};typedef struct IntTuple_t IntTuple_t;

IntTuple_t IntTuple_new (int n1, int n2);int IntTuple_first (IntTuple_t t);…

#endif

Page 23: Abstract Data Type

Or the “IntTuple” ADT// in a file “int-tuple.h”#ifndef INT_TUPLE_H#define INT_TUPLE_H

typedef struct IntTuple_t *IntTuple_t;

IntTuple_t IntTuple_new (int n1, int n2);int IntTuple_first (IntTuple_t t);int IntTuple_equals (IntTuple_t t1, IntTuple_t t2);…

#endif// We only discuss “tupleEquals ()”. All others// functions left to you.

Page 24: Abstract Data Type

Equality Testing// in a file “int-tuple.c”

int Tuple_equals (IntTuple_t t1, IntTuple_t t2)

{

return ((t1->x == t2->x) && (t1->y==t2->y));

}

x

y

t1x

y

t2

Page 25: Abstract Data Type

Problems? It’s ok if we only design “IntTuple” But we if we’ll design these tuples:

(int, double), (int, char *), (double, double), …

Same code exists everywhere, no means to maintain and evolve Nightmares for programmers Remember: never duplicate code!

Page 26: Abstract Data Type

Polymorphism Now, we consider a polymorphic tuple type

called “tuple”: “poly”: may take various forms Every element of the type “tuple” may be of di

fferent types (2, 3.14), (“8”, ‘a’), (‘\0’, 99), …

The “tuple” ADT: type: tuple elements: (2, 3.14), (“8”, ‘a’), (‘\0’, 99), …

Page 27: Abstract Data Type

The Tuple ADT

What about operations? tuple new (??? x, ??? y); ??? first (tuple t); ??? second (tuple t); int equals (tuple t1, tuple t2); …

Page 28: Abstract Data Type

Polymorphic Type To resove this, C dedicates a special polym

orphic type “void *” “void *” is a pointer which can point to “an

y” concrete types (i.e., it’s compatible with any pointer type),

very poly… long history of practice, initially “char *” can not be used directly, use ugly cast similar to constructs in others language, such as

“Object”

Page 29: Abstract Data Type

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); …

Page 30: Abstract Data Type

“tuple” Interface// in a file “tuple.h”#ifndef TUPLE_H#define TUPLE_H

typedef void *poly;typedef struct Tuple_t * Tuple_t;

Tuple_t Tuple_new (poly x, poly y);poly first (Tuple_t t);poly second (Tuple_t t);int equals (Tuple_t t1, Tuple_t t2);

#endif TUPLE_H

Page 31: Abstract Data Type

Client Code// file “main.c”#include “tuple.h”

int main (){ int i = 8;

Tuple_t t1 = Tuple_new (&i, “hello”); return 0;}

Page 32: Abstract Data Type

“tuple” ADT Implementation// in a file “tuple.c”#include <stdlib.h>#include “tuple.h”

struct Tuple_t { poly x; poly y;};Tuple_t Tuple_new (poly x, poly y){ tuple t = malloc (sizeof (*t)); t->x = x; t->y = y; return t;}

x

y

t

Page 33: Abstract Data Type

“tuple” ADT Implementation// in a file “tuple.c”#include <stdlib.h>#include “tuple.h”

struct Tuple_t{ poly x; poly y;};

poly Tuple_first (Tuple_t t){ return t->x;}

x

y

t

Page 34: Abstract Data Type

Client Code#include “complex.h” // ADT version#include “tuple.h”

int main (){ int i = 8;

Tuple_t t1 = Tuple_new (&i, “hello”);

// type castint *p = (int *)Tuple_first (t1);

return 0;}

Page 35: Abstract Data Type

Equality Testingstruct Tuple_t{ poly x; poly y;};

// The #1 try:int Tuple_equals (Tuple_t t1, Tuple_t t2){ return ((t1->x == t2->x)

&& (t1->y == t2->y)); // Wrong!!}

x

y

t

Page 36: Abstract Data Type

Equality Testingstruct Tuple_t{ poly x; poly y;};

// The #2 try:int Tuple_equals (Tuple_t t1, Tuple_t t2){ return (*(t1->x) == *(t2->x) && *(t1->y) == *(t2->y)); // Problem?}

x

y

t

Page 37: Abstract Data Type

Equality Testingstruct Tuple_t{ poly x; poly y;};

// The #3 try:int Tuple_equals (Tuple_t t1, Tuple_t t2){ return (equalsXXX (t1->x, t2->x) && equalsYYY (t1->y, t2->y)); // but what are “equalsXXX” and “equalsYYY”?}

x

y

t

Page 38: Abstract Data Type

Function as Arguments// So in the body of “equals” function, instead // of guessing the types of t->x and t->y, we // require the callers of “equals” supply the // necessary equality testing functions. // The #4 try:typedef int (*tf)(poly, poly);

int Tuple_equals (tuple t1, tuple t2, tf eqx, tf eqy){ return (eqx (t1->x, t2->x) && eqy (t1->y, t2->y));}

Page 39: Abstract Data Type

Change to “tuple” Interface// in file “tuple.h”#ifndef TUPLE_H#define TUPLE_H

typedef void *poly;typedef int (*tf)(poly, poly);typedef struct Tuple_t *Tuple_t;

Tuple_t Tuple_new (poly x, poly y);poly Tuple_first (Tuple_t t);poly Tuple_second (Tuple_t t);int Tuple_equals (Tuple_t t1, Tuple_t t2, tf eqx, tf eqy);

#endif TUPLE_H

Page 40: Abstract Data Type

Client Code// in file “main.c”#include “tuple.h”

int main (){ int i=8, j=8, k=7, m=7; Tuple_t t1 = Tuple_new (&i, &k); Tuple_t t2 = Tuple_new (&j, &k);

Tuple_equals (t1, t2, Int_equals, Int_equals); return 0;}

Page 41: Abstract Data Type

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

Page 42: Abstract Data Type

Function-Carrying Data

Why we can NOT make use of data, such as passed as function arguments, when it’s of type “void *”?

Better idea: Let data carry functions themselves,

instead passing function pointers such kind of data called objects

Page 43: Abstract Data Type

Function Pointer in Dataint Tuple_equals (Tuple_t t1, Tuple_t t2){ // note that if t1->x or t1->y has carried the // equality testing functions, then the code // could just be written as: return (t1->x->equals (t1->x, t2->x)

&& t1->y->equals (t1->y, t2->y)); } equals

……

equals_y

x

y

t1

equals

……

equals_x

Page 44: Abstract Data Type

Function Pointer in Data// To cope with this, we should modify other // modules. For instance, the “complex” ADT:struct Complex_t{ int (*equals) (poly, poly); double a[2];};

Complex_t Complex_new (double x, double y){ Complex_t c = malloc (sizeof (*c)); c->equals = Complex_equals;

…; return n;}

x

n

equals

y

Page 45: Abstract Data Type

Function Callint Tuple_equals (Tuple_t t1, Tuple_t t2){ return (t1->x->equals (t1->x, t2->x)

&& t1->y->equals (t1->y,t2->y));}

a[0]

equals

a[0]t2

a[1]a[1]

x

y

t1x

y

Page 46: Abstract Data Type

Client Code// in file “main.c”#include “complex.h”#include “tuple.h”

int main (){ Complex_t c1 = Complex_new (1.0, 2.0); Complex_t c2 = Complex_new (1.0, 2.0);

Tuple_t t1 = Tuple_new (c1, c2); Tuple_t t2 = Tuple_new (c1, c2); Tuple_equals (t1, t2); // dirty simple! :-P return 0;}

Page 47: Abstract Data Type

Object

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 oriented programming In fact, early C++ compilers compiles to C That’s partly why I don’t love object-

oriented languages

Page 48: Abstract Data Type

Summary

Abstract data types enable modular programming clear separation between interface

and implementation interface and implementation should

design and evolve together Polymorphism enables code reuse Object = data + function pointers