* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Download 57:017, Computers in Engineering Dynamic Data Structures
Survey
Document related concepts
Transcript
57:017, Computers in Engineering Dynamic Data Structures Introduction z Dynamic data structures z Data structures that grow and shrink during execution z Linked lists z z Allow insertions and removals only at top of stack Queues z Allow insertions and removals anywhere St k Stacks Allow insertions at the back and removals from the front Binary trees High-speed searching and sorting of data and efficient elimination of duplicate data items © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. Self-Referential Structures z Self-referential structures z z Structure that contains a field that is a pointer to a structure of the same type Can be linked together to form useful data structures such as lists, queues, stacks and trees struct node { t data; int struct node *nextPtr; } z nextPtr z Points to an object of type node z Referred to as a link z Ties one node to another node z Terminated with a NULL pointer Linked Lists z Linked list z z z z z z Linear collection of self-referential structures, called nodes Connected by pointer links Accessed via a pointer to the first node of the list Subsequent q nodes are accessed via the link-pointer p member of the current node Link pointer in the last node is set to NULL to mark the list’s end Dynamic Memory Allocation Two self-referential structures linked together: 15 sPtr 10 What is going on in the computer memory? struct node { int data; struct node *nextPtr; } sPtr ÅÆ Address Value 4000 6000 ….. ….. sPtr->data ÅÆ 6000 15 sPtr->nextPtr ÅÆ 6004 7000 ….. sPtr->nextPtr->data ÅÆ sPtr->nextPtr->nextPtr ÅÆ ….. 7000 10 7004 NULL Linked Lists struct listNode{ char data; struct listNode *nextPtr; }; typedef struct listNode ListNode; typedef ListNode * ListNodePtr; struct listNode * startPtr; ListNode * startPtr; ListNodePtr startPtr;; All 3 definitions are equivalent Pick y your favorite Use a linked list instead of an array when z z z You have an unpredictable number of data elements Your list needs to be sorted quickly You need to do insertions and deletions within the list 1 Linked Lists /* Fig. 12.3: fig12_03.c 1 Address startPtr ÅÆ Value 3000 17 3004 6500 ….. 6000 3 #include <stdio.h> 4 #include <stdlib.h> fig12_03.c (Part 1 of 8) 5 What is going on in the computer memory? (*startPtr).data, startPtr->data ÅÆ (*startPtr).nextPtr, startPtr->nextPtr ÅÆ Operating and maintaining a list */ 2 struct listNode{ char data; struct listNode *nextPtr; }; struct listNode * startPtr; ….. 3000 ….. ….. startptr->nextPtr->data ÅÆ 6500 29 startptr->nextPtr->nextPtr ÅÆ 6012 5500 6 /* self-referential structure */ 7 struct listNode { 8 char data; 9 struct listNode *nextPtr; /* listNode pointer */ /* define data as char */ 10 }; /* end structure listNode */ 11 12 typedef struct listNode ListNode; 13 typedef ListNode *ListNodePtr; 14 15 /* prototypes */ 16 void insert( ListNodePtr *sPtr, char value ); 17 char delete( ListNodePtr *sPtr, char value ); 18 int isEmpty( ListNodePtr sPtr ); 19 void printList( ListNodePtr currentPtr ); 20 void instructions( void ); 21 22 int main() 23 { startPtr is an address of a struct listNode *startPtr is a struct listNode ….. ….. 8020 93 8024 NULL © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. 24 ListNodePtr startPtr = NULL; /* initialize startPtr */ 51 /* if character is found */ 25 int choice; /* user's choice */ 52 if ( delete( &startPtr, item ) ) { 26 char item; /* char entered by user */ 53 27 28 instructions(); /* display the menu */ 29 printf( "? " ); 30 scanf( "%d", &choice ); fig12_03.c (Part 2 of 8) 31 /* loop while user does not choose 3 */ 33 while ( choice != 3 ) { } /* end if */ 56 else { fig12_03.c (Part 3 of 8) printf( "%c not found.\n\n", item ); 57 } /* end else */ 59 34 switch ( choice ) { 60 } /* end if */ 61 else { 62 36 37 printList( startPtr ); 55 58 32 35 printf( "%c deleted.\n", item ); 54 63 case 1: printf( "List is empty.\n\n" ); } /* end else */ 64 38 printf( "Enter a character: " ); 39 scanf( "\n%c", &item ); 40 insert( &startPtr, item ); 41 printList( startPtr ); 67 42 break; 68 65 b break; k 66 default: printf( "Invalid choice.\n\n" ); 43 69 instructions(); 44 70 break; case 2: 71 45 46 /* if list is not empty */ 72 47 if ( !isEmpty( startPtr ) ) { 73 48 printf( "Enter character to be deleted: " ); 49 scanf( "\n%c", &item ); } /* end switch */ 50 © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. 74 75 76 © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. printf( "? " ); 100 scanf( "%d", &choice ); 101 } /* end while */ 102 77 78 printf( "End of run.\n" ); 79 80 return 0; /* indicates successful termination */ fig12_03.c (Part 4 of 8) newPtr = malloc( sizeof( ListNode ) ); if ( newPtr != NULL ) { 103 newPtr->data = value; 104 newPtr->nextPtr = NULL; /* is space available */ fig12_03.c (Part 5 of 8) 105 106 previousPtr = NULL; currentPtr = *sPtr; 81 107 82 } /* end main */ 108 83 109 /* loop to find the correct location in the list */ 84 /* display program instructions to user */ 110 while ( currentPtr != NULL && value > currentPtr->data ) { 85 void instructions( void ) 111 86 { 112 87 printf( "Enter your choice:\n" 113 previousPtr = currentPtr; /* walk to ... currentPtr = currentPtr->nextPtr; /* ... next node */ */ } /* end while */ 88 " 1 to insert an element into the list.\n" 114 89 " 2 to delete an element from the list.\n" 115 /* insert newPtr at beginning of list */ 90 " 3 to end.\n" ); 116 if ( previousPtr == NULL ) { newPtr->nextPtr = *sPtr; 91 } /* end function instructions */ 117 92 118 93 /* Insert a new value into the list in sorted order */ 119 } /* end if */ 94 void insert( ListNodePtr *sPtr, char value ) 120 else { /* insert newPtr between previousPtr and currentPtr */ 95 { 121 96 ListNodePtr newPtr; 97 ListNodePtr previousPtr; /* pointer to previous node in list */ /* pointer to new node */ 123 98 ListNodePtr currentPtr; 124 /* pointer to current node in list */ 122 *sPtr = newPtr; previousPtr->nextPtr = newPtr; newPtr->nextPtr = currentPtr; } /* end else */ 99 © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. 2 125 } /* end if */ 150 /* loop to find the correct location in the list */ 126 else { 151 while ( currentPtr != NULL && currentPtr->data != value ) { 127 128 printf( "%c not inserted. No memory available.\n", value ); 152 } /* end else */ 153 fig12_03.c (Part 6 of 8) 129 130 } /* end function insert */ previousPtr = currentPtr; /* walk to ... currentPtr = currentPtr->nextPtr; /* ... next node */ 155 156 /* delete node at currentPtr */ 132 /* Delete a list element */ 157 if ( currentPtr != NULL ) { 133 char delete( ListNodePtr *sPtr, char value ) 158 tempPtr = currentPtr; 134 { 159 131 ListNodePtr previousPtr; /* pointer to previous node in list */ 160 free( tempPtr ); 136 ListNodePtr currentPtr; /* pointer to current node in list */ 161 return value; 137 ListNodePtr tempPtr; /* temporary node pointer */ 162 } /* end if */ 163 139 /* delete first node */ 164 140 if ( value == ( *sPtr )->data ) { 165 141 tempPtr = *sPtr; } /* end else */ return '\0'; 166 *sPtr = ( *sPtr )->nextPtr; /* de-thread the node */ 167 143 free( tempPtr ); /* free the de-threaded node */ 168 } /* end function delete */ 144 return value; 142 fig12_03.c (Part 7 of 8) previousPtr->nextPtr = currentPtr->nextPtr; 135 138 */ } /* end while */ 154 169 145 } /* end if */ 170 /* Return 1 if the list is empty, 0 otherwise */ 146 else { 171 int isEmpty( ListNodePtr sPtr ) 147 previousPtr = *sPtr; 172 { 148 currentPtr = ( *sPtr )->nextPtr; 173 149 return sPtr == NULL; 174 175 } /* end function isEmpty */ 176 © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. 177 /* Print the list */ 178 void printList( ListNodePtr currentPtr ) 179 { 180 181 /* if list is empty */ 182 if ( currentPtr == NULL ) { 183 } /* end if */ 185 else { ? 1 Enter a character: C The list is: A --> > B --> > C --> > NULL printf( "The list is:\n" ); 187 188 /* while not the end of the list */ / / 189 while ( currentPtr != NULL ) { 190 printf( "%c --> ", currentPtr->data ); 191 currentPtr = currentPtr->nextPtr; 192 ? 2 Enter character to be deleted: D D not found. } /* end while */ ? 2 Enter character to be deleted: B B deleted. The list is: A --> C --> NULL 193 194 195 Program Output (Part 1 of 3) ? 1 Enter a character: A The list is: A --> B --> NULL printf( "List is empty.\n\n" ); 184 186 fig12_03.c (Part 8 of 8) Enter your choice: 1 to insert an element into the list. 2 to delete an element from the list. 3 to end. ? 1 Enter a character: B The list is: B --> NULL printf( "NULL\n\n" ); } /* end else */ 196 197 } /* end function printList */ © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. ? 2 Enter character to be deleted: C C deleted. The list is: A --> NULL © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. Program Output (Part 2 of 3) Program Output (Part 3 of 3) ? 2 Enter character to be deleted: A A deleted. List is empty. ? 4 Invalid choice. Enter your choice: 1 to insert an element into the list. 2 to delete an element from the list. list 3 to end. ? 3 End of run. ? 4 Invalid choice. Enter your choice: 1 to insert an element into the list. 2 to delete an element from the list. 3 to end. ? 3 End of run. ? 2 Enter character to be deleted: C C deleted. The list is: A --> NULL ? 2 Enter character to be deleted: A A deleted. List is empty. © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. 3 Important Note about the insert and delete functions z Note that the actual type of the first parameter passed to these functions (the list anchor pointer) is: listNode **sPtr (i.e. sPrtr is a pointer to pointer to listNode) sPtr z *sPtr Since the insert and delete functions must change the value of the list anchor pointer in some cases—i.e deleting the first element of the list or inserting at the beginning of the list, the list anchor pointer must be passed by reference—i.e. as a pointer to the list anchor pointer Linked List—insertion of a new element Important Note (con’t) function call in main program, insert(&startPtr, ‘w’); call-by-reference, pass memory address of startPtr so value of startPtr can be changed in function void insert(listNode **sPtr, char value){ function definition ......}; struct listNode{ char data; struct listNode *nextPtr; }; struct listNode *startPtr; startPtr; z sPtr *sPtr startPtr Read from right to left: sPtr is an address of an address of a listNode *sPtr is an address of a listNode **sPtr is a listNode Address Value sPtr ÅÆ 5000 6000 ….. ….. startPtr, *sPtr ÅÆ 6000 6016 ….. ….. (**sPtr).data, (*sPtr)->data ÅÆ 6016 6017-6019 ‘z’ unused (**sPtr).nextPtr, (*sPtr)->nextPtr ÅÆ 6020 NULL Pseudocode for Insert() function 1 Attempt to malloc a new node and set newPtr to point at this node. 2. If malloc is successful (i.e. newPtr != NULL) 2.1 Assign value to data field of new node and initialize its nextPtr field to NULL 2.2 Search for proper insertion point of new node in list 2.3 Reassign pointers to link the new cell into the list at proper insertion point. Else 2.4 print error message 3. Return Refinement of step 2.2 2.2.1 initialize previousPtr to NULL and currentPtr to point at first list element While the list has not been exhausted and the data field of node pointed to by currentPtr is less than the new data 2.2.2.1 Advance PreviousPtr and CurrentPtr by one node. 2.2.2 Note: There are two possible conditions for exiting the loop: a) A node whose data field is greater than the new value has been encountered (currentPtr points at this node) or b) The entire list has been traversed without finding a node whose data portion is greater than the new value. (In this case the new node goes at the end of the list, or becomes the only element in the list if the list was previously empty. void insert( ListNodePtr *sPtr, char value ) { ListNodePtr newPtr; /* pointer to new node */ ListNodePtr previousPtr; /* pointer to previous node in list */ ListNodePtr currentPtr; /* pointer to current node in list */ newPtr = malloc( sizeof( ListNode ) ); /* create node */ if ( newPtr != NULL ) { /* is space available */ newPtr->data = value; /* place value in node */ newPtr->nextPtr = NULL; /* node does not link to another node */ previousPtr = NULL; currentPtr = *sPtr; /* loop to find the correct location in the list */ while ( currentPtr != NULL && value > currentPtr->data ) { previousPtr = currentPtr; /* walk to ... */ currentPtr = currentPtr->nextPtr; /* ... next node */ } /* end while */ / insert new node at beginning of list */ /* / if ( previousPtr == NULL ) { newPtr->nextPtr = *sPtr; *sPtr = newPtr; } /* end if */ else { /* insert new node between previousPtr and currentPtr */ previousPtr->nextPtr = newPtr; newPtr->nextPtr = currentPtr; } /* end else */ } /* end if */ else { printf( "%c not inserted. No memory available.\n", value ); } /* end else */ } /* end function insert */ 4 Deletion from a linked list Pseudocode for delete() function 1. If the node to be deleted is the first node in the list 1.1 Reassign the list’s anchor pointer (sPtr) to point at second list node ( or set it to NULL if there is not a second list node) 1.2 Free the first list node 1.3 Return value Else 1.4 Search the list until either the node with matching data value is found or end off list li t iis encountered t d 1.5 If node to be deleted is found 1.5.1 Reassign the nextPtr field of preceding node to point to following node in list (or to null if the node to be deleted is the last element in the list) 1.5.2 Free the deleted node 1.5.3 Return value else 1.5.4 No matching node exists in the list—no deletion is preformed 1.5.5 Return null charactter /* Delete a list element */ char delete( ListNodePtr *sPtr, char value ) { ListNodePtr previousPtr; /* pointer to previous node in list */ ListNodePtr currentPtr; /* pointer to current node in list */ ListNodePtr tempPtr; /* temporary node pointer */ /* delete first node */ if ( value == ( *sPtr )->data ) { tempPtr = *sPtr; /* hold onto node being removed */ *sPtr = ( *sPtr )->nextPtr; /* de-thread the node */ free( tempPtr ); /* free the de-threaded node */ return value; } /* end if */ else { previousPtr = *sPtr; currentPtr = ( *sPtr sPtr )->nextPtr; ) >nextPtr; /* loop to find the correct location in the list */ while ( currentPtr != NULL && currentPtr->data != value ) { previousPtr = currentPtr; /* walk to ... */ currentPtr = currentPtr->nextPtr; /* ... next node */ } /* end while */ /* delete node at currentPtr */ if ( currentPtr != NULL ) { tempPtr = currentPtr; previousPtr->nextPtr = currentPtr->nextPtr; free( tempPtr ); return value; } /* end if */ } /* end else */ return '\0'; } /* end function delete */ The printList() function /* Print the list */ void printList( ListNodePtr currentPtr ) { /* if list is empty */ if ( currentPtr == NULL ) { printf( "List is empty.\n\n" ); } /* end if */ else { printf( "The list is:\n" ); /* while not the end of the list */ while ( currentPtr != NULL ) { printf( "%c --> ", currentPtr->data ); currentPtr = currentPtr->nextPtr; } /* end while */ The isEmpty() function /* Return 1 if the list is empty, 0 otherwise */ int isEmpty( ListNodePtr sPtr ) { return sPtr == NULL; } /* end function isEmpty */ Note: (sPtr == NULL) is a logical expression that evaluates to 1(TRUE) if sPtr is null and to 0 (false) otherwise Stacks z Stack z z z z z z push z printf( "NULL\n\n" ); } /* end else */ } /* end function printList */ z New nodes can be added and removed only at the top Similar to a pile of dishes Last-in, first-out (LIFO) Bottom of stack indicated by a link member to NULL Constrained version of a linked list Adds a new node to the top of the stack pop z z z Removes a node from the top Stores the popped value Returns true if pop was successful 5 Stacks Stacks /* Fig. 12.8: fig12_08.c 1 dynamic stack program */ 2 Stacks 3 #include <stdio.h> 4 #include <stdlib.h> fig12_08.c (Part 1 of 6) 5 6 /* self-referential structure */ 7 struct stackNode { 8 int data; 9 struct stackNode *nextPtr; /* stackNode pointer */ /* define data as an int */ 10 }; /* end structure stackNode */ 11 12 typedef struct stackNode StackNode; 13 typedef StackNode *StackNodePtr; 14 15 /* prototypes */ 16 void push( StackNodePtr *topPtr, int info ); 17 int pop( StackNodePtr *topPtr ); 18 int isEmpty( StackNodePtr topPtr ); 19 void printStack( StackNodePtr currentPtr ); 20 void instructions( void ); 21 22 /* function main begins program execution */ 23 int main() 24 { 25 StackNodePtr stackPtr = NULL; /* points to stack top */ 26 int choice; /* user's menu choice */ 27 int value; /* int input by user */ 28 © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. 29 instructions(); /* display the menu */ 54 printStack( stackPtr ); 30 printf( "? " ); 55 break; 31 scanf( "%d", &choice ); 56 57 32 33 /* while user does not enter 3 */ 34 while ( choice != 3 ) { 35 36 switch ( choice ) { fig12_08.c (Part 2 of 6) 58 instructions(); break; /* push value onto stack */ 63 39 case 1: 64 40 printf( "Enter an integer: " ); 65 41 scanf( "%d", &value ); 66 push( &stackPtr, value ); 67 43 printStack( stackPtr ); 68 44 break; 69 70 45 } /* end switch */ printf( "? " ); scanf( "%d", &choice ); } /* end while */ printf( "End of run.\n" ); return 0; /* indicates successful termination */ 46 /* pop value off stack */ 71 47 case 2: 72 } /* end main */ 73 48 49 /* if stack is not empty */ 74 /* display program instructions to user */ 50 if ( !isEmpty( stackPtr ) ) { 75 void instructions( void ) 51 52 fig12_08.c (Part 3 of 6) 61 38 42 printf( "Invalid choice.\n\n" ); 60 62 37 default: 59 printf( "The popped value is %d.\n", pop( &stackPtr ) ); } /* end if */ 53 76 { 77 printf( "Enter choice:\n" 78 "1 to push a value on the stack\n" 79 "2 to pop a value off the stack\n" 80 "3 to end program\n" ); 81 } /* end function instructions */ © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. 82 © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. 6 83 /* Insert a node at the stack top */ 108 tempPtr = *topPtr; 84 void push( StackNodePtr *topPtr, int info ) 109 popValue = ( *topPtr )->data; 85 { 110 *topPtr = ( *topPtr )->nextPtr; fig12_08.c (Part 4 of 6) StackNodePtr newPtr; /* pointer to new node */ 86 87 newPtr = malloc( sizeof( StackNode ) ); 88 111 free( tempPtr ); 112 113 return popValue; fig12_08.c (Part 5 of 6) 114 89 90 /* insert the node at stack top */ 115 } /* end function pop */ 91 if ( newPtr != NULL ) { 116 92 newPtr->data = info; 117 /* Print the stack */ 93 newPtr->nextPtr = *topPtr; 118 void printStack( StackNodePtr currentPtr ) 94 *topPtr = newPtr; 119 { 95 } /* end if */ 120 96 else { /* no space p available */ 121 /* if stack is empty p y */ 122 if ( currentPtr == NULL ) { printf( "%d not inserted. No memory available.\n", info ); 97 } /* end else */ 98 123 printf( "The stack is empty.\n\n" ); 99 124 } /* end if */ 100 } /* end function push */ 125 else { 101 126 102 /* Remove a node from the stack top */ 127 103 int pop( StackNodePtr *topPtr ) 128 /* while not the end of the stack */ 104 { 129 while ( currentPtr != NULL ) { 105 StackNodePtr tempPtr; /* temporary node pointer */ 130 106 int popValue; 131 /* node value */ 132 107 printf( "The stack is:\n" ); printf( "%d --> ", currentPtr->data ); currentPtr = currentPtr->nextPtr; } /* end while */ 133 © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. printf( "NULL\n\n" ); 134 } /* end else */ 135 136 137 } /* end function printList */ 138 fig12_08.c (Part 6 of 6) 139 /* Return 1 if the stack is empty, 0 otherwise */ ? 2 The popped value is 4. The stack is: 6 --> 5 --> NULL 140 int isEmpty( StackNodePtr topPtr ) 141 { 142 ? 1 Enter an integer: 4 The stack is: 4 --> 6 --> 5 --> NULL return topPtr == NULL; 143 Program Output (Part 2 of 2) ? 2 The popped value is 6. The stack is: 5 --> NULL 144 } /* end function isEmpty */ ? 2 The p popped pp value is 5. The stack is empty. Enter choice: 1 to push a value on the stack 2 to pop a value off the stack 3 to end program ? 1 Enter an integer: 5 The stack is: 5 --> NULL ? 1 Enter an integer: 6 The stack is: 6 --> 5 --> NULL © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. Queues z ? 4 Invalid choice. Program Output (Part 1 of 2) Enter choice: 1 to push a value on the stack 2 to pop a value off the stack 3 to end program ? 3 End of run. © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. Queues Queue z z z z z ? 2 The stack is empty. Similar to a supermarket checkout line First-in, first-out (FIFO) Nodes are removed only from the head Nodes are inserted only at the tail Insert and remove operations z Enqueue (insert) and dequeue (remove) 7 Queues Queues /* Fig. 12.13: fig12_13.c 1 3 4 #include <stdio.h> 5 #include <stdlib.h> fig12_13.c (Part 1 of 7) 6 7 /* self-referential structure */ 8 struct queueNode { 28 QueueNodePtr tailPtr = NULL; /* initialize tailPtr */ 29 int choice; /* user's menu choice */ 30 char item; /* char input by user */ 31 32 instructions(); /* display the menu */ 33 printf( "? " ); char data; /* define data as a char */ 10 struct queueNode *nextPtr; /* queueNode pointer */ 35 11 }; /* end structure queueNode */ 12 36 /* while user does not enter 3 */ 37 while ( choice != 3 ) { 38 13 typedef struct queueNode QueueNode; 40 15 16 /* function prototypes */ 17 void printQueue( QueueNodePtr currentPtr ); 18 int isEmpty( QueueNodePtr headPtr ); 19 char dequeue( QueueNodePtr *headPtr, QueueNodePtr *tailPtr ); 41 /* enqueue value */ 42 case 1: 43 printf( "Enter a character: " ); 44 scanf( "\n%c", &item ); enqueue( &headPtr, &tailPtr, item ); 45 20 void enqueue( QueueNodePtr *headPtr, QueueNodePtr *tailPtr, char value ); 21 switch( choice ) { 39 14 typedef QueueNode *QueueNodePtr; 22 void instructions( void ); 46 printQueue( headPtr ); 47 break; 48 23 24 /* function main begins program execution */ 25 int main() 49 /* dequeue value */ 50 case 2: 51 26 { © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. 52 /* if queue is not empty */ 53 if ( !isEmpty( headPtr ) ) { 54 item = dequeue( &headPtr, &tailPtr ); 55 printf( "%c has been dequeued.\n", item ); } /* end if */ 57 © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. 78 /* display program instructions to user */ 79 void instructions( void ) 80 { fig12_13.c (Part 3 of 7) 81 printf ( "Enter your choice:\n" 82 " 1 to add an item to the queue\n" 83 " 2 to remove an item from the queue\n" " 3 to end\n" ); 58 printQueue( headPtr ); 84 59 break; 85 } /* end function instructions */ 60 61 default: 87 /* insert a node a queue tail */ printf( "Invalid choice.\n\n" ); 88 void enqueue( QueueNodePtr *headPtr, QueueNodePtr *tailPtr, 63 instructions(); 89 64 break; 90 { 65 91 } /* end switch */ 67 93 printf( "? " ); 94 69 scanf( "%d", &choice ); 95 } /* end while */ 71 72 73 74 96 97 printf( "End of run.\n" ); return 0; /* indicates successful termination */ char value ) QueueNodePtr newPtr; /* pointer to new node */ 92 68 70 fig12_13.c (Part 4 of 7) 86 62 66 fig12_13.c (Part 2 of 7) scanf( "%d", &choice ); 34 9 56 QueueNodePtr headPtr = NULL; /* initialize headPtr */ 27 Operating and maintaining a queue */ 2 newPtr = malloc( sizeof( QueueNode ) ); if ( newPtr != NULL ) { /* is space available */ newPtr->data = value; newPtr->nextPtr = NULL; 98 99 /* if empty, insert node at head */ 100 if ( isEmpty( *headPtr ) ) { 75 101 76 } /* end main */ 102 *headPtr = newPtr; } /* end if */ 77 © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. 8 else { 103 130 ( *tailPtr )->nextPtr = newPtr; 104 fig12_13.c (Part 5 of 7) 106 *tailPtr = newPtr; 107 free( tempPtr ); 131 } /* end else */ 105 132 return value; 133 134 } /* end function dequeue */ 108 } /* end if */ 135 109 else { 136 /* Return 1 if the list is empty, 0 otherwise */ printf( "%c not inserted. No memory available.\n", value ); 110 111 137 int isEmpty( QueueNodePtr headPtr ) } /* end else */ 138 { 112 139 113 } /* end function enqueue */ 140 114 141 } /* end function isEmpty */ 115 /* remove node from queue head */ 142 116 char h d dequeue( ( QueueNodePtr Q N d Pt *headPtr, *h dPt QueueNodePtr Q N d Pt *tailPtr *t ilPt ) 143 /* Print P i t the th queue */ 117 { 144 void printQueue( QueueNodePtr currentPtr ) 118 char value; 119 QueueNodePtr tempPtr; /* temporary node pointer */ /* node value */ return headPtr == NULL; 145 { 146 147 /* if queue is empty */ 121 value = ( *headPtr )->data; 148 if ( currentPtr == NULL ) { 122 tempPtr = *headPtr; 149 123 *headPtr = ( *headPtr )->nextPtr; 150 } /* end if */ 151 else { 120 124 125 /* if queue is empty */ 152 126 if ( *headPtr == NULL ) { 153 printf( "The queue is:\n" ); } /* end if */ 129 © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. 154 /* while not end of queue */ 155 while ( currentPtr != NULL ) { © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. printf( "%c --> ", currentPtr->data ); 156 currentPtr = currentPtr->nextPtr; 157 fig12_13.c (Part 7 of 7) } /* end while */ 158 159 printf( "NULL\n\n" ); 160 161 printf( "Queue is empty.\n\n" ); *tailPtr = NULL; 127 128 fig12_13.c (Part 6 of 7) 163 } /* end function printQueue */ ? 2 C has been dequeued. Queue is empty. Enter your choice: 1 to add an item to the queue 2 to remove an item from the queue 3 to end ? 1 Enter a character: A The queue is: A --> NULL ? 2 Q Queue i is empty. t ? 4 Invalid choice. Enter your choice: 1 to add an item to the queue 2 to remove an item from the queue 3 to end ? 3 End of run. ? 1 Enter a character: B The queue is: A --> B --> NULL © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. Program Output (Part 1 of 2) Trees z © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. Trees Tree nodes contain two or more links z z Program Output (Part 2 of 2) ? 2 B has been dequeued. The queue is: C --> NULL } /* end else */ 162 ? 1 Enter a character: C The queue is: A --> B --> C --> NULL ? 2 A has been dequeued. The queue is: B --> C --> NULL All other data structures we have discussed only contain one Binary trees z All nodes contain two links z The root node is the first node in a tree. Each link in the root node refers to a child A node with no children is called a leaf node z z z None, one, or both of which may be NULL 9 Trees z Binary Search Trees Binary search tree z z z z Values in left subtree less than parent Values in right subtree greater than parent Facilitates duplicate elimination 2 Fast searches - for a balanced tree, maximum of log n comparisons Creating A Binary Search Tree z 27 13 6 17 48 42 33 27 z 13 6 A Quick Aside: Recursion and Recursive Functions 48 17 int nFact(int N) { if (N ==0) { return 1; } else { return N*nFact(N-1); } } 42 33 Recursion z Recursive function z z Calls itself directly or indirectly through another function to solve a problem. Tree Traversal—A Recursive Algorithm z z Attributes of a “recursive” problem z z z z z Has a “base base case case”, or simplest part of problem to solve. solve If the function is called with base case, then it simply returns a result. Otherwise, function divides problem into the base case and the part it does not know how to solve. The unsolved part must resemble the original problem and be a smaller part of the original problem. The unsolved part is solved by calling the function with this smaller problem. In Mathematics, it is common to define functions recursively: e.g. Consider the definition of N! (N-factorial): 0! = 1 N! = N(N-1)! for N>0 Can also define C functions recursively: z Consider the problem of printing the values of a binary search tree in ascending order. The algorithm to do this is extremely difficult to express in non-recursive terms. However it’s However, it s very simple to express recursively recursively, as follows: If the tree is null, print nothing Otherwise: Print the left subtree of the root node in ascending order Print the value of the root node Print the right subtree of the root node in ascending order 10 Tree Traversal z z z z Tree Traversal (continued) Since the tree is defined recursively, it is most convenient and easiest to code using recursive functions to operate on it The base case can be either the NULL tree or a tree with just one node (leaf) The recursive step operates on the two subtrees of the current node Since subtrees are smaller than the original tree, algorithms are guaranteed to converge z z Unlike a list, there are several ways we can traverse and print out the elements of a tree Inorder traversal z z z z Print root, left subtree, right subtree Postorder traversal z z Print left subtree, root, right subtree Preorder traversal Print left subtree, right subtree, root All are defined recursively Trees Trees z Tree traversals: z z Inorder traversal – prints the node values in ascending order 1. Traverse the left subtree with an inorder traversal 2. Process the value in the node (i.e., print the node value) 3. Traverse the right subtree with an inorder traversal Preorder traversal 1. Process the value in the node 2. Traverse the left subtree with a preorder traversal 3. Traverse the right subtree with a preorder traversal InOrder Traversal z Tree traversals—continued z Postorder traversal 1. Traverse the left subtree with a postorder traversal 2. Traverse the right subtree with a postorder traversal 3. Process the value in the node PreOrder Traversal typedef struct NODE { int value; struct NODE *left_p; struct NODE *right_p; } node_t; typedef struct NODE { int value; struct NODE *left_p; struct NODE *right_p; } node_t; void InOrder(node_t *tree_p) { if (tree_p != NULL) { InOrder(tree_p->left_p); printf("%d ",tree_p->value); InOrder(tree_p->right_p); } } void PreOrder(node_t *tree_p) { if (tree_p != NULL) { printf("%d ",tree_p->value); PreOrder(tree_p->left_p); PreOrder(tree_p->right_p); } } Note: The tree in this example is not a Binary Search Tree 11 PostOrder Traversal PostOrder Traversal typedef struct NODE { int value; struct NODE *left_p; struct NODE *right_p; } node_t; typedef struct NODE { int value; struct NODE *left_p; struct NODE *right_p; } node_t; void PostOrder(node_t *tree_p) { if (tree_p != NULL) { PostOrder(tree_p->left_p); PostOrder(tree_p->right_p); printf("%d ",tree_p->value); } } void PostOrder(node_t *tree_p) { if (tree_p != NULL) { PostOrder(tree_p->left_p); PostOrder(tree_p->right_p); printf("%d ",tree_p->value); } } Displaying a Tree Printout of Tree Structure Can use modified inorder traversal to print the tree in a structured format. Output of PrintTree void PrintTree(node_t *tree_p, int indent){ int i; if (tree_p != NULL){ PrintTree(tree_p->right_p, indent+5); for(i=1, i<=indent, i++){ printf(“ “); } printf(“%d\n”,tree_p->value); printTree(tree_p->left_p, indent+5); } } 1 3 8 4 6 5 2 /* Fig. 12.19: fig12_19.c 2 Create a binary tree and traverse it 3 preorder, inorder, and postorder */ 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <time.h> fig12_19.c (Part 1 of 6) 27 int i; /* counter */ 28 int item; /* variable to hold random values */ 29 TreeNodePtr rootPtr = NULL; /* initialize rootPtr */ 30 31 srand( time( NULL ) ); 32 printf( "The numbers being placed in the tree are:\n" ); fig12_19.c (Part 2 of 6) 33 7 8 /* self-referential structure */ 34 /* insert random values between 1 and 15 in the tree */ 9 struct treeNode { 35 for ( i = 1; i <= 10; i++ ) { 10 struct treeNode *leftPtr; /* treeNode pointer */ 36 11 int data; /* define data as an int */ 37 12 struct treeNode *rightPtr; /* treeNode pointer */ 38 item = rand() % 15; printf( "%3d", item ); insertNode( &rootPtr, item ); } /* end for */ 13 }; /* end structure treeNode */ 39 14 40 15 typedef struct treeNode TreeNode; 41 /* traverse the tree preOrder */ 16 typedef TreeNode *TreeNodePtr; 42 printf( "\n\nThe preOrder traversal is:\n" ); 17 43 18 /* prototypes */ 44 19 void insertNode( TreeNodePtr *treePtr, int value ); 45 /* traverse the tree inOrder */ 20 void inOrder( TreeNodePtr treePtr ); 46 printf( "\n\nThe inOrder traversal is:\n" ); 21 void preOrder( TreeNodePtr treePtr ); 47 22 void postOrder( TreeNodePtr treePtr ); 48 23 49 /* traverse the tree postOrder */ 24 /* function main begins program execution */ 50 printf( "\n\nThe postOrder traversal is:\n" ); 25 int main() 51 postOrder( rootPtr ); 26 { 52 © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. preOrder( rootPtr ); inOrder( rootPtr ); © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. 12 else { /* tree is not empty */ 76 return 0; /* indicates successful termination */ 53 77 54 55 } /* end main */ 56 57 /* insert node into tree */ fig12_19.c (Part 3 of 6) 58 void insertNode( TreeNodePtr *treePtr, int value ) 78 /* data to insert is less than data in current node */ 79 if ( value < ( *treePtr )->data ) { insertNode( &( ( *treePtr )->leftPtr ), value ); 80 } /* end if */ 81 82 59 { 60 83 /* data to insert is greater than data in current node */ 84 else if ( value > ( *treePtr )->data ) { 61 /* if tree is empty */ 85 62 if ( *treePtr == NULL ) { 86 } /* end else if */ 87 else { /* duplicate data value ignored */ *treePtr = malloc( sizeof( TreeNode ) ); 63 64 insertNode( &( ( *treePtr )->rightPtr ), value ); printf( "dup" ); 88 65 /* if memory was allocated then assign data */ 89 66 if ( *treePtr != NULL ) { 90 } /* end else */ 67 ( *treePtr )->data = value; 91 68 ( *treePtr )->leftPtr = NULL; 92 69 ( *treePtr )->rightPtr = NULL; 93 } /* end function insertNode */ } /* end else */ 70 } /* end if */ 94 71 else { 95 /* begin inorder traversal of tree */ 96 void inOrder( TreeNodePtr treePtr ) printf( "%d not inserted. No memory available.\n", value ); 72 97 { } /* end else */ 73 fig12_19.c (Part 4 of 6) 98 74 } /* end if */ 75 © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. 121 /* begin postorder traversal of tree */ 99 /* if tree is not empty then traverse */ 100 if ( treePtr != NULL ) { 101 inOrder( treePtr->leftPtr ); 102 printf( "%3d", treePtr->data ); 103 104 inOrder( treePtr->rightPtr ); 122 void postOrder( TreeNodePtr treePtr ) 123 { fig12_19.c (Part 5 of 6) } /* end if */ 124 125 /* if tree is not empty then traverse */ 126 if ( treePtr != NULL ) { 127 105 128 106 } /* end function inOrder */ 107 108 /* begin preorder traversal of tree */ 109 void preOrder( TreeNodePtr treePtr ) 110 { 129 130 fig12_19.c (Part 6 of 6) postOrder( treePtr->leftPtr ); postOrder( treePtr->rightPtr ); printf( "%3d", treePtr->data ); } /* end if */ 131 132 } /* end function postOrder */ 111 112 /* if tree is not empty then traverse */ 113 if ( treePtr != NULL ) { 114 printf( "%3d", treePtr->data ); 115 preOrder( treePtr->leftPtr ); 116 117 preOrder( treePtr->rightPtr ); } /* end if */ The numbers being placed in the tree are: 6 7 4 12 7dup 2 2dup 5 7dup 11 The preOrder traversal is: 6 4 2 5 7 12 11 The inOrder traversal is: 2 4 5 6 7 11 12 118 119 } /* end function preOrder */ The postOrder traversal is: 2 5 4 11 12 7 6 120 © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. An iterative (non-recursive) version of the insertNode() function: void insertNode( TreeNodePtr *treePtr, int value ){ TreeNode *insertionPtr; TreeNode *newPtr; int insertionPointFound; newPtr = (TreeNode *) malloc(sizeof(TreeNode)); if(newPtr == NULL) { printf( "%d not inserted. No memory available.\n", value ); return; } else { newPtr->data = value; newPtr->leftPtr = NULL; newPtr->rightPtr = NULL; } if ( *treePtr == NULL ) { /* if tree is empty */ *treePtr = newPtr; } Continued on next slide Program Output © Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. Iterative InsertNode() (continued) else { /* tree is not empty */ insertionPointFound = FALSE; insertionPtr = *treePtr; while (!insertionPointFound) { if (value < (insertionPtr->data)) { /* data to insert is less than data in current node */ if ((insertionPtr->leftPtr) == NULL) { insertionPointFound = TRUE; insertionPtr->leftPtr = newPtr; } else { insertionPtr = insertionPtr->leftPtr; } } else { if (value > (insertionPtr->data)) { / data to insert is greater than data in current node */ /* / if ((insertionPtr->rightPtr) == NULL) { insertionPointFound = TRUE; insertionPtr->rightPtr = newPtr; } else { insertionPtr = insertionPtr->rightPtr; } } else { /* duplicate data value ignored */ insertionPointFound = TRUE; printf( "dup" ); free(newPtr); /* new node not needed */ } } } /* end while */ } /* end else */ } /* end function insertNode */ 13 A Recursive Version of the TreeSearch Function Searching a Binary Search Tree /* The function TreeSearch searches a binary search tree rooted by rootPtr for a node with data matching the searchArg. If a match is found, a pointer to the matching node is returned. Otherwise a NULL pointer is returned */ /* The function TreeSearchRec recursively searches a binary search tree for a node with data matching the searchArg. If a match is found, a pointer to the matching node is returned. Otherwise a NULL pointer is returned */ TreeNodePtr TreeSearch(TreeNodePtr rootPtr, int searchArg) { TreeNodePtr currentNode; int MatchFound; TreeNodePtr TreeSearchRec(TreeNodePtr rootPtr, int searchArg) { if(rootPtr ==NULL) { return NULL; } else { if(searchArg == rootPtr->data) { return rootPtr; } else { if (searchArg < rootPtr->data) { return TreeSearchRec(rootPtr->leftPtr, searchArg); } else { /* (searchArg > rootPtr->data) */ return TreeSearchRec(rootPtr->rightPtr, searchArg); } } } } /* end of function TreeSearchRec() */ currentNode = rootPtr; MatchFound = FALSE; while((currentNode != NULL) && !MatchFound) { if (currentNode->data == searchArg) { MatchFound=TRUE; } else { if (searchArg < currentNode->data) { currentNode = currentNode->leftPtr; } else { currentNode = currentNode->rightPtr; } } } return currentNode; } A Caveat about Binary Search Trees z BST Balance z A BST is efficient for searching and other operations, only if it is “balanced”. z 2 5 z 3 3 2 8 4 6 4 9 z 5 z 6 7 A balanced BST For a BST constructed from a randomly ordered data stream, the degree of tree balance will be a random function of the original data order E.g. for the trees on the previous slide: An Unbalanced BST 7 8 a data order of 5 3 8 2 4 6 7 9 yyields the balanced tree on the left a data order of 2 3 4 5 6 7 8 9 yields the unbalanced tree on the right. There are a number of sophisticated techniques for creating balanced BSTs and maintaining balance in the presence of insertions and deletions. 9 14