Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
34 views23 pages

06 Dynamic Data Structures I

Uploaded by

Destiny
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
34 views23 pages

06 Dynamic Data Structures I

Uploaded by

Destiny
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
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