1
ADTAbstract Data Types
The Stack Example
2
ADT
יוצגו שלושה פתרונות לבעיה זו :
- נועד להמחשת הבעיה.פתרון ישיר ופשוט•- של מחסנית ADTפתרון אשר נעזר ב •
פתרון זה מפריד בין האפליקציה לבין מבנה הנתונים ומאפשר להיעזר במחסנית
גם בתוכניות אחרות אולם מייצר מבנה נתונים המאפשר לשמור רק תווים.
- כלומר גנרי ADTפתרון אשר נעזר ב •ADT המאפשר להגדיר מחסניות השומרות
טיפוסי נתונים שונים – ובפרט תווים.
לצורך הכרות עם מבנה נתונים הממומש ניעזר בדוגמה הבאה לאורך ADTכ
השיעור: 100נרצה לקרוא מהקלט הסטנדרטי
תווים ולהדפיסם בסדר הפוך לסדר בו .נקראו
3
תווים100תוכנית להיפוך Reverese.c
#include <stdio.h>
int main() {int c ;char array[100];int cur = 0;
while ((c=getchar()) != EOF && cur<100) {array[cur] = c ;cur++ ;}while (cur) printf( "%c\n", array[--cur]) ;
return 0;}
4
הטיפוס האבסטרקטי - מחסנית ) המאפשר ) טיפוס הנה כעת שנראה המחסנית
, רגע בכל כאשר תווים של מסוים מספר שמירתלמחסנית ) שהוכנס האחרון התו רק נגיש Lastנתון
In First Out .): הבאות בפעולות תומך הטיפוס
• pushpush . ) למחסנית - ) תו איבר הוסף• poppop ) שהוכנס - ) האחרון התו האיבר את הוצא
.) ערכו ) את להחזיר מבלי למחסנית• toptop ) האחרון - ) התו האיבר של ערכו את החזר
אותו ) להוציא מבלי למחסנית שהוכנסמהמחסנית(.
• countcount . ) במחסנית - ) יש תווים איברים כמהובנוסף:
• createcreate.) ריק - ) מחסנית מסוג נתונים מבנה צור• destroy. מחסנית - הנתונים מבנה את הרוס
http://www.cosc.canterbury.ac.nz/people/mukundan/dsal/StackAppl.html
5
טיפוס נתונים אבסטרקטי - Iממשק
Stack.h#ifndef _STACK_H#define _STACK_H
/* ADT of Stack of characters */typedef struct Stack_t* Stack ;
/* possible return values */typedef enum {Fail, Success}
Result ;
/* IMPORTANT all functions get the stack that they should work on ! */
/* creates a Stack. sets the stack maximal capcity to max_size. If fails, returns NULL*/
Stack create(int max_size) ;
/* releases the memory allocated for the stack. */
void destroy(Stack s) ;
6
טיפוס נתונים אבסטרקטי - ממשק II
/* insert a char to the top of the stack. fails if s==NULL, or if the stack is full. */ Result push(Stack s, char c) ;
/* removes the char at the top of the stack. fails if s == NULL, or if the stack is empty. */Result pop(Stack s) ;
/* returns in pc the last element that was pushed.
Fails if s == NULL or pc == NULL or if the stack s is empty. */
Result top(Stack s, char* pc) ;
/* returns the number of elements in the stack. Returns -1 if s == NULL. */int count(Stack s);
#endif
7
מימוש אפשרי של המחסניתנגדיר מבנה שבו שלושה
שדות:מערך בו ישמרו התווים.•שדה אשר ישמור את גודל •
המערך )וכתוצאה את מספר התווים המקסימלי שיכולים
להישמר(שדה שישמור את מספר •
התווים השמורים במחסנית - שהנו גם האינדקס במערך
אליו יוכנס התו הבא.
‘a’top
‘z’‘b’‘a’
8
Iטיפוס נתונים אבסטרקטי - מימוש Stack.c
#include <stdlib.h>#include "Stack.h"
/* a structure that represents a Stack. one structure for each Stack */
struct Stack_t {/* The Stack is implemented as an array of characters. With top as an index to the next available position and maximal size stored in maxCapacity. */char* array ;int top ;int maxCapacity ;
} ;
9
IIטיפוס נתונים אבסטרקטי - מימוש Stack create(int max_size) {
Stack s ;char* tmp = NULL;
if (max_size <=0) return NULL ;
s = (Stack) malloc (sizeof(struct Stack_t)) ;if (s == NULL) return NULL;tmp= (char*) malloc (max_size) ; if (tmp == NULL) {free (s) ;return NULL ;}s->top = 0; s->maxCapacity = max_size ;s->array = tmp;
return s;}
10
IIIטיפוס נתונים אבסטרקטי - מימוש Result push(Stack s, char c) {
if ((s == NULL) || (s->top >= s->maxCapacity))return Fail ;
s->array[s->top] = c ;s->top++ ;return Success ;
}
Result pop(Stack s) {if ((s == NULL) || (s->top == 0)) return Fail ;
s->top--;return Success ;
}
11
IVטיפוס נתונים אבסטרקטי - מימוש Result top(Stack s, char* pc) {
if ((s == NULL) || (s->top == 0) || (pc == NULL))
return Fail ;
*pc = s->array[s->top-1];return Success ;
}
int count(Stack s) {if ((s == NULL))return -1;return s->top ;
}
Result destroy(Stack s) {if (s == NULL) return;free(s->array);free(s);
}
12
שימוש בטיפוס הנתונים האבסטרקטי#include <stdio.h>#include "Stack.h"
int main() {int c ;char t ;Stack even, odd ;even=create(100) ; odd=create(100) ;while(1) {
if ((c = getchar()) == EOF) break ;
push(even,c);if ((c = getchar()) == EOF) break
;push(odd,c);
}while (count(odd) > 0) {
top(odd,&t ); putchar(t); pop(odd);}while (count(even) > 0) {
top(even,&t ); putchar(t); pop(even);}return 0;
}
חסר ? מה
התחשבות 200היפוך תוך תוויםהאי ) כל יופיעו קודם בזוגיותכך ואחר הפוך בסדר זוגיים
) הפוך בסדר הזוגיים
13
Generic ADT
The stack example
generic version
14
Generic ADTשימוש במצביעים לפונקציות ב
ADT לא משנה איזה טיפוסי נתונים יכיל, ADTלרוב ל
בין אם הם מחרוזות, מבנים, שלמים או תווים. תהיה ADTבכל מקרה ה-“לוגיקה” של ה
זהה. למשל, מחסנית תמיד תוציא את האיברים
שהוכנסו אליה בסדר הפוך לסדר ההכנסה )LIFO.ללא קשר לטיפוס האיברים - (
שמסוגל להכיל כללי ADTעל כן, נרצה לכתוב איברים מכל טיפוס שהוא. בדרך זו מספיק
רק פעם אחת כדי שנקבל ADTלכתוב את ה-ADT.שמסוגל לפעול על כל סוג של נתונים
לא ידע כיצד לבצע ADTהבעיה הנה שה-פעולות פשוטות הנוגעות לאיברים - למשל
להעתיק איבר, להדפיס איבר, למחוק איבר וכדומה, שכן ביצוע פעולות אלו דורש ידיעה
. הפתרון ADTשל סוג הטיפוס שנמצא ב-לבעיה זו הוא שימוש במצביעים לפונקציות:
מעביר בעת אתחול ADTהמשתמש ב- מצביעים לפונקציות שמבצעות את ADTה-
הפעולות הספציפיות לטיפוס.
15
טיפוס נתונים אבסטרקטי - I Stack.hממשק
#ifndef STACK_H#define STACK_H/* ADT of a generic Stack */typedef struct Stack_t* Stack ;typedef void* Elem;typedef Elem (*cpy_func)(Elem);typedef void (*free_func)(Elem);
/* possible return values */typedef enum {Fail, Success}
Result ;
/* Initialize the Stack. Sets the stack maximal capacity to max_size. Save pointers to functions. If fails, return NULL */
Stack create(int max_size, cpy_func cpy_elm, free_func free_elm );
/* Releases all the resources of the stack */void destroy (Stack s) ;
16
IIטיפוס נתונים אבסטרקטי - ממשק
/* Insert a copy of the element to the top of the stack. Fails if s == NULL, or elm == NULL or if the stack is full. */
Result push(Stack s, Elem elm) ;
/* Removes the elment at the top of the stack. Fails if s == NULL or if the stack is empty. */ Result pop(Stack s) ;
/* Returns a copy of the element in the top of the stack.
Fails if s == NULL or pelem == NULL. */ Result top(Stack s, Elem* pelm) ;
/* Returns the number of elements in the stack. Returns -1 if s == NULL. */int count(Stack s);
#endif
17
Iטיפוס נתונים אבסטרקטי - מימוש
Stack.c#include <stdlib.h>#include "Stack.h"
/* A structure that represents a Stack. One structure for each Stack *//* Each stack keeps pointers to functions that
treat elements */struct Stack_t {
Elem* array ;int top ;int maxCapacity ; cpy_func cp_elm; free_func fr_elm;
} ;
18
טיפוס נתונים אבסטרקטי - מימוש II
Stack create(int max_size, cpy_func copy_elm, free_func free_elm){
Stack s ;
if (max_size <=0 || free_elm==NULL || copy_elm == NULL)
return NULL ;
s = (Stack) malloc (sizeof(struct Stack_t)) ;if (s== NULL) return NULL;s->array = (Elem*)malloc(max_size*sizeof(Elem)) ; if (s->array == NULL) {free(s) ; return NULL ;}s->top = 0; s->maxCapacity = max_size ;s->cp_elm = copy_elm ;
s->fr_elm = free_elm;
return s ; }
19
טיפוס נתונים אבסטרקטי -מימוש III
Result push(Stack s, Elem elm) {Elem tmp = NULL;if ( s == NULL || elm == NULL ||
s->top >= s->maxCapacity )
return Fail;
tmp = s->cp_elm(elm) ;if (tmp == NULL)
return Fail ;
s->array[s->top] = tmp; s->top++ ;return Success ;
}
20
טיפוס נתונים אבסטרקטי -מימוש IV
Result pop(Stack s) { if ((s == NULL) || (s->top == 0))
return Fail ; s->top--; s->fr_elem(s->array[s->top]); return Success ;}
Result top(Stack s, Elem* pelm) { Elem tmp = NULL;
if (s == NULL || s->top == 0 || pelm == NULL) return Fail ;
tmp = s->cp_elm(s->array[s->top -1]); *pelm = tmp;
return (tmp == NULL) ? Fail : Success ;}
21
Vטיפוס נתונים אבסטרקטי -מימוש
int count(Stack s) {if (s == NULL)
return -1;
return s->top;}
void destroy (Stack s) {if (s == NULL)
return;while (s->top> 0
&& pop(s) == Success) ;free(s->array);free(s);
}
? דרוש התנאי האם
22
שימוש בטיפוס הנתונים האבסטרקטי: מחרוזות100היפוך
#include <stdio.h>#include <string.h> #include "Stack.h"/* functions that will be used by the ADT */Elem cp_str(Elem s) {
char *cp;if (s == NULL) return NULL;cp = (char*) malloc (strlen((char*) s) + 1);strcpy(cp, (char*) s);return cp;
}
void fr_str (void* s) {free (s);
}
ADTבכדי שנוכל לנצל ב את המצביעים לפונקציות
על כולן להיות עם אותו ממשק, לכן במקום לציין
את הטיפוס בו הן מטפלות כחלק מהגדרת הפונקציה,
נגדירן תמיד כפונקציות ונבצע voidהמטפלות ב *
. castingבתוכן
? שנראה כדי מחרוזות למהשהוא טיפוס עם שהעבודה
במיוחד קשה איננה מורכב יחסיתשל הפרטי למקרה .charביחס
23
המשך דוגמא
int main() {char str[256] ;Elem tmp;Stack st ;st = create (100, cp_str, fr_str) ; if (st == NULL)
return 1 ;while(fgets(str,256,stdin) != NULL)
push(st,(Elem) str);while (count(st) > 0) {
top(st, &tmp) ; printf (“%s\n”, (char*) tmp); pop(st);fr_str(tmp);
}destroy(st);return 0;
}
24
דרך נוספת לבצוע אתחול מבנהשימוש במצביע למצביע
Result create(Stack* ps, int max_size) {Stack s = NULL ;if ((max_size <=0) || (ps == NULL)) return Fail ;*ps = NULL;s = (Stack) malloc (sizeof(struct Stack_t)) ;if (s == NULL) return Fail;s->array = (char*) malloc (max_size) ; if (s->array == NULL) {free (s) ;return Fail ;}s->top = 0; s->maxCapacity = max_size ;
*ps = s ; /* VERY IMPORTANT */
return Success ; }
Top Related