1 / 109

C Data Structures

C Data Structures. C How to Program, 6/e. 12.1   Introduction. We’ve studied fixed-size data structures such as single-subscripted arrays, double-subscripted arrays and struct s . This chapter introduces dynamic data structures with sizes that grow and shrink at execution time.

mandar
Télécharger la présentation

C Data Structures

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. C Data Structures C How to Program, 6/e

  2. 12.1  Introduction • We’ve studied fixed-size data structures such as single-subscripted arrays, double-subscripted arrays and structs. • This chapter introduces dynamicdata structures with sizes that grow and shrink at execution time. • Linked lists are collections of data items “lined up in a row”—insertions and deletions are made anywhere in a linked list. • Stacks are important in compilers and operating systems—insertions and deletions are made only at one end of a stack—its top.

  3. 12.1  Introduction (Cont.) • Queues represent waiting lines; insertions are made at the back (also referred to as the tail) of a queue and deletions are made from the front (also referred to as the head) of a queue. • Binary trees facilitate high-speed searching and sorting of data, efficient elimination of duplicate data items, representing file system directories and compiling expressions into machine language. • Each of these data structures has many other interesting applications.

  4. 12.1  Introduction (Cont.) • We’ll discuss each of the major types of data structures and implement programs that create and manipulate these data structures. • In the next part of the book—the introduction to C++ and object-oriented programming—we’ll study data abstraction. • This technique will enable us to build these data structures in a dramatically different manner designed for producing software that is much easier to maintain and reuse. • The programs are especially heavy on pointer manipulation.

  5. 12.2  Self-Referential Structures • A self-referential structure contains a pointer member that points to a structure of the same structure type. • For example, the definition • struct node { int data;struct node *nextPtr;}; defines a type, structnode. • A structure of type structnode has two members—integer member data and pointer member nextPtr.

  6. 12.2  Self-Referential Structures (Cont.) • Member nextPtr points to a structure of type structnode—a structure of the same type as the one being declared here, hence the term “self-referential structure.” • Member nextPtr is referred to as alink—i.e., nextPtr can be used to “tie” a structure of type structnode to another structure of the same type. • Self-referential structures can be linked together to form useful data structures such as lists, queues, stacks and trees.

  7. 12.2  Self-Referential Structures (Cont.) • Figure 12.1 illustrates two self-referential structure objects linked together to form a list. • A slash—representing a NULL pointer—is placed in the link member of the second self-referential structure to indicate that the link does not point to another structure. • [Note: The slash is only for illustration purposes; it does not correspond to the backslash character in C.] • A NULL pointer normally indicates the end of a data structure just as the null character indicates the end of a string.

  8. 12.3  Dynamic Memory Allocation • Creating and maintaining dynamic data structures requires dynamic memory allocation—the ability for a program to obtain more memory space at execution time to hold new nodes, and to release space no longer needed. • The limit for dynamic memory allocation can be as large as the amount of available physical memory in the computer or the amount of available virtual memory in a virtual memory system. • Often, the limits are much smaller because available memory must be shared among many applications. • Functions malloc andfree, and operator sizeof, are essential to dynamic memory allocation.

  9. 12.3  Dynamic Memory Allocation (Cont.) • Function malloc takes as an argument the number of bytes to be allocated and returns a pointer of type void* (pointer to void)to the allocated memory. • A void* pointer may be assigned to a variable of any pointer type. • Function malloc is normally used with the sizeof operator.

  10. For example, the statement • newPtr = malloc( sizeof( struct node ) ); • evaluates sizeof(structnode) to determine the size in bytes of a structure of type structnode, allocates a new area in memory of that number of bytes and stores a pointer to the allocated memory in variable newPtr.

  11. 12.3  Dynamic Memory Allocation (Cont.) • The allocated memory is not initialized. • If no memory is available, malloc returns NULL. • Function freedeallocates memory—i.e., the memory is returned to the system so that the memory can be reallocated in the future. • To free memory dynamically allocated by the preceding malloc call, use the statement • free( newPtr ); • C also provides functions calloc and realloc for creating and modifying dynamic arrays.

  12. 12.4  Linked Lists • A linked list is a linear collection of self-referential structures, called nodes, connected by pointer links—hence, the term “linked” list. • A linked list is accessed via a pointer to the first node of the list. • Subsequent nodes are accessed via the link pointer member stored in each node. • By convention, the link pointer in the last node of a list is set to NULL to mark the end of the list. • Data is stored in a linked list dynamically—each node is created as necessary.

  13. 12.4  Linked Lists (Cont.) • A node can contain data of any type including other struct objects. • Stacks and queues are also linear data structures, and, as we’ll see, are constrained versions of linked lists. • Trees are nonlinear data structures. • Lists of data can be stored in arrays, but linked lists provide several advantages. • A linked list is appropriate when the number of data elements to be represented in the data structure is unpredictable. • Linked lists are dynamic, so the length of a list can increase or decrease as necessary.

  14. 12.4  Linked Lists (Cont.) • The size of an array, however cannot be altered once memory is allocated. • Arrays can become full. • Linked lists become full only when the system has insufficient memory to satisfy dynamic storage allocation requests.

  15. 12.4  Linked Lists (Cont.) • Linked lists can be maintained in sorted order by inserting each new element at the proper point in the list.

  16. 12.4  Linked Lists (Cont.) • Linked list nodes are normally not stored contiguously in memory. • Logically, however, the nodes of a linked list appear to be contiguous. • Figure 12.2 illustrates a linked list with several nodes.

  17. 12.4  Linked Lists (Cont.) • Figure 12.3 (output shown in Fig. 12.4) manipulates a list of characters. • The program enables you to insert a character in the list in alphabetical order (function insert) or to delete a character from the list (function delete).

  18. 12.4  Linked Lists (Cont.) • The primary functions of linked lists are insert (lines 86–120) and delete (lines 123–156). • Function isEmpty (lines 159–162) is called a predicate function—it does not alter the list in any way; rather it determines if the list is empty (i.e., the pointer to the first node of the list is NULL). • If the list is empty, 1 is returned; otherwise, 0 is returned. • Function printList (lines 165–182) prints the list.

  19. 12.4  Linked Lists (Cont.) • Characters are inserted in the list in alphabetical order. • Function insert (lines 86–120) receives the address of the list and a character to be inserted. • The address of the list is necessary when a value is to be inserted at the start of the list. • Providing the address of the list enables the list (i.e., the pointer to the first node of the list) to be modified via a call by reference. • Since the list itself is a pointer (to its first element), passing the address of the list creates a pointer to a pointer (i.e., double indirection). • This is a complex notion and requires careful programming.

  20. 12.4  Linked Lists (Cont.) • The steps for inserting a character in the list are as follows (see Fig. 12.5): • Create a node by calling malloc, assigning to newPtr the address of the allocated memory (line 92), assigning the character to be inserted to newPtr->data (line 95), and assigning NULL to newPtr->nextPtr (line 96). • Initialize previousPtr to NULL (line 198) and currentPtr to *sPtr (line 99)—the pointer to the start of the list. Pointers previousPtr and currentPtr store the locations of the node preceding the insertion point and the node after the insertion point. • While currentPtr is not NULL and the value to be inserted is greater than currentPtr->data (line 102), assign currentPtr to previousPtr (line 103) and advance currentPtr to the next node in the list (line 104). This locates the insertion point for the value.

  21. 12.4  Linked Lists (Cont.) • If previousPtr is NULL (line 108), insert the new node as the first node in the list (lines 109–110). Assign *sPtr to newPtr->nextPtr (the new node link points to the former first node) and assign newPtr to *sPtr (*sPtr points to the new node). Otherwise, if previousPtr is not NULL, the new node is inserted in place (lines 113–114). Assign newPtr to previousPtr->nextPtr (the previous node points to the new node) and assign currentPtr to newPtr->nextPtr (the new node link points to the current node).

  22. 12.4  Linked Lists (Cont.) • Figure 12.5 illustrates the insertion of a node containing the character 'C' into an ordered list. • Part a) of the figure shows the list and the new node before the insertion. • Part b) of the figure shows the result of inserting the new node. • The reassigned pointers are dotted arrows. • For simplicity, we implemented function insert (and other similar functions in this chapter) with a void return type. • It’s possible that function malloc will fail to allocate the requested memory. • In this case, it would be better for our insert function to return a status that indicates whether the operation was successful.

  23. 12.4  Linked Lists (Cont.) • Function delete (lines 123–156) receives the address of the pointer to the start of the list and a character to be deleted. • The steps for deleting a character from the list are as follows: • If the character to be deleted matches the character in the first node of the list (line 130), assign *sPtr to tempPtr (tempPtr will be used to free the unneeded memory), assign (*sPtr)->nextPtr to *sPtr (*sPtr now points to the second node in the list), free the memory pointed to by tempPtr, and return the character that was deleted. • Otherwise, initialize previousPtr with *sPtr and initialize currentPtr with (*sPtr)->nextPtr (lines 137–138). • While currentPtr is not NULL and the value to be deleted is not equal to currentPtr->data (Line 141), assign currentPtr to previousPtr (line 142), and assign currentPtr->nextPtr to currentPtr (line 143). This locates the character to be deleted if it’s contained in the list.

  24. 12.4  Linked Lists (Cont.) • If currentPtr is not NULL (line 147), assign currentPtr to tempPtr (line 148), assign currentPtr->nextPtr to previousPtr->nextPtr (line 149), free the node pointed to by tempPtr (line 150), and return the character that was deleted from the list (line 151). If currentPtr is NULL, return the null character ('\0') to signify that the character to be deleted was not found in the list (line 155).

  25. 12.4  Linked Lists (Cont.) • Figure 12.6 illustrates the deletion of a node from a linked list. • Part a) of the figure shows the linked list after the preceding insert operation. • Part b) shows the reassignment of the link element of previousPtr and the assignment of currentPtr to tempPtr. • Pointer tempPtr is used to free the memory allocated to store 'C'.

  26. 12.4  Linked Lists (Cont.) • Function printList (lines 165–182) receives a pointer to the start of the list as an argument and refers to the pointer as currentPtr. • The function first determines if the list is empty (lines 168–170) and, if so, prints "Thelistisempty." and terminates. • Otherwise, it prints the data in the list (lines 171–181).

  27. 12.4  Linked Lists (Cont.) • While currentPtr is not NULL, the value of currentPtr->data is printed by the function, and currentPtr->nextPtr is assigned to currentPtr. • If the link in the last node of the list is not NULL, the printing algorithm will try to print past the end of the list, and an error will occur. • The printing algorithm is identical for linked lists, stacks and queues.

  28. 12.5  Stacks • A stack is a constrained version of a linked list. • New nodes can be added to a stack and removed from a stack only at the top. • For this reason, a stack is referred to as alast-in, first-out (LIFO) data structure. • A stack is referenced via a pointer to the top element of the stack. • The link member in the last node of the stack is set to NULL to indicate the bottom of the stack.

  29. 12.5  Stacks (Cont.) • Figure 12.7 illustrates a stack with several nodes. • Stacks and linked lists are represented identically. • The difference between stacks and linked lists is that insertions and deletions may occur anywhere in a linked list, but only at the top of a stack.

  30. 12.5  Stacks (Cont.) • The primary functions used to manipulate a stack are push and pop. • Function push creates a new node and places it on top of the stack. • Function pop removes a node from the top of the stack, frees the memory that was allocated to the popped node and returns the popped value. • Figure 12.8 (output shown in Fig. 12.9) implements a simple stack of integers. • The program provides three options: 1) push a value onto the stack (function push), 2) pop a value off the stack (function pop) and 3) terminate the program.

More Related