45
ססססס סס'5 ADT םם םםםם םםםםםם ADT םםםםםם םםםםם םםםם םםםםםם םםםם םםםםםם

תרגול מס' 5

  • Upload
    tehya

  • View
    78

  • Download
    8

Embed Size (px)

DESCRIPTION

תרגול מס' 5. ADT של מבני נתונים ADT גנריים בחירת מבני נתונים שאלה לדוגמה. ADT של מבני נתונים. פתרון בעיה ישירות מבני נתונים מחסנית פתרון הבעיה בעזרת מחסנית. בעיה לדוגמה. נרצה לקלוט 100 מספרים אי שליליים מהקלט ולהדפיס אותם בסדר הפוך - PowerPoint PPT Presentation

Citation preview

Page 1: תרגול מס' 5

5תרגול מס' ADTשל מבני נתונים ADTגנריים בחירת מבני נתוניםשאלה לדוגמה

Page 2: תרגול מס' 5

2מבוא לתכנות מערכות - 234122

ADTשל מבני נתונים

פתרון בעיה ישירותמבני נתוניםמחסניתפתרון הבעיה בעזרת מחסנית

Page 3: תרגול מס' 5

3מבוא לתכנות מערכות - 234122

בעיה לדוגמה

מספרים אי שליליים מהקלט ולהדפיס אותם בסדר 100נרצה לקלוט הפוך

בזמן הכנסת הקלט המשתמש יכול להתחרט ולבטל את הכנסת המספרהאחרון

-1לצורך כך הוא צריך להכניס –

פעולת הביטול דומה לפעולת“undoבעורכי טקסטים ”

“ המשתמש יכול לבצעundoכמה פעמים ולבטל כמה מספרים ”

נפתור תחילה את הבעיה הזו ישירות

Page 4: תרגול מס' 5

4מבוא לתכנות מערכות - 234122

פתרון ישיר#include <stdio.h>#include <assert.h>#define MAX_SIZE 100#define UNDO_LAST_COMMAND -1 int main() {

int input, size = 0, numbers[MAX_SIZE];while (size < MAX_SIZE && scanf("%d", &input) == 1) {

if (input != UNDO_LAST_COMMAND) {assert(size >= 0 && size < MAX_SIZE);numbers[size++] = input;continue;

}if (size < 1) {

printf("No numbers were entered until now\n");continue;

}size--;printf("undo\n");

}while (size > 0) {

printf("%d\n", numbers[--size]);assert(size >= 0 && size < MAX_SIZE);

}return 0;

}

Page 5: תרגול מס' 5

5מבוא לתכנות מערכות - 234122

חסרונות הפתרון הישירלא ניתן לעשות שימוש חוזר בקוד עבור בעיות דומות

קל להכניס באגים–size-- או --size?

–size++ או ++size?

– size > 0 אוsize >= 0?

–size < 1 או size < 0?

הפתרון אינו מתעד את עצמומוסיפים רק לסוף המערך–

מורידים מספרים רק מסוף המערך–

ההדפסה מתבצעת רק בסדר הפוך–

עבור בעיה גדולה יותר, כבר לא ניתן לשמור על הקוד פשוט כמו במקרה זה

Page 6: תרגול מס' 5

6מבוא לתכנות מערכות - 234122

מבני נתונים

הם טיפוסי נתונים מיוחדים שמטרתם לשמור אוסף של מבני נתוניםמשתנים ולאפשר עליהם פעולות מסוימות

:דוגמאות- המנשק של מערך כולל קריאת איברים לפי אינדקס והשמה מערך–

לאיברים לפי אינדקס

- המנשק של רשימה מקושרת כולל קריאת איברים רשימה מקושרת –מהרשימה והכנסה/הוצאה של איברים מכל מקום ברשימה

נוח לכתוב מבני נתונים נוספים כטיפוס נתונים ולהשתמש בהם עבורבעיות מתאימות

Page 7: תרגול מס' 5

7מבוא לתכנות מערכות - 234122

Stackמחסנית - מוגדר לפי המנשק הבא:מחסניתמבנה הנתונים push הוסף איבר למחסנית -pop הוצא את האיבר האחרון שהוכנס למחסנית )מבלי -

להחזיר את ערכו(top החזר את ערכו של האיבר האחרון שהוכנס -

למחסנית )מבלי להוציאו(

מחסנית מאפשרת גישה רק לאיבר האחרון שהוכנס ורק(LIFO - Last In First Outאותו ניתן להוציא ברגע נתון )

:המחשת מחסניתhttp://

www.cosc.canterbury.ac.nz/people/mukundan/dsal/StackAppl.html

Page 8: תרגול מס' 5

8מבוא לתכנות מערכות - 234122

ADT - מחסנית stack.h#ifndef _STACK_H#define _STACK_H /** ADT of Stack of integers */typedef struct Stack_t* Stack; /** possible return values */typedef enum {

STACK_BAD_ARGUMENT, STACK_SUCCESS, STACK_EMPTY, STACK_FULL} StackResult; /** creates a Stack with maximal capacity of 'maxSize'. if fails, returns NULL */Stack stackCreate(int maxSize); /** releases the memory allocated for the stack */void stackDestroy(Stack stack);

לא לשכוח הגנה איפה המבנה כפולincludeנגד

עצמו?מדוע?

ערכי שגיאות מוסכמים כדי לאפשר למשתמש להתמודד עם שגיאות

Page 9: תרגול מס' 5

9מבוא לתכנות מערכות - 234122

ADT - מחסנית stack.h/** insert a number to the top of the stack. Error Codes: STACK_BAD_ARGUMENT if stack is NULL STACK_FULL if the stack is full. */

StackResult stackPush(Stack stack, int number);

/** removes the element at the top of the stack. Error codes: STACK_BAD_ARGUMENT if stack is NULL STACK_EMPTY if the stack is empty */StackResult stackPop(Stack stack) /** returns in 'number' the last element that was pushed. Error codes: STACK_BAD_ARGUMENT if stack or number are NULL STACK_EMPTY if the stack is empty */StackResult stackTop(Stack stack, int* number) /** returns the number of elements in the stack. stack must not be NULL */int stackSize(Stack stack) #endif

Page 10: תרגול מס' 5

10מבוא לתכנות מערכות - 234122

פתרון הבעיה בעזרת מחסנית#include <stdio.h>#include <assert.h>#include <stdlib.h>#include "stack.h" #define MAX_INPUT_SIZE 100#define UNDO_LAST_COMMAND -1 int main() {

Stack stack = stackCreate(MAX_INPUT_SIZE);if (stack == NULL) {

fprintf(stderr, "failed to create stack\n");return -1;

}int input;while (stackSize(stack) < MAX_INPUT_SIZE && scanf("%d", &input) == 1) {

if (input != UNDO_LAST_COMMAND) {StackResult result = stackPush(stack, input);assert(result == STACK_SUCCESS);continue;

}StackResult result = stackPop(stack);if (result == STACK_EMPTY) {

printf("No numbers were entered until now\n");} else {

assert(result == STACK_SUCCESS);printf("undo\n");

}}

Page 11: תרגול מס' 5

11מבוא לתכנות מערכות - 234122

פתרון הבעיה בעזרת מחסנית 

while (stackSize(stack) > 0) {int number;StackResult result = stackTop(stack, &number);StackResult result2 = stackPop(stack);assert (result == STACK_SUCCESS && result2 ==

STACK_SUCCESS);printf("%d\n", number);

stackDestroy(stack);return 0;

}

Page 12: תרגול מס' 5

12מבוא לתכנות מערכות - 234122

2

17

3

מימוש המחסנית

נבחר לממש את המחסנית בעזרת מערך

נשמור שלושה שדות במבנהמערך בו יישמרו המספרים–

גודל המחסינת המקסימלי–

אינדקס המקום הפנוי הבא במערך–

זהו גם מספר האיברים במבנה•

?איזו דרך נוספת קיימת למימוש מחסנית

nextIndex

5

Page 13: תרגול מס' 5

13מבוא לתכנות מערכות - 234122

ADT - מחסנית stack.c#include <stdlib.h>#include <assert.h>#include "stack.h" /** The Stack is implemented as an array of integers. * With nextIndex as an index to the next available position and * the maximal size is stored in maxSize. */struct Stack_t {

int* array;int nextIndex;int maxSize;

}; 

Page 14: תרגול מס' 5

14מבוא לתכנות מערכות - 234122

ADT - מחסנית stack.cStack stackCreate(int maxSize) {

if (maxSize <= 0) {return NULL;

}Stack stack = malloc(sizeof(*stack));if (stack == NULL) {

return NULL;}stack->array = malloc(sizeof(int)*maxSize);if (stack->array == NULL) {

free(stack);return NULL;

}stack->nextIndex = 0;stack->maxSize = maxSize;return stack;

שימו לב, בשלב זה כבר יש הקצאה

שהצליחה

Page 15: תרגול מס' 5

15מבוא לתכנות מערכות - 234122

ADT - מחסנית stack.cStackResult stackPush(Stack stack, int number) {

if (stack == NULL) {return STACK_BAD_ARGUMENT;}if (stack->nextIndex >= stack->maxSize) {return STACK_FULL;}assert(stack->nextIndex >= 0 && stack->nextIndex < stack->maxSize);stack->array[stack->nextIndex++] = number;return STACK_SUCCESS;

} StackResult stackPop(Stack stack) {

if (stack == NULL) {return STACK_BAD_ARGUMENT;}if (stack->nextIndex < 1) {return STACK_EMPTY;}

 stack->nextIndex--;return STACK_SUCCESS;

}

Page 16: תרגול מס' 5

16מבוא לתכנות מערכות - 234122

ADT - מחסנית stack.cStackResult stackTop(Stack stack, int* number) {

if (stack == NULL || number == NULL) {return STACK_BAD_ARGUMENT;

}if (stack->nextIndex < 1) {

return STACK_EMPTY;}assert(stack->nextIndex > 0 && stack->nextIndex <= stack->maxSize);*number = stack->array[stack->nextIndex - 1];return STACK_SUCCESS;

}

int stackSize(Stack stack) {assert(stack);return stack->nextIndex;

} void stackDestroy(Stack stack) {

if (stack != NULL) {free(stack->array);free(stack);

}}

כיצד ניתן לכתוב את פונקציה זו בצורה שונה כך שתחזיר ערכי שגיאה?

מה היתרונות והחסרונות של כל שיטה?

Page 17: תרגול מס' 5

17מבוא לתכנות מערכות - 234122

ADTשל מבני נתונים - סיכום

-ניתן להגדיר מבני נתונים כADT ע"י פתרון הבעיה עם מבנה המחסנית מתקבל פתרון עם סיכוי קטן יותר

לבאגיםהפתרון עם המחסנית מתעד את עצמושימוש במבני נתונים מונע שכפול קודשימוש במבני נתונים מבטיח את אופן העבודה עם הנתוניםשימוש במבני הנתונים מקל על המתכנת בכתיבת קוד

Page 18: תרגול מס' 5

18מבוא לתכנות מערכות - 234122

ADTגנריים

מבני נתונים גנרייםמחסנית גנריתשימוש במחסנית הגנרית

Page 19: תרגול מס' 5

19מבוא לתכנות מערכות - 234122

מבני נתונים גנריים

המחסנית שלנו מתאימה רק למספרים שלמיםבדרך כלל נשתמש בטיפוסים מורכבים יותר–

נצטרך לשכפל את המחסנית לכל טיפוס–

נכתוב את המחסנית מחדש כמבנה נתונים גנרי המסוגל להחזיק עצמיםמכל סוג

אלו תכונות של העצמים נצטרך כדי לשמור אותם במחסנית?–

כיצד ניתן לספק את תכונות אלו למחסנית מבלי לפגוע בגנריות?–

Page 20: תרגול מס' 5

20מבוא לתכנות מערכות - 234122

stack.hמחסנית גנרית - #ifndef _STACK_H#define _STACK_H /** generic ADT of Stack of integers */typedef struct Stack_t* Stack;typedef void* Element;typedef Element (*CopyFunction)(Element);typedef void (*FreeFunction)(Element); /** possible return values */typedef enum {

STACK_BAD_ARGUMENT, STACK_SUCCESS,STACK_FAIL, STACK_EMPTY, STACK_FULL

} StackResult;

typedef כדי להקל על המשתמש

במבנה

קוד שגיאה להתמודדות עם שגיאות בפונקציות הנשלחות ע"י

המשתמש

Page 21: תרגול מס' 5

21מבוא לתכנות מערכות - 234122

stack.hמחסנית גנרית - /** creates a Stack with maximal capacity of 'maxSize'. if fails, returns NULL */Stack stackCreate(int maxSize, CopyFunction copyFunction,

FreeFunction freeFunction); /** releases the memory allocated for the stack */void stackDestroy(Stack stack); /** inserts an element to the top of the stack. Error Codes: STACK_BAD_ARGUMENT if stack is NULL STACK_FULL if the stack is full and STACK_FAIL if the supplied copy function fails. */StackResult stackPush(Stack stack, Element element);

Page 22: תרגול מס' 5

22מבוא לתכנות מערכות - 234122

stack.hמחסנית גנרית - /** removes the element at the top of the stack. Error codes: STACK_BAD_ARGUMENT if stack is NULL STACK_EMPTY if the stack is empty */StackResult stackPop(Stack stack); /** returns in 'element' the last element that was pushed. Error codes: STACK_BAD_ARGUMENT if stack or number are NULL STACK_EMPTY if the stack is empty and STACK_FAIL if the supplied copy function fails */StackResult stackTop(Stack stack, Element* element); /** returns the number of elements in the stack. stack must not be NULL */int stackSize(Stack stack); #endif 

Page 23: תרגול מס' 5

23מבוא לתכנות מערכות - 234122

פתרון הבעיה בעזרת מחסנית גנרית#include <stdio.h>#include <assert.h>#include <stdlib.h>#include "stack.h"

#define MAX_INPUT_SIZE 10#define UNDO_LAST_COMMAND -1

/* functions that will be used by the stack */Element copyInt(Element element) {

if (element == NULL) {return NULL;

}int* newInt = malloc(sizeof(int));if (newInt == NULL) {

return NULL;}*newInt = *(int*)element;return newInt;

}

void freeInt(Element element) {free(element);

}

Page 24: תרגול מס' 5

24מבוא לתכנות מערכות - 234122

פתרון הבעיה בעזרת מחסנית גנרית

int main() {Stack stack = stackCreate(MAX_INPUT_SIZE, copyInt, freeInt);if (stack == NULL) {

fprintf(stderr, "failed to create stack\n");return -1;

int input;while (stackSize(stack) < MAX_INPUT_SIZE && scanf("%d", &input) == 1) {

if (input != UNDO_LAST_COMMAND) {StackResult result = stackPush(stack, &input);assert(result == STACK_SUCCESS);continue;

StackResult result = stackPop(stack);if (result == STACK_EMPTY) {

printf("No numbers were entered until now\n");} else {

assert(result == STACK_SUCCESS);printf("undo\n");

}}

Page 25: תרגול מס' 5

25מבוא לתכנות מערכות - 234122

פתרון הבעיה בעזרת מחסנית גנרית

while (stackSize(stack) > 0) {int* number = NULL;StackResult result = stackTop(stack,

(Element*)&number);StackResult result2 = stackPop(stack);assert(result == STACK_SUCCESS && result2 ==

STACK_SUCCESS);printf("%d\n", *number);freeInt(number);

}stackDestroy(stack);return 0;

}

Page 26: תרגול מס' 5

26מבוא לתכנות מערכות - 234122

שימוש בגנריות

שמייצגות פקודותמחרוזותנניח שהפעם אנחנו רוצים לקלוט מהקלט 80גודל מחרוזת מקסימלי הוא –

הפוךבסוף קליטת הפקודות התוכנית תדפיס את הפקודות בסדר

אחת הפקודות יכולה להיות“UNDO” היא מבטלת קליטת פקודה - קודמת

אינה נקלטת ואינה מודפסת בסוף התוכניתUNDOפקודת –

Page 27: תרגול מס' 5

27מבוא לתכנות מערכות - 234122

שימוש במחסנית גנרית#include <stdio.h>#include <assert.h>#include <stdlib.h>#include <string.h>#include "stack.h" #define MAX_INPUT_SIZE 100#define UNDO_COMMAND "UNDO"#define MAX_COMMAND_SIZE 80 /* functions that will be used by the stack */Element copyString(Element element) {

if (element == NULL) {

return NULL;}char* newString = malloc (strlen(element) + 1);if (newString == NULL) {

return NULL;}return strcpy(newString, element);

} void freeString(Element element) {

free (element);}

Page 28: תרגול מס' 5

28מבוא לתכנות מערכות - 234122

שימוש במחסנית גנריתint main() {

Stack stack = stackCreate(MAX_INPUT_SIZE, copyString, freeString);if (stack == NULL) {fprintf(stderr, "failed to create stack\n");

return -1;}

 char input[MAX_COMMAND_SIZE] = "";while (stackSize(stack) < MAX_INPUT_SIZE && scanf("%s", input) == 1) {if (strcmp(input,UNDO_COMMAND) != 0) {StackResult result = stackPush(stack, input);assert(result == STACK_SUCCESS);

continue;}StackResult result = stackPop(stack);if (result == STACK_EMPTY) {

printf("No numbers were entered until now\n");} else {assert(result == STACK_SUCCESS);

printf("undo\n");}}

Page 29: תרגול מס' 5

29מבוא לתכנות מערכות - 234122

שימוש במחסנית גנרית

while (stackSize(stack) > 0) {char* command = NULL;StackResult result = stackTop(stack,

(Element*)&command);StackResult result2 = stackPop(stack);assert(result == STACK_SUCCESS && result2 ==

STACK_SUCCESS);printf("%s\n", command);freeString(command);

}stackDestroy(stack);return 0;

}

Page 30: תרגול מס' 5

30מבוא לתכנות מערכות - 234122

stack.cמימוש המחסנית גנרית - #include <stdlib.h>#include <assert.h>#include "stack.h" /** The Stack is implemented as an array of Elements. * With nextIndex as an index to the next available position and * maximal size stored in maxsize. */struct Stack_t {

Element* array;int nextIndex;int maxSize;CopyFunction copyElement;FreeFunction freeElement;

}; 

Page 31: תרגול מס' 5

31מבוא לתכנות מערכות - 234122

stack.cמימוש המחסנית גנרית - Stack stackCreate(int maxSize, CopyFunction copyFunction, FreeFunction freeFunction) {

if (maxSize <= 0 || !copyFunction || !freeFunction) {

return NULL;}Stack stack = malloc(sizeof(*stack));if (stack == NULL) {

return NULL;}stack->array = malloc(sizeof(Element) * maxSize);if (stack->array == NULL) {

free(stack);

return NULL;}

stack->nextIndex = 0;stack->maxSize = maxSize;stack->copyElement = copyFunction;stack->freeElement = freeFunction;return stack;

}

Page 32: תרגול מס' 5

32מבוא לתכנות מערכות - 234122

stack.cמימוש המחסנית גנרית - StackResult stackPush(Stack stack, Element element) {

if (stack == NULL) {return STACK_BAD_ARGUMENT;

}if (stack->nextIndex >= stack->maxSize) {

return STACK_FULL;}

 Element newElement = stack->copyElement(element);if (newElement == NULL) {

return STACK_FAIL;}assert(stack->nextIndex >= 0 && stack->nextIndex < stack-

>maxSize);stack->array[stack->nextIndex++] = newElement;return STACK_SUCCESS;

Page 33: תרגול מס' 5

33מבוא לתכנות מערכות - 234122

stack.cמימוש המחסנית גנרית - StackResult stackPop(Stack stack) {

if (stack == NULL) {return STACK_BAD_ARGUMENT;

}if (stack->nextIndex < 1) {

return STACK_EMPTY;}

 assert(stack->nextIndex > 0 && stack->nextIndex <= stack-

>maxSize);stack->freeElement(stack->array[stack->nextIndex - 1]);stack->nextIndex--;return STACK_SUCCESS;

}

Page 34: תרגול מס' 5

34מבוא לתכנות מערכות - 234122

stack.cמימוש המחסנית גנרית - StackResult stackTop(Stack stack, Element* element) {

if (stack == NULL || element == NULL) {return STACK_BAD_ARGUMENT;

}if (stack->nextIndex < 1) {

return STACK_EMPTY;}assert(stack->nextIndex > 0 && stack->nextIndex <= stack-

>maxSize);Element newElement = stack->copyElement(stack->array[stack-

>nextIndex - 1]);if (newElement == NULL) {

return STACK_FAIL;}*element = newElement;return STACK_SUCCESS;

}

למה יוצרים העתק של העצם המוחזר?

Page 35: תרגול מס' 5

35מבוא לתכנות מערכות - 234122

stack.cמימוש המחסנית גנרית - int stackSize(Stack stack) {

assert(stack);return stack->nextIndex;

} void stackDestroy(Stack stack) {

if (stack == NULL) {return;

while (stackSize(stack) > 0) {StackResult result = stackPop(stack);assert(result == STACK_SUCCESS);

free(stack->array);free(stack);

}

Page 36: תרגול מס' 5

36מבוא לתכנות מערכות - 234122

ADTגנריים - סיכום

ניתן ליצור מבני נתונים גנריים המסוגלים לשמור כל סוג של עצמים כדי לאפשר למבני נתונים גנריים לעבור עם סוג מסוים של עצמים יש

לספק להם מצביעים לפונקציות לביצוע הפעולות הבסיסיות שימוש במבני נתונים גנריים מאפשר שימוש חוזר במבנה עבור טיפוסים

שונים ומונע שכפול קוד

Page 37: תרגול מס' 5

37מבוא לתכנות מערכות - 234122

בחירת מבני נתונים

בחירת מבני נתוניםמבני הנתונים הנלמדים בקורס

Page 38: תרגול מס' 5

38מבוא לתכנות מערכות - 234122

מבני הנתונים הנלמדים בקורס

הבאים )כולם מבני הנתונים הבסיסיים בקורס זה אנו לומדים את(:ADTנלמדים כ-

.1Listשומרת אוסף איברים עם סדר ביניהם ומאפשרת הכנסת - רשימה :אותו איבר מספר פעמים

.2Setמאפשרת הכנסת איבר פעם אחת בלבד ואינה שומרת - קבוצה :סדר בין איברי הקבוצה

.3Stackמאפשרת הכנסה, גישה והוצאה רק מסופה. שומרת - מחסנית :על סדר ומאפשרת כפילויות

.4Graphשומר קבוצת צמתים וקבוצת קשתות המחברות ביניהם - גרף :מתאים לבעיות הדורשות אבסטרקציה של רשתות כגון רשת כבישים, רשת –

מחשבים וכו'.

Page 39: תרגול מס' 5

39מבוא לתכנות מערכות - 234122

התאמת מבנה נתונים לבעיה מבנה הנתונים המתאים ביותרלכל בעיה חשוב להתאים את

:התאמת מבנה הנתונים נעשית לפי שני שיקולים עיקרייםמונעת שכפול קוד , פשוט יותר, קוד קצר יותראיכות הקוד - בחירה טובה יוצרת –

מקשה על הכנסת באגיםו

מונעת הכנסת איבר פעמיים, חוסכת התעסקות list במקום setלמשל בחירת •בסדר הרשימה ובדיקות לפני הכנסת איבר בשנית

שיקול זה לא יעניין סיבוכיות - בחירת מבנה כך שהפעולות הקריטיות מהירות. –אותנו בקורס זה ויילמד לעומק בקורס מבני נתונים

:בבחירת המבנה כדאי להתחשב בדברים הבאיםהאם יש כפילויות?–

האם צריך לשמור סדר שונה בכל פעם?–

האם ניתן לקחת מבנה ספציפי יותר כך שייחסכו בדיקות מיותרות?–

Page 40: תרגול מס' 5

40מבוא לתכנות מערכות - 234122

בחירת מבני נתונים - סיכום

מבני הנתונים הנלמדים בקורס הםList, Set, Stack-ו Graphיש לבחור מבנה נתונים מתאים לבעיה כדי להקל על העבודה

Page 41: תרגול מס' 5

41מבוא לתכנות מערכות - 234122

ADTשאלה לדוגמה -

Page 42: תרגול מס' 5

42מבוא לתכנות מערכות - 234122

שאלה לדוגמה

מבנה הנתונים ערמה מאפשר הכנסת איברים והוצאה של האיבר"המקסימלי" לפי סדר שהוגדר. כלומר הפעולות הנדרשות מערמה הן:

יצירת ערמה חדשה.1.

שחרור ערמה קיימת.2.

הכנסת איבר לערמה, ניתן להכניס מספר עותקים של אותו איבר.3.

הוצאת האיבר המקסימלי מהערמה. במקרה והערמה ריקה תוחזר שגיאה.4.

של ערמהADTא. כתבו את קובץ המנשק עבור

שנלמדו בקורס כדאי להשתמש למימוש בערמה? מדוע?ADTב. באילו מה-

עבור הערמהstructג. כתבו את הקוד הדרוש למימוש ה-

ד. ממשו את הפונקציה עבור יצירת ערמה חדשה

Page 43: תרגול מס' 5

43מבוא לתכנות מערכות - 234122

סעיף א'#ifndef _HEAP_H

#define _HEAP_H

#include <stdbool.h>

typedef struct heap_t* Heap;

typedef enum {

HEAP_SUCCESS, HEAP_NULL_ARGUMENT, HEAP_OUT_OF_MEMORY, HEAP_EMPTY

} HeapResult;

Heap heapCreate(void* (*copy)(void*),

void(*release)(void*),

bool (*compare)(void*,void*));

HeapResult heapPush(Heap heap, void* element);

HeapResult heapPop(Heap heap, void** element);

void heapDestroy(Heap heap);

#endif

ניתן להגדיר את המצביעים typedefישירות או להוסיף מתאימים

Page 44: תרגול מס' 5

44מבוא לתכנות מערכות - 234122

סעיפים ב' ו-ג'

-נבחר להשתמש בList:עבור מימוש הערמה ייתכנו העתקים של אותו איבר בערמה–

יהיה לנו נוח יותר להוציא את האיבר ששמור בראש הרשימה–

-מימוש המבנה בקובץ הC:

struct heap_t {

List items;

bool (*compare)(void*,void*);

};איפה יישמרו המצביעים

לשאר לפונקציות?

Page 45: תרגול מס' 5

45מבוא לתכנות מערכות - 234122

סעיף ד'Heap heapCreate(void* (*copy)(void*), void (*release)(void*),

bool (*compare)(void*,void*)) {if (!copy || !release || !compare) {

return NULL;  }

Heap heap = malloc(sizeof(*heap));if (!heap) {

return NULL;  }

heap->items = listCreate(copy, release);if (!heap->items) {

heapDestroy(heap);return NULL;

}heap->compare = compare;return heap;

}