660 likes | 868 Views
Chapter 3. Topics. Arrays Singly Linked Lists Doubly Linked Lists Circularly List Lists and List Reversal Recursion. Arrays. Collection of n elements stored in a certain linear order (same type) Range [0,n-1] Index of an element is the number of elements that precede the element
E N D
Topics • Arrays • Singly Linked Lists • Doubly Linked Lists • Circularly List Lists and List Reversal • Recursion
Arrays • Collection of n elements stored in a certain linear order (same type) • Range [0,n-1] • Index of an element is the number of elements that precede the element • C++ does not have built-in boundary checking
Array Lists (1) • An array is a fixed-size data structure • Once an array is created, its size cannot be changed • Nevertheless, one can still use array to implement dynamic data structures • The trick is to create a new larger array to replace the current array if the current array cannot hold new elements in the list
Array Lists (2) • Initially, an array is created with a default size • When inserting a new element into the array, first ensure there is enough room in the array • If not, create a new array with the size as twice as the current one • Copy the elements from the current array to the new array • The new array now becomes the current array
Insertion Before inserting a new element at a specified index, shift all the elements after the index to the right and increase the list size by 1 Each cell stores a reference of an object
Deletion To remove an element at a specified index, shift all the elements after the index to the left by one position and decrease the list size by 1
Sample Code using Arrays • See examples (array1 – array7)
Sorting an Array • Insertion Sort • The insertion sort algorithm sorts a list of values by repeatedly inserting an unsorted element into a sorted sub-list until the whole list is sorted
Insertion Sort int[] myList = {2, 9, 5, 4, 8, 1, 6}; // Unsorted
Insertion Sort void insertionSort(char* A, int n) { // sort an array of n characters for (inti = 1; i < n; i++) { // insertion loop char cur = A[i]; // current character to insert int j = i - 1; // start at previous character while ((j >= 0) && (A[j] > cur)) { // while A[j] is out of order A[j + 1] = A[j]; // move A[j] right j--; // decrement j } A[j + 1] = cur; // this is the proper place for cur } }
Limitations of Arrays • One can find the size of the array, store, retrieve, and modify data in the array • Arrays are simple and easy to use, but they have two limitations • Once an array is created, its size cannot be altered • Array provides inadequate support for inserting, deleting, sorting, and searching operations
Linked Lists • The order of the components is determined by an explicit link member in each node • The list needs to be traverse to access nodes
Singly Linked Lists • A singly linked list is a concrete data structure consisting of a sequence of nodes • Each node stores • element • link to the next node (except the last node) • Every node in a linked list has two components • Each node contains a component member and also a link member that gives the location of the next node in the list • The address of the first node of the list is stored in a separate location called the “head”
ATL BOS Singly Linked List Structure next node elem A B C D head tail NULL LAX MSP
Constructing a Singly Linked List • See source code (3.13 – 3.15)
LAX MSP ATL BOS MSP ATL BOS Insertion in a Singly Linked List (head) head tail NULL head tail NULL
Linked Lists Allocate a new node Insert new element Have new node point to old head Update head to point to new node Inserting at the Head See source code (3.16)
LAX MSP ATL BOS MSP ATL BOS Removing an Element in a Singly Linked List (head) head tail NULL head tail NULL
Linked Lists Removing at the Head • Update head to point to next node in the list • Allow garbage collector to reclaim the former first node See source code (3.17)
MSP ATL BOS MSP ATL BOS MIA Insertion in a Singly Linked List (tail) head tail NULL head tail NULL
Linked Lists Inserting at the Tail Allocate a new node Insert new element Have new node point to null Have old last node point to new node Update tail to point to new node
Linked Lists Removing at the Tail • Removing at the tail of a singly linked list is not efficient! • There is no constant-time way to update the tail to point to the previous node • Need to update the next link of the node immediately preceding the delete node • Should use doubly linked lists
Implementing a Generic Linked List • See source code (3.18 – 3.21) • See examples (link1 – link7)
Doubly Linked Lists • A doubly linked list is a linked list in which every node has a next and a back pointer • A doubly linked list can be traversed in either direction • One can traverse the list starting at the first node or if a pointer to the last node is given, we can traverse the list starting at the last node • Quicker updates in the middle of the list compared to a singly linked list • A header node and a trailer node exist (containing no data) header PVD JFK trailer SFO
prev next elem node Doubly Linked Lists header PVD JFK trailer SFO
Doubly Linked Lists (1) • Header and Trailer Sentinels • Separate header and trailer • One header, one trailer • Integrated header and trailer • One node with previous pointing to the last node and next pointing to the first node
Lists Insertion • We visualize operation insert(p, x), which inserts x before p p a b c p a b c q x q p a b x c
Lists Insertion Algorithm Algorithm insert(p, e): {insert e before p} Create a new node v velement = e u = pprev vnext = p; pprev = v {link in v before p} vprev = u; unext = v {link in v after u}
Lists Deletion • We visualize remove(p) p a b c d a b c p d a b c
Lists Deletion Algorithm Algorithm remove(p): u = pprev w = pnext unext = w{linking out p} wprev = u See example (link8)
Circularly Link List • A linked list without head or tail • Traversal means circle through all nodes • Singly linked list where the last node points to the first node • Cursor allows one to have a place to start • Keeps track of where traversing commenced • Methods • Add node: insert after the cursor • Remove node: remove node immediately after the cursor • Advance node: advance the cursor to the next node
ATL BOS Circularly Link List cursor MIA MSP
Circularly Linked Lists Methods (1) • front () • Returns the element referenced by the cursor • Returns an error if the list is empty • back () • Returns the element immediately after the cursor • Returns an error if the list is empty • advance () • Advance the cursor to the next in the list • Returns an error if the list is empty
Circularly Linked Lists Methods (2) • add (e) • Insert a new node with element e immediately after the cursor • If the list is empty, then this node becomes the cursor and its next pointer points to itself • remove () • Remove the node immediately after the cursor • Not the cursor itself unless it is the only node • If the list becomes empty, the cursor is set to null
Implementing a Circularly Linked List • See source code (3.28 – 3.34)
Reversing a Doubly Link List • See source code (3.35)
Using Recursion Using Recursion
Recursion • Recursion is when a function calls itself or calls a function which in turn calls the originating function • A recursive solution to a problem must be written carefully • Need to avoid making an infinite sequence of function calls (infinite recursion) • Each recursive algorithm must have at least one base case, as well as a general (recursive) case • One must supply an exit routine (make sure that code is not an endless loop)
Recursion • Recursion is used since some problems are easier to code using this technique • Recursive programs tend to use alot of memory • Every recursive program can be rewritten with an iteration replacing the recursion • Conversely, every iteration can be written with recursion replacing iteration
General format for Many Recursive Functions • if (some easily-solved condition) // base case • solution statement • else // general case • recursive function call
When a function is called ... (1) • When any function is called the run-time stack is used • On this stack is placed an activation frame for each function call • The activation frame contains the return address for this function call, and also the parameters, and local variables, and space for the function’s return value, if non-void • These frames are put on a stack • They are destroyed in reverse order in which they are created • This stack is a last in/first out (LIFO) • There is a limit on the size of the stack
When a function is called ... (2) • If the operating system runs out of stack space, there may be a stack overflow error or the computer may simply stop responding until a reboot • Stacks overflows are usually caused by infinite recursion • The activation frame for a particular function call is popped off the run-time stack when the final closing brace in the function code is reached, or when a return statement is reached in the function code • At this time the function’s return value, if non-void, is brought back to the calling block return address for use there
Linear Recursion • Test for base cases • Begin by testing for a set of base cases (there should be at least one) • Every possible chain of recursive calls must eventually reach a base case, and the handling of each base case should not use recursion • Recur once • Perform a single recursive call • This step may have a test that decides which of several possible recursive calls to make, but it should ultimately make just one of these calls • Define each possible recursive call so that it makes progress towards a base case
Linear Recursion • Linear Recursion • Where a function is defined so that is makes at most one recursive cal each time it is invoked • Useful when one views an algorithm problem in terms of a first or last element plus a remaining set that has the same structure as the original set
Summation • Writing a Recursive Function to Find the Sum of the Numbers from 1 to n called Summation The sum of the numbers from 1 to n, that is, 1 + 2 + . . . + n can be written as n + the sum of the numbers from 1 to (n - 1), that is, n + 1 + 2 + . . . + (n-1) or n + Summation(n - 1)
Summation(4) Trace of Call Returns 4 + Summation(3) = 4 + 6 = 10 Call 1: Summation(4) Returns 3 + Summation(2) = 3 + 3 = 6 Call 2: Summation(3) Returns 2 + Summation(1) = 2 + 1 =3 Call 3: Summation(2) n==1 Returns 1 Call 4: (See example recur1)Summation(1) n 4 n 3 n 2 n 1
Factorial • Writing a Recursive Function to Find n Factorial The function call Factorial(4) should have value 24, because that is 4 * 3 * 2 * 1 . The value of Factorial(n) can be written as n * the product of the numbers from (n - 1) to 1, that is, n * (n - 1) * . . . * 1 or, n * Factorial(n - 1) • (See example recur2)