Download presentation
Presentation is loading. Please wait.
1
Very Powerful Data Structure
Linked Lists Very Powerful Data Structure Copyright © 2004 – – Curt Hill
2
Comparing with Stacks and queues
Stacks have only one site for add or delete Queues have two A deque has two as well A linked list can have action anywhere There are many operations for a list that make no sense with a stack or queue Copyright © 2004 – – Curt Hill
3
Don’t do this with a stack
The idea of searching a list The idea of sorting a list Maintaining a sorted list Insertion anywhere Deletion anywhere Traversal Windows Interchange of two members Copyright © 2004 – – Curt Hill
4
Simulating an array with a list
Any operation an array can do a list can do Disregarding speed Since an array is all that memory is Any data structures can be simulated by array One can conclude that a list is very strong Some things are easy for one and hard for the other Insertion/deletion in an array is hard, in a list it is easy Copyright © 2004 – – Curt Hill
5
Copyright © 2004 – 2006 – Curt Hill
Topologies Depending on our needs there are several list types that are useful Straight singly linked list Circular singly linked list Straight doubly linked list Circular doubly linked list Most of the other variants cease to be a list Second pointer that points 5 (or any distance) ahead This is really a graph Copyright © 2004 – – Curt Hill
6
Copyright © 2004 – 2006 – Curt Hill
Singly Linked List NULL Copyright © 2004 – – Curt Hill
7
Copyright © 2004 – 2006 – Curt Hill
Singly Linked List Starts with a single pointer Usually named variable on stack Often known as root This points to first item The first item contains data and pointer to next item Chain ends with a null pointer An empty list has a NULL pointer in the root Copyright © 2004 – – Curt Hill
8
Copyright © 2004 – 2006 – Curt Hill
Contents Each node or item contains data and a pointer The data may contain a key or not If it contains a key: The list may be sorted or unsorted It may be searched If there is no key, is there any reason to touch the interior of the list? However, we may need an enlarged notion of a key Copyright © 2004 – – Curt Hill
9
Copyright © 2004 – 2006 – Curt Hill
Curt’s Rule Pointers are too dangerous to be left running around Thus classes should contain and hide pointers Therefore two or three classes should be used in this case Copyright © 2004 – – Curt Hill
10
Copyright © 2004 – 2006 – Curt Hill
The Classes Friend class Main class Iterator class NULL Copyright © 2004 – – Curt Hill
11
Copyright © 2004 – 2006 – Curt Hill
The Classes The main class contains only the root of the list Most of the methods are there Contains only one pointer A friend class contains the data and a pointer Most of its data and methods are private Thus only the main class can access An iterator class could also be used If needed Copyright © 2004 – – Curt Hill
12
Copyright © 2004 – 2006 – Curt Hill
Linked Stacks A stack may be implemented by a singly linked list A push inserts item at the root A pop removes the item pointed to by root Empty is just root equal to null Full returns false Count or size requires an extra integer Copyright © 2004 – – Curt Hill
13
Copyright © 2004 – 2006 – Curt Hill
Processing an Item A push works like this: Create the new node Make the new node point at same item as root Redirect root to this first item Pop is not quite the reverse but close Consider the push graphically Copyright © 2004 – – Curt Hill
14
Linked Stack Push (step 0)
The original linked stack 3 2 1 NULL Copyright © 2004 – – Curt Hill
15
Linked Stack Push (step 1)
Create the new node Root 3 2 1 NULL 4 temp NULL Copyright © 2004 – – Curt Hill
16
Linked Stack Push (step 2)
Redirect the new node Root 3 2 1 NULL 4 temp Copyright © 2004 – – Curt Hill
17
Linked Stack Push (step 3)
Redirect the new node Root 3 2 1 NULL 4 temp Copyright © 2004 – – Curt Hill
18
Linked Stack Pop (step 0)
Original State Root 3 2 1 NULL 4 Copyright © 2004 – – Curt Hill
19
Linked Stack Pop (step 1)
Two pointers at top of stack Root 3 2 1 NULL 4 temp Copyright © 2004 – – Curt Hill
20
Linked Stack Pop (step 2)
Redirect root to second node Root 3 2 1 NULL 4 temp Copyright © 2004 – – Curt Hill
21
Linked Stack Pop (step 3)
Return results and delete temp Root 3 2 1 NULL temp Return 4 Copyright © 2004 – – Curt Hill
22
Copyright © 2004 – 2006 – Curt Hill
Perils of Pointers Every item on the heap is anonymous If there is no pointer referring to it, it is inaccessible Two pointers are needed to deleted item at start If root is deleted, no way to access the next item Must also save the item before deleting temp Copyright © 2004 – – Curt Hill
23
Copyright © 2004 – 2006 – Curt Hill
Linked Queues A queue may be implemented by a singly linked list The root has two pointers One to either end Adding to the queue adds at the end of the queue Removing removes from front of queue Empty is just root equal to null Full returns false Count or size requires an extra integer Copyright © 2004 – – Curt Hill
24
Copyright © 2004 – 2006 – Curt Hill
Linked Queue Main class Friend class Exit Enter NULL Copyright © 2004 – – Curt Hill
25
Linked Queue Remove (step 0)
Original state Enter Exit 1 2 3 NULL Copyright © 2004 – – Curt Hill
26
Linked Queue Remove (step 1)
Two pointers at exit Enter Exit 1 2 3 NULL temp Copyright © 2004 – – Curt Hill
27
Linked Queue Remove (step 2)
Advance exit Enter Exit 1 2 3 NULL temp Copyright © 2004 – – Curt Hill
28
Linked Queue Remove (step 3)
Return and remove Enter Exit 2 3 NULL temp Return 1 Copyright © 2004 – – Curt Hill
29
Copyright © 2004 – 2006 – Curt Hill
Processing Stack and queue processing is generally straightforward Are there any questions about how this would work? General list processing is somewhat more exciting Copyright © 2004 – – Curt Hill
30
Problems in processing
The thing that most complicates the code is the fatality of exercising a NULL pointer Typically we terminate the list with a NULL An empty list is rooted with a NULL We must be careful to verify the next pointer is not NULL before we move on to look at that item Singly linked lists are one directional, we cannot back up Because of this, many operations will need two pointers One to explore the frontier of the search One to point to the node that refers to the frontier In other words two pointers that are one node apart Copyright © 2004 – – Curt Hill
31
Copyright © 2004 – 2006 – Curt Hill
Special Cases Much of the thinking (and code) handles a number of special cases These cases vary with the code and the method to be implemented In list these are the normal ones to consider: Empty list Desired item is first Desired item is last Desired item is in the middle Copyright © 2004 – – Curt Hill
32
Copyright © 2004 – 2006 – Curt Hill
Searching a list Many of the other operations will involve a search, so it is best to look at this one first The search is terminated by one of three reasons: We find the item We run off the end of the list If the list is sorted and we have passed the point where the key could conceivably be The latter two indicate a failure to find the item Copyright © 2004 – – Curt Hill
33
Copyright © 2004 – 2006 – Curt Hill
Search PseudoCode if root is null return failure ptr = root while ptr is not null if ptr points at desired item return success if ptr is past the key return failure ptr = ptr’s next return failure Copyright © 2004 – – Curt Hill
34
Copyright © 2004 – 2006 – Curt Hill
Notes on Search The while prevents exercising a NULL pointer For search, the empty list is the only special case If the list is unsorted, the ptr is past key if can never be true Only one temporary pointer is required Copyright © 2004 – – Curt Hill
35
Copyright © 2004 – 2006 – Curt Hill
Insertion Somewhat more complicated then the find When we find the node that it will be inserted before we must also remember the node that points at it Several special cases should be considered in next screen The usual positions Does this list allow duplicates? Copyright © 2004 – – Curt Hill
36
Copyright © 2004 – 2006 – Curt Hill
Insertion Cases NULL Insert 5 5 9 25 NULL Insert 3 Insert 7 Insert 9 Insert 30 Copyright © 2004 – – Curt Hill
37
Copyright © 2004 – 2006 – Curt Hill
Special Cases Empty list No search, check before search Root changes A new first element of the list Start search only A new middle element of the list Both leading and trailing pointers are valid A new last element of the list Leading pointer falls off end of list Copyright © 2004 – – Curt Hill
38
Copyright © 2004 – 2006 – Curt Hill
Insertion Basic flow: Allocate and initialize a new node, unless duplicate and duplicates disallowed Involves three cases: Empty list Item inserted before current head of list Item inserted anywhere else on list Talk about and trace through the following code: Copyright © 2004 – – Curt Hill
39
Copyright © 2004 – 2006 – Curt Hill
Pseudocode (1 of 3) if root is null create and insert change root return success Create two pointers lead is set to root trail is set to null Drop into following loop: Copyright © 2004 – – Curt Hill
40
Copyright © 2004 – 2006 – Curt Hill
Pseudocode (2 of 3) while lead is not null if lead value is too large set lead to null else if lead value is equal if duplicates disallowed return failure else set trail to lead set lead to lead’s next Next screen is post loop cleanup Copyright © 2004 – – Curt Hill
41
Copyright © 2004 – 2006 – Curt Hill
Pseudocode (3 of 3) if trail is null create node node’s success = root root points at new node return success new node points at trails successor trail’s successor points at new node Copyright © 2004 – – Curt Hill
42
Copyright © 2004 – 2006 – Curt Hill
Insert Middle (step 0) Original state Root 5 9 25 NULL Copyright © 2004 – – Curt Hill
43
Copyright © 2004 – 2006 – Curt Hill
Insert Middle (step 1) Create two pointers Root 5 9 25 NULL trail NULL lead insert value 15 Copyright © 2004 – – Curt Hill
44
Copyright © 2004 – 2006 – Curt Hill
Insert Middle (step 2) Search starts, advance pointers Root 5 9 25 NULL trail NULL lead insert value 15 Copyright © 2004 – – Curt Hill
45
Copyright © 2004 – 2006 – Curt Hill
Insert Middle (step 3) Advance pointers again Root 5 9 25 NULL trail lead insert value 15 Copyright © 2004 – – Curt Hill
46
Copyright © 2004 – 2006 – Curt Hill
Insert Middle (step 4) Lead is past point, set to null, drop from loop Root 5 9 25 NULL trail lead null insert value 15 Copyright © 2004 – – Curt Hill
47
Copyright © 2004 – 2006 – Curt Hill
Insert Middle (step 5) Create new node Root 5 9 25 NULL trail lead 15 NULL NULL insert value 15 Copyright © 2004 – – Curt Hill
48
Copyright © 2004 – 2006 – Curt Hill
Insert Middle (step 6) Link new node into list Root 5 9 25 NULL trail lead 15 NULL insert value 15 Copyright © 2004 – – Curt Hill
49
Copyright © 2004 – 2006 – Curt Hill
Insert Middle (step 7) Finish linkage Root 5 25 9 NULL trail lead 15 insert value return success 15 Copyright © 2004 – – Curt Hill
50
Copyright © 2004 – 2006 – Curt Hill
Removing an item Find the node as we did in insert Have a temporary pointer refer to the item to be deleted Have the trailing pointer redirect its next to the one that follows the deletion Use the delete operator and finish up The same three cases do need to be considered Copyright © 2004 – – Curt Hill
51
Copyright © 2004 – 2006 – Curt Hill
Traversal/Iteration There are many needs to touch every node Sum the salaries of a list of employees Display/print every node Delete every node Traversal usually involves one call with a passed function Iteration usually involves one call per node The more general technique Copyright © 2004 – – Curt Hill
52
Passing a function to a function
How do we pass the address of a function into the class and then call it? Why? I want to create a sorted linked list template that has a key and value The operations will include: Insert an item Find an item Delete an item All of which can treat the list as a mass But to print each item requires: Knowledge of the form Copyright © 2004 – – Curt Hill
53
Why not code this in template?
With templatizable parameters, we do not know the parameter types We could use a template function, but it would require a known name Besides this will be fun We accomplish this with a variable that holds the address of a function What we need is a variable (that is a pointer) that holds the address of the function Copyright © 2004 – – Curt Hill
54
Copyright © 2004 – 2006 – Curt Hill
Pointers Recall that pointers must point to a specific kind of item: int * is not the same as char * double * is not float * Even though these are compatible In this regard the pointer must point to a specific type of function Copyright © 2004 – – Curt Hill
55
What is the signature of a function?
Usually the name However, pointers do not need a name The parameter list: Parameter passage mechanism By value, reference, constant reference etc The type of the parameter int double double * The number and order of the parameters The result type of the function is not part of the signature but in this case must know what type is being picked up after function is done Copyright © 2004 – – Curt Hill
56
Copyright © 2004 – 2006 – Curt Hill
Function Pointers We must declare a pointer to a function in such a way that it tells the compiler the result returned and the signature, which is everything it needs to know to call it Declaration of one of these looks unusual compared to most other declarations Suppose that we have these functions: int fn1(float i) { ... } int fn2(float j) { ... } As far as calling goes they are both called in exactly the same way Then a pointer to that kind of function would look like this: int (* pname) (float); Copyright © 2004 – – Curt Hill
57
Function pointer general form:
result (* var_name) parm_list Where: result is the result type that this thing will produce It may be any legal result type var_name is the name of the variable Not the name of the function, since any number of function addresses could be stored there parm_list is the parenthesized parameter list just like could be seen in a function prototype Copyright © 2004 – – Curt Hill
58
Copyright © 2004 – 2006 – Curt Hill
Example Suppose: template <class TYPE> class list{ … void traverse(void (* fn)(TYPE)){ … (*fn)(current->data); … To use and call void display(int); … list<int> mylist; … void (*fn)(int) ptr = &display; mylist.traverse(ptr); // or mylist.traverse(display); Copyright © 2004 – – Curt Hill
59
Copyright © 2004 – 2006 – Curt Hill
Notes Notice no parameter list in either call This is supplied in the traverse method No ampersand is needed if the function name is used Calling the function in traverse looks plenty weird The first parentheses pair develops the the address of the function The second the parameters to it Copyright © 2004 – – Curt Hill
60
Copyright © 2004 – 2006 – Curt Hill
Traversal The method itself is like a search Except it only looks for the end of the list Each node it finds it calls the passed method Using the data of the list Traversal is only called once The passed method is called once for each node on the list Not quite as general as iteration Copyright © 2004 – – Curt Hill
61
Copyright © 2004 – 2006 – Curt Hill
Iterators Iterators are usually a third class Contains a pointer into the data structure Usual methods would look like this: TYPE next(); TYPE previous(); void start(List &); bool done(); Copyright © 2004 – – Curt Hill
62
Copyright © 2004 – 2006 – Curt Hill
Notes An iterator may be uni-directional or bi-directional A singly linked list will not have bi-directional, nor the previous method If the list is sorted, key cannot be changed so the result of next is a copy If the list is not sorted returning a pointer would be OK Some handshaking would be in order Copyright © 2004 – – Curt Hill
63
Copyright © 2004 – 2006 – Curt Hill
Iterator Problems An iterator is sensitive to the fact that the list does not change A traversal does not have this problem Without threads a traversal is an indivisible operation The worst case is that the List changes the node that the iterator is about to examine This could result in exercising a pointer that is no longer valid or null Copyright © 2004 – – Curt Hill
64
Copyright © 2004 – 2006 – Curt Hill
Handshaking One solution to the iterator problem is that the data structure class and iterator class talk to each other The iterator tells the list that it is in an iteration The list tells the iterator that a change has been made The iterator may then abort the rest of the iteration or determine that it may continue The latter could be hard Copyright © 2004 – – Curt Hill
65
Copyright © 2004 – 2006 – Curt Hill
Windows Recall Microsoft Word or any other word processor On large documents only a window of the larger file is visible A window is a linear subset of the list Typically defined by two pointers or two iterators This is a handy thing to have when only a portion of the list needs examination Copyright © 2004 – – Curt Hill
66
Other variant straight lists
Doubly linked A previous pointer as well as a next pointer More work to insert and delete Much easier to go backwards Do not need the pair of pointers (lead and trail) because it is easy to go backwards The main class may have one or two pointers One pointer could point anywhere in list Copyright © 2004 – – Curt Hill
67
Copyright © 2004 – 2006 – Curt Hill
Application One obvious case where it is desirable to move forward or backward is a text editor Each line becomes an entry We then move forward and backward based on cursor keys In this case the key is the position in the list, much like an array subscript is a key Copyright © 2004 – – Curt Hill
68
Copyright © 2004 – 2006 – Curt Hill
Circular linked lists Instead of ending in a NULL the last item points at the first item Not usually used for keyed items, since keys really cannot be circular and properly conform to the < = > property that a key should compare Root may point at any item No real notion of a starting point Copyright © 2004 – – Curt Hill
69
How does this alter our routines?
Search Do not search for NULL (you will never find it) Search for the initial pointer Moving the root is OK Insert Empty list Make item point at itself Since we are not keyed, we choose the easiest case to insert: one past the current pointer Copyright © 2004 – – Curt Hill
70
Copyright © 2004 – 2006 – Curt Hill
Queues Again A queue can be handled with a circular list so we do not need two pointers Root points at the newest entry and root’s successor is the next one to exit Insertion always occurs after the root Root 1 2 3 Copyright © 2004 – – Curt Hill
71
Copyright © 2004 – 2006 – Curt Hill
Applications Memory manager Store free memory chunks on a list If the list is straight we always scan the front first It then tends to be loaded with small chunks that can not satisfy most requests Instead make circular and move the root pointer Minimizes average search Copyright © 2004 – – Curt Hill
72
Memory Chunk Sizes Straight List
Root 48 32 36 98 64 128 80 48 256 null Copyright © 2004 – – Curt Hill
73
Copyright © 2004 – 2006 – Curt Hill
Memory manager again In this application the list is in order by memory address Two addresses Lowest memory address and highest Class may contain two pointers Lowest memory Current memory Copyright © 2004 – – Curt Hill
74
Memory Manager Methods
Request memory (new) Start with current Find the first item large enough Remove it If some left over merely replace the length/starting address Return memory (delete) Use the lowest memory Merge adjacents if possible Copyright © 2004 – – Curt Hill
75
Linked lists that aren’t
Implemented with arrays and not heap Pointers are not needed Could use a subscript in an array for the "pointer" Works fine if and only if Only one type of data structure A suitable array maximum is found Seen in FORTRAN programs etc. Copyright © 2004 – – Curt Hill
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.