Presentation is loading. Please wait.

Presentation is loading. Please wait.

Abstract Data Types.

Similar presentations


Presentation on theme: "Abstract Data Types."— Presentation transcript:

1 Abstract Data Types

2 Abstract Data Types A useful tool for specifying the logical properties of a data type is the abstract data type, or ADT. A data type is a collection of data objects that share a defined set of properties and operations for processing the objects. That collection and those operations form a concept that may be implemented using a particular hardware or software data structure.

3 ADT Some programming language provide explicit mechanism to support the distinction between specification and implementation. C++, Java : a class C does not have an explicit mechanism for implementing ADTs, but it is still possible and desirable to design your data types using the same notion. Example : lists, sets, graphs along with their operations

4 Why Abstract Data Types?
User of the ADT “sees” only the interface to the objects; the implementation details are “hidden” in the definition of the ADT The user is constrained to manipulate the object solely through the functions (operations) that are provided. The designer may still alter the representation as long as the new implementations of the operations do not change the user interface. This means that users will not have to recode their algorithms.

5 ADT The basic idea: the implementation of these operations is written
any other part of the program that needs to perform some operation on the ADT calls the appropriate function If implementation details change, it will be transparent to the rest of the program.

6 Examples of ADTs String ADT
definition of string object (alphabet, sequence) definition of string operations Boolean StringCopy (srcString, dstString) Boolean StringConcat (srcString, dstString) Boolean StringCompare (SrcString, dstString) Void StringPrint (String); possible implementations array implementation linked list implementation circular doubly-linked list implementation

7 ADT Example: Rational Numbers
Can be written as a/b where a and b are int and b != 0 Precision may be lost in representing as a single number A rational number has two parts : numerator and denominator – both are integers. Interface functions makerational add mul equal printrat reduce

8 ADT: Rational Number Interface functions
Constructor function: RATIONAL makerational (int, int); Selector functions : int numerator (RATIONAL); Int denominator (RATIONAL) ; Operations: RATIONAL add (RATIONAL,RATIONAL); RATIONAL mult (RATIONAL, RATIONAL); RATIONAL reduce (RATIONAL) ; Equality testing : int equal (RATIONAL, RATIONAL); Print : void printrat (RATIONAL) ;

9 Several Ways to Represent Rational
typedef struct { int numerator; int denominator; } Rational; int ar[2];

10 ADT: Rational Number Concrete implementation I
typedef struct { int numerator; int denominator; }RATIONAL; RATIONAL makerational (int x, int y) { RATIONAL r; r.numerator = x; r.denominator = y; return r; } RATIONAL reduce (RATIONAL r) { int g; g = gcd(r.numerator,r.denominator); r.numerator /= g; r.denominator /= g; return r; } int numerator (RATIONAL r) { return r.numerator; } int denominator (RATIONAL r) { return r.denominator;

11 ADT: Rational Number implementation of add (1)
typedef struct { int numerator; int denominator; } RATIONAL; RATIONAL add (RATIONAL r1, RATIONAL r2) { RATIONAL r; int g; g = gcd(r1.denominator,r2.denominator); r.denominator = lcm(r1.denominator,r2.denominator); r.numerator = r1.denominator*r2.denominator/g; r.numerator += r2.denominator*r1.numerator/g; return r; }

12 ADT: Rational Number implementation of add (2)
typedef struct { int numerator; int denominator; }RATIONAL; RATIONAL add (RATIONAL r1, RATIONAL r2) { RATIONAL r; r.numerator = r1.numerator*r2.denominator +r2.numerator*r1.denominator; r.denominator=r1.denominator*r2.denominator; return r; }

13 ADT: Rational Number Concrete implementation I
RATIONAL mult (RATIONAL r1, RATIONAL r2) { RATIONAL r; r.numerator = r1.numerator*r2.numerator; r.denominator = r1.denominator*r2.denominator; r = reduce (r); return r; } typedef struct { int numerator; int denominator; }RATIONAL; int equal (RATIONAL r1, RATIONAL r2) { return (r1.numerator*r2.denominator==r2.numerator*r1.denominator); } void printrat (RATIONAL r) { printf (“%d / %d “,r.numerator, r.denominator); }

14 ADT: Rational Number Concrete implementation II
typedef struct { int ar[2] ; }RATIONAL; RATIONAL makerational (int x, int y) { RATIONAL r; r.ar[0] = x; r.ar[1] = y; return r; } RATIONAL reduce (RATIONAL r) { int g; g = gcd (r.numerator,r.denominator); r.a[0] /= g; r.a[1] /= g; return r; } int numerator (RATIONAL r) { return r.a[0]; } int denominator (RATIONAL r) { return r.a[1];

15 The List ADT LIST makenull () : returns an empty list
A list : <A1, A2, ... , AN> of size N. Special list of size 0 : an empty list Operations: LIST makenull () : returns an empty list LIST makelist (ETYPE) : makes a list containing a single element void printlist (LIST) int search(ETYPE, LIST) : searches whether a key is in the list void insert (ETYPE, LIST) void delete (ETYPE, LIST) ETYPE findKth (LIST)

16 Array Implementation of List
typedef int ETYPE; typedef struct { ETYPE elements[MAXS]; int size; } LIST; LIST makenull () ; LIST makeList (ETYPE) ; void printList (LIST) ; int IsEmpty (LIST) ; int search (ETYPE, LIST) ; void delete (ETYPE, LIST * ); void insert (ETYPE, LIST * )

17 Complex Number ADT typedef struct { float real; float imag; } COMPLEX; COMPLEX makecomplex (float, float) ; COMPLEX addc (COMPLEX, COMPLEX); COMPLEX subc (COMPLEX, COMPLEX); COMPLEX multc (COMPLEX, COMPLEX); COMPLEX divc (COMPLEX, COMPLEX);

18 SET ADT Interface functions (1): SET makenullset () ; int member (ETYPE, SET) ; SET adjoin (ETYPE, SET); SET union (SET, SET) ; SET intersection (SET, SET); void printset (SET) ; Interface functions (2): SET makenullset () ; int member (ETYPE, SET) ; void adjoin(ETYPE, SET *); void union (SET, SET, SET*); void intersection (SET, SET, SET*); void printset (SET) ;

19 Concrete implementation of SET ADT
typedef struct { ETYPE elem[MAX]; int size; } SET; Implementation 1 : sorted array adjoin : Sorted insert member : Binary search delete : ? union : merge 2 sorted arrays intersection : ?

20 Concrete implementation of SET ADT
typedef struct { ETYPE elem[MAX]; int size; } SET; Implementation 2 : unsorted array keep the elements in the array unsorted. adjoin : Insert at the end member : Search till found or till the end delete : Go through the array sequentially until element is found, or reach the end. Then left shift the array. union , intersection ?

21 Concrete implementation of SET ADT
typedef struct node { ETYPE elem; struct node * next; } * SET; Implementation 3, 4 : linked list Sorted or unsorted adjoin : member : delete : union , intersection

22 Another ADT Example: Stacks
LIFO: Last-In, First-Out Like the stack of trays at the cafeteria “Push” a tray onto the stack “Pop” a tray off the stack Useful in many contexts

23 The Stack ADT initialize push pop empty full Operations Objects:
a finite sequence of elements of the same type additions restricted to one end of the sequence called the top of the stack deletions also restricted to the same end Operations initialize push pop empty full

24 Stack Properties and Attributes
LIFO data structures. All accesses are done to the element referenced by top. The top always refers to the topmost element in the stack. Insertions are done “above” the top element. Attributes size : The number of elements in the stack: size >= 0 at all times. top : The topmost element of the stack, refers to null, a special value indicating top doesn’t reference anything in the stack. 6-24

25 Example 3 :: Last-In-First-Out STACK
Assume:: stack contains integer elements void init (stack *s); /* Create a new stack */ void push (stack *s, int element); /* Insert an element in the stack */ int pop (stack *s); /* Remove and return the top element */ int isempty (stack *s); /* Check if stack is empty */ int isfull (stack *s); /* Check if stack is full */ Spring 2012 Programming and Data Structure

26 Programming and Data Structure
Contd. We shall look into two different ways of implementing stack: Using arrays Using linked list Spring 2012 Programming and Data Structure

27 Example:: First-In-First-Out QUEUE
Assume:: queue contains integer elements void enqueue (queue *q, int element); /* Insert an element in the queue */ int dequeue (queue *q); /* Remove an element from the queue */ queue *create(); /* Create a new queue */ int isempty (queue *q); /* Check if queue is empty */ int size (queue *q); /* Return the no. of elements in queue */ Spring 2012 Programming and Data Structure

28 Stack Implementations: Using Array
Spring 2012 Programming and Data Structure

29 Programming and Data Structure
STACK USING ARRAY PUSH top top Spring 2012 Programming and Data Structure

30 Programming and Data Structure
STACK USING ARRAY POP top top Spring 2012 Programming and Data Structure

31 stack.h #define SIZE 200 #define ERROR 1 #define OK 0 typedef struct { int data[SIZE]; int tos; } stack ; void init(stack *) ; int push(stack * , int) ; int pop(stack *) ; int top(stack *, int *) ; int isEmpty(stack *) ; int isFull(stack *) ;

32 stack.c #include "stack.h" void init(stack *s) { s->tos = -1; } int push(stack *s, int n) { if(isFull(s)) { printf("The STACK is full\n"); return ERROR ; s->tos++; s->data[s->tos]=n; return OK ; int Pop(stack *s) { if(isEmpty(s)) { printf("The STACK is empty\n"); return ERROR ; } s -> tos-- ; return OK ; int isFull(stack *s) { return s->tos == SIZE-1; int isEmpty(stack *s) { return s->tos == -1;

33 stack.c int Top(stack *s , int *val) { if (isEmpty(s)) { printf("The STACK is empty\n") ; return ERROR ; } *val = (s -> data[s -> tos]) ; return OK ;

34 Array Implementation of Stack
CAPACITY too large: waste memory CAPACITY too small: wasted space data data

35 Compiling the datatype
$ gcc -c stack.c We get the object module stack.o. We can construct library from it.

36 User Program: testStack.c
#include <stdio.h> #include "stack.h" int main() // testStack.c { stack s ; int x , err , val ; char c ; init(&s); printf(" ’U’ for push (U 15)\n ’O’ for pop\n ’T’ for top printf(" ’E’ for exit :\n");

37 while((c = getchar()). = ’e’ && c
while((c = getchar()) != ’e’ && c != ’E’) switch(c) { case ’U’ : scanf("%d",&x); err = push(&s,x); break; case ’O’ : err = pop(&s); case ’T’ : err = top(&s , &val) ; if(!err) printf("%d\n", val); case ’\n’ : case ’\t’ : case ’ ’ : break; default : printf("Token Unknown\n"); } return 0;

38 Compiling the user program
$ gcc -Wall testStack.c stack.o We get the executable module a.out.

39 Stack: Linked List Structure
PUSH OPERATION top Spring 2012 Programming and Data Structure

40 Stack: Linked List Structure
POP OPERATION top Spring 2012 Programming and Data Structure

41 Representation struct stack { int data ; struct stack *next ; }; typedef struct stackNode node, *stack ;

42 Interface functions (stackl.h)
#include <stdio.h> #include <stdlib.h> #define ERROR 1 #define OK 0 struct stack { int data ; struct stack *next ; } ; typedef struct stack node, *stack ; #define INIT(s) ((s)=NULL) #define ISEMPTY(s) ((s) == NULL) int push(stack * , int) ; int pop(stack *) ; int top(stack, int *) ;

43 Implementation File: stackSR.c
#include "stackSR.h" int push(stack *s, int n) { // stackSR.c stack temp ; temp=(stack)malloc(sizeof(node)) ; if(temp == NULL) { printf("The STACK is full\n"); return ERROR ; } temp->data=n; temp->next=*s ; *s = temp ; return OK ;

44 stackSR.c continued int pop(stack *s) { stack temp ; if(ISEMPTY(*s)) { printf("The STACK is empty\n"); return ERROR ; } temp=*s; *s=(*s)->next ; free(temp) ; return OK ;

45 stackSR.c continued int top(stack s , int *val) { if(ISEMPTY(s)) { printf("The STACK is empty\n") ; return ERROR ; } *val = s -> data ; return OK ;

46 User Program: testStack.c
#include <stdio.h> #include "stackSR.h" int main() // testStackSR.c { stack s ; int x , err , val ; char c ; INIT(s); printf(" ’U’ for push (U 15)\n ’O’ for pop\n ’T’ for top printf(" ’E’ for exit :\n");

47 while((c = getchar()). = ’e’ && c
while((c = getchar()) != ’e’ && c != ’E’) switch(c) { case ’U’ : scanf("%d",&x); err = push(&s,x); break; case ’O’ : err = pop(&s); case ’T’ : err = top(s , &val) ; if(!err) printf("%d\n", val); case ’\n’ :case ’\t’ :case ’ ’ : break; default :printf("Token Unknown\n"); } return 0;

48 Programming and Data Structure
Queue Implementation Spring 2012 Programming and Data Structure

49 Queues in Our Life A queue is a FIFO structure: Fast In First Out
Figure 5-1 Queues in Our Life A queue is a FIFO structure: Fast In First Out

50 Circular Arrays 1 3 2 4 5 6 7 Neat trick: use a circular array to insert and remove items from a queue in constant time The idea of a circular array is that the end of the array “wraps around” to the start of the array

51 Queue will overgrow the array
Figure 5-16 Queue will overgrow the array Should we use VERY L A R G E ARRAYS?

52 Array implementation of queues
queueAry maxsize count front rear 7 4 1 5 front rear 11 37 22 15 3 -7 1

53 Queue on Circular Array: Representation
#define MAX 200 typedef struct { int data[MAX] ; int front , rear ; } queue; The queue may contain MAX - 1 data.

54 Queue on Circular Array: Operations
void init(queue *) ; int add(queue *, int) ; int delete(queue *); int front(queue *, int *) ; int isEmpty(queue *) ; int isFull(queue *) ;

55 Interface File: queue.h
#include <stdio.h> #define MAX 200 #define ERROR 1 #define OK 0 typedef struct { int data[MAX]; int front, rear; } queue; /* Queue may contain MAX-1 data.*/ void init(queue *); int add(queue *, int); int delete(queue *); int front(queue *, int *); int isEmpty(queue *); int isFull(queue *);

56 Implementation File: queue.c
#include "queue.h" void init(queue *q) { q->front=q->rear=0; } int isEmpty(queue *q) { return q->rear == q->front; } int isFull(queue *q) { return (q->rear+1)%MAX == q->front; }

57 int add(queue *q, int n) { if(isFull(q)) return ERROR; q->rear=(q->rear+1)%MAX; q->data[q->rear]=n; return OK ; } int delete(queue *q) { if(isEmpty(q)) return ERROR ; q->front=(q->front+1)%MAX ;

58 int front(queue. q , int. v) { if(isEmpty(q)) return ERROR ;
int front(queue *q , int *v) { if(isEmpty(q)) return ERROR ; *v=q->data[(q->front+1)%MAX] ; return OK ; }

59 User Program: testQueue.c
#include "queue.h" int main() { queue q ; int x , err , val ; char c; init(&q); printf(" ’A’ for add (A 15)\n") ; printf(" ’D’ for delete\n ’F’ for front\n ’E’ for exit while((c = getchar()) != ’e’ && c != ’E’) switch(c) {

60 case ’A’ : scanf("%d",&x); err = add(&q,x); if(err) printf("Queue is full\n") ; break; case ’D’ : err = delete(&q); printf("Q empty\n") ; case ’F’ : err = front(&q , &val)

61 if(err) printf("Q empty\n") ; else printf("%d\n",val); break; case ’\n’ :case ’\t’ :case ’ ’ : default : printf("Token Unknown\n"); } return 0 ;

62

63 Programming and Data Structure
Basic Idea Create a linked list to which items would be added to one end and deleted from the other end. Two pointers will be maintained: One pointing to the beginning of the list (point from where elements will be deleted). Another pointing to the end of the list (point where new elements will be inserted). Rear Front DELETION INSERTION Spring 2012 Programming and Data Structure

64 QUEUE: LINKED LIST STRUCTURE
ENQUEUE front rear Spring 2012 Programming and Data Structure

65 QUEUE: LINKED LIST STRUCTURE
DEQUEUE front rear Spring 2012 Programming and Data Structure

66 QUEUE using Linked List
#include <stdio.h> #include <stdlib.h> #include <string.h> struct node{ char name[30]; struct node *next; }; typedef struct node _QNODE; typedef struct { _QNODE *queue_front, *queue_rear; } _QUEUE; Spring 2012 Programming and Data Structure

67 Programming and Data Structure
_QNODE *enqueue (_QUEUE *q, char x[]) { _QNODE *temp; temp= (_QNODE *) malloc (sizeof(_QNODE)); if (temp==NULL){ printf(“Bad allocation \n"); return NULL; } strcpy(temp->name,x); temp->next=NULL; if (q->queue_rear==NULL) { q->queue_rear=temp; q->queue_front=q->queue_rear; else { q->queue_rear->next=temp; return(q->queue_rear); Spring 2012 Programming and Data Structure

68 Programming and Data Structure
char *dequeue(_QUEUE *q,char x[]) { _QNODE *temp_pnt; if(q->queue_front==NULL){ q->queue_rear=NULL; printf("Queue is empty \n"); return(NULL); } else{ strcpy(x,q->queue_front->name); temp_pnt=q->queue_front; q->queue_front= q->queue_front->next; free(temp_pnt); if(q->queue_front==NULL) q->queue_rear=NULL; return(x); } Spring 2012 Programming and Data Structure

69 Programming and Data Structure
void init_queue(_QUEUE *q) { q->queue_front= q->queue_rear=NULL; } int isEmpty(_QUEUE *q) if(q==NULL) return 1; else return 0; Spring 2012 Programming and Data Structure

70 Programming and Data Structure
int main() { int i,j; char command[5],val[30]; _QUEUE q; init_queue(&q); command[0]='\0'; printf("For entering a name use 'enter <name>'\n"); printf("For deleting use 'delete' \n"); printf("To end the session use 'bye' \n"); while(strcmp(command,"bye")){ scanf("%s",command); Spring 2012 Programming and Data Structure

71 Programming and Data Structure
if(!strcmp(command,"enter")) { scanf("%s",val); if((enqueue(&q,val)==NULL)) printf("No more pushing please \n"); else printf("Name entered %s \n",val); } if (!strcmp(command,"delete")) { if (!isEmpty(&q)) printf("%s \n",dequeue(&q,val)); else printf("Name deleted %s \n",val); } } /* while */ printf("End session \n"); Spring 2012 Programming and Data Structure

72 Problem With Array Implementation
ENQUEUE DEQUEUE Effective queuing storage area of array gets reduced. N front rear rear front Use of circular array indexing Spring 2012 Programming and Data Structure

73 Queue: Example with Array Implementation
#define MAX_SIZE 100 typedef struct { char name[30]; } _ELEMENT; typedef struct { _ELEMENT q_elem[MAX_SIZE]; int rear; int front; int full,empty; } _QUEUE; Spring 2012 Programming and Data Structure

74 Programming and Data Structure
Queue Example: Contd. void init_queue(_QUEUE *q) { q->rear= q->front= 0; q->full=0; q->empty=1; } int IsFull(_QUEUE *q) { return(q->full); int IsEmpty(_QUEUE *q) { return(q->empty); Spring 2012 Programming and Data Structure

75 Programming and Data Structure
Queue Example: Contd. void AddQ(_QUEUE *q, _ELEMENT ob) { if(IsFull(q)) {printf("Queue is Full \n"); return;} q->rear=(q->rear+1)%(MAX_SIZE); q->q_elem[q->rear]=ob; if(q->front==q->rear) q->full=1; else q->full=0; q->empty=0; return; } Spring 2012 Programming and Data Structure

76 Programming and Data Structure
Queue Example: Contd. _ELEMENT DeleteQ(_QUEUE *q) { _ELEMENT temp; temp.name[0]='\0'; if(IsEmpty(q)) {printf("Queue is EMPTY\n");return(temp);} q->front=(q->front+1)%(MAX_SIZE); temp=q->q_elem[q->front]; if(q->rear==q->front) q->empty=1; else q->empty=0; q->full=0; return(temp); } Spring 2012 Programming and Data Structure

77 Programming and Data Structure
Queue Example: Contd. main() { int i,j; char command[5]; _ELEMENT ob; _QUEUE A; init_queue(&A); command[0]='\0'; printf("For adding a name use 'add [name]'\n"); printf("For deleting use 'delete' \n"); printf("To end the session use 'bye' \n"); #include <stdio.h> #include <stdlib.h> #include <string.h> Spring 2012 Programming and Data Structure

78 Programming and Data Structure
Queue Example: Contd. while (strcmp(command,"bye")!=0){ scanf("%s",command); if(strcmp(command,"add")==0) { scanf("%s",ob.name); if (IsFull(&A)) printf("No more insertion please \n"); else { AddQ(&A,ob); printf("Name inserted %s \n",ob.name); } Spring 2012 Programming and Data Structure

79 Programming and Data Structure
Queue Example: Contd. if (strcmp(command,"delete")==0) { if (IsEmpty(&A)) printf("Queue is empty \n"); else { ob=DeleteQ(&A); printf("Name deleted %s \n",ob.name); } } /* End of while */ printf("End session \n"); Spring 2012 Programming and Data Structure

80 Terminology Infix -3+4 Postfix -3 4 + Prefix + -3 4 6-80

81 Postfix Expressions The calculation: ((1 + 2) * 4) + 3 can be written down in postfix notation with the advantage of no precedence rules and no parentheses needed. * 3 + 6-81

82 The expression is evaluated from the left to right using a stack:
when encountering an operand, push the operand when encountering an operator, pop two operands and evaluate the value then push the result. 6-82

83 Solution 1 2 + 4 * 3 + when encountering an operand, push the operand
when encountering an operation, pop two operands and evaluate the value then push the result. * 3 + 6-83

84 Stack Usage Examples Browser “back” button: takes you to the page visited before the current page Editor “undo” button: takes you to the state of the document before the current state Process stacks: stores call frames to support method calls. The call frame on top of the stack is the currently executing method, the call frame below it represents the method invoked before the current method, and so on Many virtual machines are also stack-oriented, including the p-code machine and the Java virtual machine. 6-84

85 Properties Stack: a Last-In-First-Out (LIFO) data structure – the last item into the stack is the first out of it Attributes: top – references the element on top of the stack Operations: push(element), pop(), peek(), isEmpty(), size() 6-85

86 Stack Operations Stack() pre-condition: none
responsibilities: constructor – initialize the stack attributes post-condition: size is 0 top refers to null (a special value not part of the stack) returns: nothing push( Type ) responsibilities: push element onto the top of the stack post-condition: element is placed on top of the stack size is incremented by 1 top refers to the element pushed 6-86

87 Stack Operations pop() pre-condition: isEmpty() is false
responsibilities: remove and return the element at top post-condition: the top element is no longer in the stack size is decremented by 1 top refers to the element below the previous topmost element or null if the stack is empty returns: the element removed throws: empty stack exception if pre-condition is not met 6-87

88 Stack Operations peek() pre-condition: isEmpty() is false
responsibilities: return the element at top post-condition: the stack is unchanged returns: the element referenced by top throws: empty stack exception if pre-condition is not met 6-88

89 Goals for the Stack Hide implementation details from the client
Put only the interface in stack.h, and implementation in stack.c Only allow the client to have a pointer to a Stack Allow multiple instances of stacks in the same program Define a type of Stack, rather than a global variable in stack.c Allow different stacks to have different kinds of elements Allow another abstract data type to define the type of Item Only allow the Stack to refer to a pointer to an Item Allow different stacks with different element types in the same program Using void pointers

90 Stack Interface (stack.h)
#ifndef STACK_INCLUDED #define STACK_INCLUDED typedef struct Item *Item_T; typedef struct Stack *Stack_T; Stack_T Stack_new(void); int Stack_empty(Stack_T stk); void Stack_push(Stack_T stk, Item_T item); Item_T Stack_pop(Stack_T stk); #endif What’s this for? Including a .h file more than once in another file is fine if it is just declarations, but this one has definitions (i.e., the typedefs) so can’t be defined twice.

91 Notes on stack.h Type Stack_T is an opaque pointer
Clients can pass Stack_T around but can’t look inside Definition of Stack can change without recompiling the client code Type Item_T is also an opaque pointer … but defined in some other ADT So, Stack implementation doesn’t need to know about it And, Stack implementation can be used for many kinds of items Stack_ is a disambiguating prefix A convention that helps avoid name collisions

92 Stack Implementation: Array
stack.c #include <assert.h> #include <stdlib.h> #include “stack.h” enum {CAPACITY = 1000}; struct Stack { int count; Item_T data[CAPACITY]; }; Stack_T Stack_new(void) { Stack_T stk = malloc(sizeof(*stk)); assert(stk != NULL); stk->count = 0; return stk; }

93 Careful Checking With Assert
stack.c #include <assert.h> #include <stdlib.h> #include “stack.h” enum {CAPACITY = 1000}; struct Stack { int count; Item_T data[CAPACITY]; }; Stack_T Stack_new(void) { Stack_T stk = malloc(sizeof(*stk)); assert(stk != NULL); stk->count = 0; return stk; } Make sure stk!=NULL, or halt the program!

94 Stack Implementation: Array (Cont.)
int Stack_empty(Stack_T stk) { assert(stk != NULL); return (stk->count == 0); } void Stack_push(Stack_T stk, Item_T item) { assert(stk->count < CAPACITY); stack->data[stack->count] = item; stack->count++; Item_T Stack_pop(Stack_T stk) { assert(stk->count > 0); stk->count--; return stk->data[stk->count]; 1 2 3 4 5 count is 3 CAPACITY is 6

95 Problems With Array Implementation
CAPACITY too large: waste memory CAPACITY too small: assertion failure (if you were careful) buffer overrun (if you were careless) wasted space data data

96 Linked List Would be Better…
struct List { int val; struct List *next; } *head; next val head empty stack push(1); push(2); push(3); 3 2 1 head

97 Popping and Pushing 3 2 1 head pop( ); head 3 2 1 head 2 1 4 push(4);

98 Stack Implementation: Linked List
stack.c #include <assert.h> #include <stdlib.h> #include “stack.h” struct Stack {struct List *head;}; struct List {Item_T val; struct List *next;}; Stack_T Stack_new(void) { Stack_T stk = malloc(sizeof(*stk)); assert(stk != NULL); stk->head = NULL; return stk; }

99 Stack Implementation: Linked List
int Stack_empty(Stack_T stk) { assert(stk != NULL); return (stk->head == NULL); } void Stack_push(Stack_T stk, Item_T item) { struct List *t = malloc(sizeof(*t)); assert(t != NULL); t->val = item; t->next = stk->head; stk->head = t; t 4 3 2 1 head

100 stack.c, continued Item_T Stack_pop(Stack_T stk) { Item_T x;
struct List *p; assert(stk != NULL); assert(stk->head != NULL); x = stk->head->val; p = stk->head; stk->head = stk->head->next; free(p); return x; } 3 2 1 head

101 Client Program: Uses Interface
client.c #include <stdio.h> #include <stdlib.h> #include “item.h” #include “stack.h” int main(int argc, char *argv[]) { int i; Stack_T s = Stack_new(); for (i = 1; i < argc; i++) Stack_push(s, Item_new(argv[i])); while (!Stack_empty(s)) Item_print(Stack_pop(s)); return 0; }

102 Problem: Multiple Kinds of Stacks?
Good, but still not flexible enough What about a program with multiple kinds of stacks E.g., a stack of books, and a stack of pancakes But, you can only define Item_T once Solution in C, though it is a bit clumsy Don’t define Item_T (i.e., let it be a “void *”) Good flexibility, but you lose the C type checking typedef struct Item *Item_T; typedef struct Stack *Stack_T; Stack_T Stack_new(void); int Stack_empty(Stack_T stk); void Stack_push(Stack_T stk, void *item); void *Stack_pop(Stack_T stk);

103 stack.h (with void*) #ifndef STACK_INCLUDED #define STACK_INCLUDED
typedef struct Item *Item_T; typedef struct Stack *Stack_T; Stack_T Stack_new(void); int Stack_empty(Stack_T stk); void Stack_push(Stack_T stk, void *item); void *Stack_pop(Stack_T stk); #endif

104 Stack Implementation (with void*)
stack.c #include <assert.h> #include <stdlib.h> #include “stack.h” struct Stack {struct List *head;}; struct List {void *val; struct List *next;}; Stack_T Stack_new(void) { Stack_T stk = malloc(sizeof(*stk)); assert(stk); stk->head = NULL; return stk; }

105 stack.c (with void*) continued
int Stack_empty(Stack_T stk) { assert(stk != NULL); return stk->head == NULL; } void Stack_push(Stack_T stk, void *item) { Stack_T t = malloc(sizeof(*t)); assert(t != NULL); t->val = item; t->next = stk->head; stk->head = t;

106 stack.c (with void*) continued
void *Stack_pop(Stack_T stk) { void *x; struct List *p; assert(stk != NULL); assert(stk->head != NULL); x = stk->head->val; p = stk->head; stk->head = stk->head->next; free(p); return x; }

107 Client Program (With Void)
client.c (with void*) #include <stdio.h> #include <stdlib.h> #include “item.h” #include “stack.h” int main(int argc, char *argv[]) { int i; Stack_T s = Stack_new(); for (i = 1; i < argc; i++) Stack_push(s, Item_new(argv[i])); while (!Stack_empty(s)) printf(“%s\n”,Stack_pop(s)); return 0; }

108 Structural Equality Testing
Suppose we want to test two stacks for equality: int Stack_equal(Stack_T s1, Stack_T s2); How can this be implemented? int Stack_equal(Stack_T s1, Stack_T s2) { return (s1 == s2); } We want to test whether two stacks are equivalent stacks, not whether they are the same stack.

109 Almost, But Not Quite... How about this: int Stack_equal(Stack_T s1, Stack_T s2) { struct List *p, *q; for (p=s1->head, q=s2->head; p && q; p=p->next, q=q->next) if (p->val != q->val) return 0; return p==NULL && q==NULL; } This is better, but what we want to test whether s1->val is equivalent to s2->val, not whether it is the same.

110 Item ADT Provides Equal Test
How about this: int Stack_equal(Stack_T s1, Stack_T s2) { struct List *p, *q; for (p=s1->head, q=s2->head; p && q; p=p->next, q=q->next) if ( ! Item_equal(p->val, q->val)) return 0; return p==NULL && q==NULL; } This is good for the “Item_T” version of stacks (provided the Item interface has an Item_equal function), but what about the void* version of stacks?


Download ppt "Abstract Data Types."

Similar presentations


Ads by Google