1 / 21

Homework / Quiz

Learn to implement self-referential structs for a binary tree in C, including code examples, declarations, and prototypes. Understand pointers and recursive functions for struct nodes.

alashley
Download Presentation

Homework / Quiz

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. Homework / Quiz • Exam 2 • Solutions Posted • Questions? • Continuing K&R Chapter 6 • HW6 is on line – due class 22

  2. Self Referential structs, K&R 6.5 • Look at this binary tree structure (Pg. 139) now is the for men of time all good party their to aid come

  3. Self Referential structs struct tnode { /* the tree node struct */ char *word; /* points to the word at this node */ int count; /* has a count of occurances */ struct tnode *left; /* a word < one at this node */ struct tnode *right; /* a word > one at this node */ }; • OK to have a pointer to a struct of same type in its own definition • NOT OK to have a struct itself in its own definition!

  4. Tree of struct tnodes tnode *root char *word int count tnode *left tnode *right keyword \0 … char *word int count tnode *left tnode *right … … … char *word int count tnode *left tnode *right … …

  5. Self Referential structs • Each node is a struct tnode with a string value and a count of occurrences • Each node also contains a pointer to a left child and a right child • Each child is another struct tnode

  6. Declarations / Prototypes #include <stdio.h> #include <ctype.h> (see functions in App. B2, pp. 248-249, K&R) #include <string.h> (see functions in App. B3, pp. 249-250, K&R) #include “getch.h” #define MAXWORD 100 int getword(char *word, int lim); struct tnode *addtree(struct tnode *, char *); void treeprint(struct tnode *);

  7. Main program int main( ) { struct tnode *root; /* ptr to root for binary tree */ char word[MAXWORD]; /* word to get from stdin */ root = NULL; /* initially, no tnodes in tree */ /* OK that root pointer points to NULL initially */ while (getword(word, MAXWORD) != EOF) /* getword from stdin */ if (isalpha(word[0])) /* from ctype.h library */ root = addtree(root, word); /* expect not NULL anymore */ treeprint(root); /* print it out in order */ return 0; }

  8. treeprint ( ) • To print out tree contents in order: void treeprint (struct tnode *p) { if (p != NULL) { treeprint (p->left); printf (%4d %s\n”, p->count, p->word); treeprint (p->right); } }

  9. getword ( ) int getword(char *word, int lim) { int c; char *w = word; while isspace(c = getch()) /* skip spaces; c first non-space */ ; if (c != EOF) *w++=c; /* c might be EOF here (empty word) */ if(!isalpha(c)) { /* c (identifier) starts with alpha */ *w = '\0'; return c; /* if not, word empty */ } for( ; --lim > 0; w++) if (!isalnum(*w = getch())) { /* identfier alpha or digits */ ungetch(*w); break; /* e.g., + might be needed later */ } *w = '\0'; return word[0]; }

  10. addtree ( ) struct tnode *talloc(void); /* allocate. return ptr to tnode */ char *strdup(char *); /* allocate space, copy word there */ struct tnode *addtree(struct tnode *p, char *w) { int cond; /*for empty tree, root is NULL */ if (p == NULL) { /* nothing at this node yet */ p = talloc(); /* allocate a new node */ p->word = strdup(w); /* allocate space, copy word there */ p->count = 1; /* count is 1 */ p->left = p->right = NULL; /* this works; see precedence */ } else if ((cond = strcmp(w, p->word)) == 0) /* string.h */ p->count++; /* repeated word, increment count */ else if (cond < 0) /* note cond remembers strcmp above */ p->left = addtree(p->left, w); /* less: go left subtree */ else /* more, go to right subtree */ p->right = addtree(p->right, w); return p; }

  11. addtree( ) • Note, that addtree is recursive. If it adds a node, it might need to add root or any left or right child anywhere down the tree • We pass struct tnode *p as first argument, and also pass back the same type - always a pointer to the node at the current recursive nesting level • Any time a new node is created: root, p->left or p->right in node above will be set for the FIRST time based on return value from addtree

  12. addtree ( ) • When main calls addtree, the return sets root value each time even if the root already pointed to tnode • Allows for possible addition of a pointer to a node • Why do we need to return a struct tnode *p when we have struct tnode *p as an argument? • Can't we just set it via argument, return void from addtree, and write (in main)? addtree(root, word); instead of root = addtree(root, word);

  13. addtree ( ) • No, root is already a pointer, struct tnode *, but it is the pointer root itself that must be modified • To modify root, we would need to declare addtree with a pointer to a struct tnode * as the first arg: void addtree(struct tnode **pptr, char *w) { struct tnode *p = *pptr; • Call it from main recursively by invocation: addtree(&root, word); • Then, addtree could set the value for root directly *pptr = p; • Same is true when adding a left or right child

  14. talloc ( ) • How to write talloc to allocate a tnode and return a pointer. struct tnode *talloc(void) { return (struct tnode *) malloc (sizeof(struct tnode)); }

  15. strdup ( ) • strdup ( ) creates space for a character string, copies a word into it (up to null terminator) and returns the char pointer char *strdup(char *s) { p = (char *) malloc (strlen(s)+1); /* +1 for '\0' */ if (p != NULL) /* if malloc didn’t fail */ strcpy(p, s); /* library function in string.h */ return p; }

  16. Intro to HW6 • Memory model for malloc( ) and free( ) Before any calls to alloc( ): allocbuf: After two calls to alloc( ) and before call to freef( ): allocbuf: After call to freef( ) on first block alloc gave out: allocbuf: Free Free In Use In Use Free In Use Free

  17. Intro to HW6 • Fragmentation with malloc( ) and free( ) Before call to alloc( ) for a large memory block: allocbuf: alloc can NOT provide a large contiguous block of memory - even though there is theoretically sufficient free memory! Memory is fragmented!! In use Free In use Free In use Free In use

  18. Intro to HW6 • Not possible to “defragment” allocbuf memory after the fact as you would do for a disk • On a disk, the pointers to memory are in the disk file allocation table and can be changed • With malloc, programs are holding pointers to memory they own - so can’t be changed!! • Can only defragment as blocks are freed by using program

  19. Intro to HW6 • Initial structures in allocbuf[] • Structures after two calls to alloc() blockl blockr Free Memory blockl blockr blockl blockr blockl blockr Free Memory Inuse 2 Inuse 1

  20. Intro to HW6 • Structures after free call on first block only • Structures after free call on second block only blockl blockr blockl blockr blockl blockr Free Memory Inuse 2 Free Memory blockl blockr blockl blockr Free Memory Inuse 1 Note effect of coalesce!

  21. Intro to HW6 • Four possible states for block being freed • Between two blocks that are still in-use • Above a free block and below an in-use block • Above an in-use block and below a free block • Above a free block and below a free block • When freeing a block, coalesce with adjacent free blocks to avoid unnecessary fragmentation of allocbuf (allows alloc to serve later requests for large amounts of memory)

More Related