0% found this document useful (0 votes)
14 views

06_Dynamic_Data_Structures_I

Uploaded by

Destiny
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
14 views

06_Dynamic_Data_Structures_I

Uploaded by

Destiny
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 23

Dynamic Data Structures

CEN116 Algorithms and Programming II


Dynamic data structures
• Dynamic data structures that can grow and shrink at execution time:
• Linked lists are collections of data items “lined up in a row.” You can insert
and delete items anywhere in a linked list.
• Stacks are important in compilers and operating systems. You can insert and
delete items only at one end of a stack, known as its top.
• Queues represent waiting lines. You can insert only at the queue’s back and
delete only from its front. The back and front are known as the queue’s tail
and head.
• Binary trees facilitate high-speed searching and sorting of data, efficiently
eliminating duplicate data items and compiling expressions into machine
language.
• Each has many other interesting applications
Self-Referential Structures
• Contains a pointer member that points to a structure of the same type
• struct node {
int data;
struct node *nextPtr;
};
• nextPtr is a link—it points to another struct node
• Pointer is same type as the struct we’re defining, hence “self-referential
structure”
• nextPtr used to link a struct node to another struct node
Self-Referential Structures

• Can link self-referential structure objects to form lists, queues, stacks and trees
• The \ in the last node’s link member is a NULL pointer represents end of a data
structure
Dynamic Memory Management
• Dynamic memory management has two components:
• obtaining more memory at execution time to hold new nodes
• releasing memory no longer needed
malloc Function
• Request memory by passing to malloc the number of bytes to allocate
• If successful, it returns a void * pointer to the allocated memory
• Commonly used with sizeof
• newPtr = malloc(sizeof(struct node));
• Not guaranteed to initialize memory, but many implementations do for security
Dynamic Memory Management
• If no memory is available, malloc returns NULL
• Always test for a NULL pointer before accessing the dynamically allocated
memory
free Function
• Return dynamic memory to the system when no longer needed
• free(newPtr);
• After deallocating memory, set the pointer to NULL
• Prevents accidentally referring to that memory
• Not freeing dynamically allocated memory cause a “memory leak”
• Could eventually lead to running out of memory
• Accessing freed memory typically causes a program to crash
Dynamic Memory Management
Functions calloc and realloc
• Used to create and modify the size of dynamic arrays
Linked Lists
• Linear collections of self-referential struct objects (nodes) connected by
pointer links—hence the term “linked” list
• Access a via a pointer to the first node
• Access subsequent nodes via the nodes’ pointer link members
• Store data in a linked list by creating each node as necessary
• Stacks and queues are also linear data structures
• Constrained versions of linked lists.
Arrays versus Linked Lists
Linked lists provide several advantages:
• A linked list’s length can increase or decrease as necessary. Arrays are fixed-size.
• An array may contain more elements than needed, but this can waste memory.
Using linked lists can save memory, however, the pointers in a list’s nodes require
additional memory and memory allocation incurs the overhead of function calls.
• Fixed-size arrays can become full. Linked lists become full only when the system
has insufficient memory to satisfy dynamic storage-allocation requests.
• Linked lists can be maintained in sorted order by inserting each new element at
the appropriate point in the list. Inserting into and deleting from a sorted array
can be time-consuming—all elements following the inserted or deleted element
must be shifted appropriately.
Arrays versus Linked Lists
Arrays Are Faster for Direct Element Access
• Array elements are contiguous in memory and can be accessed
directly by index
• Linked lists do not afford such immediate access to their elements
Linked Lists
Illustrating a Linked List
• Linked-list nodes generally are not contiguous in memory.
• Logically, the nodes appear to be contiguous, as in:
Implementing a Linked List
• Example program manipulates a list of characters
• The primary functions of linked lists are insert and delete
• Function isEmpty is a predicate function—it does not alter the list
in any way; rather it determines whether 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 prints the list.
Implementing a Linked List
• Characters are inserted in the list in alphabetical order.
• Function insert receives the address of the list and a character to be
inserted.
• The list’s address is necessary when a value is to be inserted at the
start of the list.
• Providing the address enables the list (i.e., the pointer to the first
node of the list) to be modified via a call by reference.
• Because the list itself is a pointer (to its first element), passing its
address creates a pointer to a pointer (i.e., double indirection).
• This is a complex notion and requires careful programming.
Function insert
• Example inserts characters in the list in alphabetical order
• Function insert receives as an argument the address of the
pointer to the list’s first node and a character to insert
• Enables insert to modify the caller’s pointer to the list’s first node
to point to a new first node when a data item is placed at the front
• Passing a pointer’s address creates a pointer to a pointer—
sometimes called double indirection
Function insert
insert performs the following steps:
• Call malloc to create a new node and assign newPtr the allocated memory’s
address
• If memory was allocated
• Assign the character to insert to newPtr->data, and NULL to newPtr-
>nextPtr
• Always assign NULL to a new node’s link member initially
• previousPtr and currentPtr store locations of the node preceding and
after the insertion point
• Initialize previousPtr to NULL and currentPtr to *sPtr—the first node’s
address
• Locate the new value’s insertion point
Function insert
• Locate the new value’s insertion point
• While currentPtr is not NULL and the value to insert is greater than currentPtr-
>data, assign currentPtr to previousPtr, then advance currentPtr to the
list’s next node
• Insert the new value in the list
• If previousPtr is NULL, insert the new node as the first node
• Assign *sPtr to newPtr->nextPtr (new node’s link points to the former first
node)
• Assign newPtr to *sPtr so startPtr in main points to the new first node.
• Otherwise, insert the new node in place
• Assign newPtr to previousPtr->nextPtr (the previous node points to the new
node)
• Assign currentPtr to newPtr->nextPtr (the new node link points to the
current node)
Function insert
• For simplicity, we implemented function insert (and other similar
functions in this chapter) with a void return type
• Function malloc may fail to allocate the requested memory
• It would be better for insert to return a status that indicates whether the
operation was successful
Function insert
Function delete
• Receives the address of the pointer to the list’s first node and a character to
delete.
• Performs the following steps:
• If the character to delete matches the first node’s character, remove the first
node
• Assign *sPtr to tempPtr, which we’ll use to free the node’s memory
• Assign (*sPtr)->nextPtr to *sPtr, so startPtr in main points
to what previously was the second node
• Call free to deallocate the memory pointed to by tempPtr
• Return the deleted character
• Otherwise, initialize previousPtr with *sPtr and currentPtr with
(*sPtr)->nextPtr
Function delete
• Locate the character to delete
• While currentPtr is not NULL and the value to delete is not equal to
currentPtr->data, assign currentPtr to previousPtr and assign
currentPtr->nextPtr to currentPtr
• If currentPtr is not NULL, return the deleted character
• Assign currentPtr to tempPtr – used to deallocate the node
• Assign currentPtr->nextPtr to previousPtr->nextPtr – connects the
nodes before and after the one being removed
• Free the node pointed to by tempPtr, then return the deleted character
• If nothing has been returned, return the null character ('\0') to
signify the character was not found in the list
Function delete
Functions isEmpty and printList
• isEmpty is a predicate function—it does not alter the list
• It determines whether the list is empty—the pointer to the first node is NULL
• If the list is empty, returns 1; otherwise, returns 0
• printList prints a list
• currentPtr parameter receives a pointer to the list’s first node
• If empty, prints "List is empty." and terminates
• Otherwise, print the list’s data
• While currentPtr is not NULL
• prints currentPtr->data
• assigns currentPtr->nextPtr to currentPtr to advance to the next
node
• 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, which is a logic error
References
• C How to Program, Ninth Edition by Deitel & Deitel, Pearson, 2022.

You might also like