Download presentation
Presentation is loading. Please wait.
1
CSC212 Data Structure - Section BC
Lecture 9 Linked Lists Instructor: Zhigang Zhu Department of Computer Science City College of New York This lecture was modified from the 1997 presentation with the book, with new conventions provided in the second edition (2001) of the textbook - Z. Zhu
2
Motivation In a sequence using an array, inserting a new item needs to move others back... 10 20 30 ? 18
3
Motivation In a sequence using an array, inserting a new item needs to move others back... 10 20 30 ? 18
4
Motivation In a sequence using an array, inserting a new item needs to move others back... So the Big-O of the insert is O(n) 10 18 20 30 ?
5
Motivation How can we insert a new item without moving others ?
10 20 30 ? 18 We need a new data structure
6
Motivation How can we insert a new item without moving others ?
10 20 30 ? ? 18 break an array into a linked chain...
7
Motivation How can we insert a new item without moving others ?
10 20 30 ? ? 18 and then put the new item into the chain
8
Motivation How can we insert a new item without moving others ?
10 20 30 ? ? 18 But the links (->) need some way to build up
9
Linked Lists in Action Chapter 5 introduces the often-used data structure of linked lists. This presentation shows how to implement the most common operations on linked lists. This lecture shows three linked list operation in detail. The operations are: 1. Adding a new node at the head of a linked list. 2. Adding a new node in the middle of a linked list. 3. Removing a node from a linked list. The best time for this lecture is just after the students have been introduced to linked lists (Section 5.1), and before the complete linked list toolkit has been covered (Section 5.2). CHAPTER 5 Data Structures and Other Objects
10
Declarations for Linked Lists
Each node in the linked list is a class, as shown here. data link 15 class node { public: typedef int value_type; ... private: value_type data; node *link; }; data link 10 Here is a special class declaration that can be used to implement a linked list of integers, as described in Section 5.1 of the text. Note that in the firs Edition of the book, we have used a struct rather than a class. In a struct, members are public unless you specify otherwise. C++ programmers tend to use a struct only when all the members are public. data link 7 null
11
Declarations for Linked Lists
The data portion of each node is a type called value_type, defined by a typedef. 15 data class node { public: typedef int value_type; ... private: value_type data; node *link; }; link 10 data Within the struct, there is a type definition for a type called called "Item". The purpose of the Item data type is to tell us what kind of data resides in each of the nodes on the linked list. For example, if we want to create a linked list of real numbers, then we would declare typedef double Item; In this example, we want a linked list of integers, so we have declared typedef int Item; As you can see, the Item data type is used in the node declaration as the data type of a member variable called data. In the picture, I have drawn three nodes which might be part of a linked list of integers. The data portions of these nodes contain the integers 10, 15 and 7. 7 link data null link
12
Declarations for Linked Lists
Each node also contains a link field which is a pointer to another node. 15 data class node { public: typedef int value_type; ... private: value_type data; node *link; }; link 10 data Also inside each Node is a second member variable called link. The purpose of the link member variable is to contain a pointer to the next Node in the sequence of nodes. Question: What appears in the link field of the final node in a linked list such as this? Answer: A special pointer value called null or end marker, which means "This pointer doesn't point to anything." This makes sense because there is no node after the final node. 7 link data null link
13
Declarations for Linked Lists
A program can keep track of the first node by using a pointer variable such as head_ptr in this example. Notice that head_ptr itself is not a node -- it is a pointer to a node. data link 15 data link 10 When a linked list is implemented, we generally keep track of the first node by using a special pointer called the "head pointer". The head pointer points to the first node in the linked list. It is important to remember that head_ptr is not actually a node. It is just a single pointer, which points to the first actual node. data link 7 null head_ptr node * head_ptr;
14
Declarations for Linked Lists
A program can also keep track of the last node by using a pointer variable such as tail_ptr in this example. Notice that tail_ptr itself is not a node -- it is a pointer to a node. data link 15 data link 10 When a linked list is implemented, we generally keep track of the first node by using a special pointer called the "head pointer". The head pointer points to the first node in the linked list. It is important to remember that head_ptr is not actually a node. It is just a single pointer, which points to the first actual node. data link 7 null head_ptr node * head_ptr; node * tail_ptr; tail_ptr
15
Declarations for Linked Lists
A program can keep track of the first and the last nodes by using pointer variables such as head_ptr, tail_ptr. Notice that neither head_ptr nor tail_ptr is a node -- it is a pointer to a node. For an empty list, null is stored in both the head and the tail pointers. node * head_ptr; node * tail_ptr; head_ptr = NULL; tail_ptr = NULL; // NULL can be used for any pointers! Also remember that it is possible for a linked list to have no nodes at all. This situation is called the "empty list". Even with the empty list, we still have a head pointer, but the head pointer has no nodes to point to. So, instead of pointing to something, the head pointer of the empty list contains that special value, null. null null head_ptr tail_ptr
16
The Complete node Class Definition
The node class is fundamental to linked lists The private member variables data: a value_type variable link: a pointer to the next node The member functions include: A constructor Set data and set link Retrieve data and retrieve link
17
The Complete node Class Definition
class node { public: // TYPEDEF typedef double value_type; // CONSTRUCTOR node( const value_type& init_data = value_type( ), node* init_link = NULL ) { data = init_data; link = init_link; } // Member functions to set the data and link fields: void set_data(const value_type& new_data) { data = new_data; } void set_link(node* new_link) { link = new_link; } // Constant member function to retrieve the current data: value_type data( ) const { return data; } // Two slightly different member functions to retrieve // the current link: const node* link( ) const { return link; } node* link( ) { return link;} private: value_type data; node* link; }; default argument given by the value_type default constructor The node class is fundamental to linked lists The private member variables data_field link_field The member functions include: A constructor Set data and set link Retrieve data and retrieve link Please read Section 5.1. for details about value_type() and two versions of the function link() Why TWO? p
18
A Small Quiz - Suppose a a program has built the linked list as shown, and head_ptr is a pointer to a node. What is the data type of *head_ptr? cout << (*head_ptr). data(); cout << head_ptr->data(); data link 15 data link 10 When a linked list is implemented, we generally keep track of the first node by using a special pointer called the "head pointer". The head pointer points to the first node in the linked list. It is important to remember that head_ptr is not actually a node. It is just a single pointer, which points to the first actual node. data link 7 null head_ptr
19
Linked List Toolkit Design Container Classes using Linked Lists
The use of a linked list is similar to our previous use of an array in a container class But storing and retrieving needs more work since we do not have that handy indexing => Linked List Toolbox using node class
20
The Workings of four functions
This lecture will show four functions: Compute the length of a linked list (code) Insert a new node at the head (code) Insert a node at any location (pseudo-code) Delete a node from the head (pseudo-code) Read Section 5.2 for other functions in the Toolbox will be used in container classes bag and sequence
21
Length of a Linked List size_t list_length(const node* head_ptr); We simply want to compute the length of the linked list, for example the one shown here. Note that list_length is not a member function of the node class 15 Well I am going to show 4 functions. In addition to the three insert/delete functions, I want to show how to traverse a linked list by looking at the function list_length. The parameter, head_ptr, is a pointer to the head node of the list, (e.g. with data 10), if the list is not empty. Otherwise it is a null pointer. Our implementation will use another pointer to step through the list, counting the nodes one at a time. 10 7 null head_ptr
22
Pseudo-code of list_length
size_t list_length(const node* head_ptr); Initialize the count to zero. Make cursor point to each node, starting at the head. Each time cursor points to a new node, add 1 to count. return count. 15 Well I am going to show 4 functions. In addition to the three insert/delete functions, I want to show how to traverse a linked list by looking at the function list_length. The parameter, head_ptr, is a pointer to the head node of the list, (e.g. with data 10), if the list is not empty. Otherwise it is a null pointer. Our implementation will use another pointer to step through the list, counting the nodes one at a time. 10 7 null count head_ptr
23
Pseudo-code of list_length
size_t list_length(const node* head_ptr); Initialize the count to zero. Make cursor point to each node, starting at the head. Each time cursor points to a new node, add 1 to count. return count. cursor 15 Well I am going to show 4 functions. In addition to the three insert/delete functions, I want to show how to traverse a linked list by looking at the function list_length. The parameter, head_ptr, is a pointer to the head node of the list, (e.g. with data 10), if the list is not empty. Otherwise it is a null pointer. Our implementation will use another pointer to step through the list, counting the nodes one at a time. 10 7 1 null count head_ptr
24
Pseudo-code of list_length
size_t list_length(const node* head_ptr); Initialize the count to zero. Make cursor point to each node, starting at the head. Each time cursor points to a new node, add 1 to count. return count. cursor 15 Well I am going to show 4 functions. In addition to the three insert/delete functions, I want to show how to traverse a linked list by looking at the function list_length. The parameter, head_ptr, is a pointer to the head node of the list, (e.g. with data 10), if the list is not empty. Otherwise it is a null pointer. Our implementation will use another pointer to step through the list, counting the nodes one at a time. 10 7 2 null count head_ptr
25
Pseudo-code of list_length
size_t list_length(const node* head_ptr); Initialize the count to zero. Make cursor point to each node, starting at the head. Each time cursor points to a new node, add 1 to count. return count. 15 Well I am going to show 4 functions. In addition to the three insert/delete functions, I want to show how to traverse a linked list by looking at the function list_length. The parameter, head_ptr, is a pointer to the head node of the list, (e.g. with data 10), if the list is not empty. Otherwise it is a null pointer. Our implementation will use another pointer to step through the list, counting the nodes one at a time. 10 7 3 null count cursor head_ptr
26
Pseudo-code of list_length
size_t list_length(const node* head_ptr); Initialize the count to zero. Make cursor point to each node, starting at the head. Each time cursor points to a new node, add 1 to count. return count. 15 Well I am going to show 4 functions. In addition to the three insert/delete functions, I want to show how to traverse a linked list by looking at the function list_length. The parameter, head_ptr, is a pointer to the head node of the list, (e.g. with data 10), if the list is not empty. Otherwise it is a null pointer. Our implementation will use another pointer to step through the list, counting the nodes one at a time. 10 7 3 null count head_ptr cursor
27
Real code of list_length: List Traverse
size_t list_length(const node* head_ptr) { const node *cursor; size_t count = 0; // step 1 for (cursor = head_ptr; cursor != NULL; cursor = cursor->link()) count++; // step 2 return count; // step 3 } 15 Well I am going to show 4 functions. In addition to the three insert/delete functions, I want to show how to traverse a linked list by looking at the function list_length. The parameter, head_ptr, is a pointer to the head node of the list, (e.g. with data 10), if the list is not empty. Otherwise it is a null pointer. Our implementation will use another pointer to step through the list, counting the nodes one at a time. Initialize the count to zero. Each time cursor points to a new node, add 1 to count. return count. 10 cursor 7 null head_ptr count
28
Real code of list_length: List Traverse
size_t list_length(const node* head_ptr) { const node *cursor; size_t count = 0; // step 1 for (cursor = head_ptr; cursor != NULL; cursor = cursor->link()) count++; // step 2 return count; // step 3 } 15 Well I am going to show 4 functions. In addition to the three insert/delete functions, I want to show how to traverse a linked list by looking at the function list_length. The parameter, head_ptr, is a pointer to the head node of the list, (e.g. with data 10), if the list is not empty. Otherwise it is a null pointer. Our implementation will use another pointer to step through the list, counting the nodes one at a time. Initialize the count to zero. Each time cursor points to a new node, add 1 to count. return count. 10 cursor 7 1 null head_ptr count
29
Real code of list_length: List Traverse
size_t list_length(const node* head_ptr) { const node *cursor; size_t count = 0; // step 1 for (cursor = head_ptr; cursor != NULL; cursor = cursor->link()) count++; // step 2 return count; // step 3 } 15 Well I am going to show 4 functions. In addition to the three insert/delete functions, I want to show how to traverse a linked list by looking at the function list_length. The parameter, head_ptr, is a pointer to the head node of the list, (e.g. with data 10), if the list is not empty. Otherwise it is a null pointer. Our implementation will use another pointer to step through the list, counting the nodes one at a time. Initialize the count to zero. Each time cursor points to a new node, add 1 to count. return count. 10 7 cursor 2 null head_ptr count
30
Real code of list_length: List Traverse
size_t list_length(const node* head_ptr) { const node *cursor; size_t count = 0; // step 1 for (cursor = head_ptr; cursor != NULL; cursor = cursor->link()) count++; // step 2 return count; // step 3 } 15 Well I am going to show 4 functions. In addition to the three insert/delete functions, I want to show how to traverse a linked list by looking at the function list_length. The parameter, head_ptr, is a pointer to the head node of the list, (e.g. with data 10), if the list is not empty. Otherwise it is a null pointer. Our implementation will use another pointer to step through the list, counting the nodes one at a time. cursor Initialize the count to zero. Each time cursor points to a new node, add 1 to count. return count. 10 7 3 null head_ptr count
31
Big-O of list_length Big-O: O (n) if length is n
size_t list_length(const node* head_ptr) { const node *cursor; size_t count = 0; for (cursor = head_ptr; cursor != NULL; cursor = cursor->link()) count++; return count; // step 3 } 15 Well I am going to show 4 functions. In addition to the three insert/delete functions, I want to show how to traverse a linked list by looking at the function list_length. The parameter, head_ptr, is a pointer to the head node of the list, (e.g. with data 10), if the list is not empty. Otherwise it is a null pointer. Our implementation will use another pointer to step through the list, counting the nodes one at a time. Big-O: O (n) if length is n 10 7 3 null head_ptr count cursor
32
Is list_length works for an empty list?
size_t list_length(const node* head_ptr) { const node *cursor; size_t count = 0; for (cursor = head_ptr; cursor != NULL; cursor = cursor->link()) count++; return count; } Well I am going to show 4 functions. In addition to the three insert/delete functions, I want to show how to traverse a linked list by looking at the function list_length. The parameter, head_ptr, is a pointer to the head node of the list, (e.g. with data 10), if the list is not empty. Otherwise it is a null pointer. Our implementation will use another pointer to step through the list, counting the nodes one at a time. cursor = head_ptr = NULL count = 0 cursor null head_ptr null count
33
The Workings of four functions
This lecture will show four functions: Compute the length of a linked list (code) Insert a new node at the head (code) Insert a node at any location (pseudo-code) Delete a node from the head (pseudo-code) Read Section 5.2 for other functions in the Toolbox will be used in container classes bag and sequence
34
Inserting a node at the Head
void list_head_insert(node*& head_ptr, const node::value_type& entry); We want to add a new entry, 13, to the head of the linked list shown here. Note that head_ptr is a reference node pointer 15 In this lecture, I'll show you the workings of three functions to manipulate linked lists. The first function is called head_insert. The purpose of the function is to insert a new entry at the front of a linked list. The first parameter is the head point of the linked list declared here as: Node*& head_ptr Notice that this is a pointer to a Node (Node*), but it is also a reference parameter (indicated by the “&”). The reason for the reference parameter is that the function will make the head pointer point to a new node (containing the new entry)--and we want the change to affect the actual head pointer back in the calling program. The new entry itself is the the second parameter, declared here as: const Node::Item& entry This is a const reference parameter because the function uses the new entry (for the data part of a new node), but the function does not change the value of the parameter. In a prototype of a function such as this, we must use the entire data type (Node::Item) and not just Item. In order to develop the function, we'll trace through a small example. In the example the new entry (number 13) is being added to a list which already has three entries (10, 15 and 7). 10 7 13 null entry head_ptr
35
Inserting a Node at the Head
void list_head_insert(node*& head_ptr, const node::value_type& entry); Create a new node, pointed to by a local variable insert_ptr. insert_ptr 15 The first step of the head_insert function is to create a new node. In order to create the new node, we need a local variable which I have called insert_ptr, which is a pointer to a node. Think of insert_ptr as being a "temporary insertion pointer" because we won't need it any more once the new node is actually placed in the list. The idea is to get insert_ptr to point to the newly-created node when this node is first created. Do you remember enough from Chapter 4 to know the C++ statement which will create the new node and point insert_ptr at this new node? 10 7 entry 13 null head_ptr
36
Inserting a Node at the Head
void list_head_insert(node*& head_ptr, const node::value_type& entry); insert_ptr = new node; insert_ptr 15 Here is the C++ statement: insert_ptr = new Node; The statement creates a new node, and points the local variable insert_ptr at this newly-created node. 10 7 entry 13 null head_ptr
37
Inserting a Node at the Head
void list_head_insert(node*& head_ptr, const node::value_type& entry); insert_ptr = new node; Place the data in the new node's data field. insert_ptr 13 15 Once the new node has been created, we need to place values in the new node's member variables. The first member variable is the new node's data field, where we are supposed to place a copy of the entry. Another question: Can you write the C++ statement which will copy the value of entry into the data field of the new node? The answer is on the next slide... 10 7 13 null entry head_ptr
38
Inserting a Node at the Head
void list_head_insert(node*& head_ptr, const node::value_type& entry); insert_ptr = new node; insert_ptr->data = entry; ? insert_ptr 13 What expression appears on the left side of the assignment statement ? 15 ...or at least most of the answer is on this slide! The assignment statement written here is copying entry into some location. What goes on the left side of the assignment statement? Your answer should refer to the data member variable of the newly-created node. 10 7 13 null entry head_ptr
39
Inserting a Node at the Head
void list_head_insert(node*& head_ptr, const node::value_type& entry); insert_ptr = new node; insert_ptr->data = entry; insert_ptr 13 But data is a private variable, so cannot be accessed by a non-member function 15 ...or at least most of the answer is on this slide! The assignment statement written here is copying entry into some location. What goes on the left side of the assignment statement? Your answer should refer to the data member variable of the newly-created node. 10 7 13 null entry head_ptr
40
Inserting a Node at the Head
void list_head_insert(node*& head_ptr, const node::value_type& entry); insert_ptr = new node; insert_ptr->data = entry; X insert_ptr 13 But data is a private variable, so cannot be accessed by a non-member function 15 ...or at least most of the answer is on this slide! The assignment statement written here is copying entry into some location. What goes on the left side of the assignment statement? Your answer should refer to the data member variable of the newly-created node. 10 7 13 null entry head_ptr
41
Inserting a Node at the Head
void list_head_insert(node*& head_ptr, const node::value_type& entry); insert_ptr = new node; insert_ptr->set_data(entry); insert_ptr 13 Instead, Set_data function is used since data_field is a private variable of the node class 15 Here is the full answer. The expression on the left of the assignment statement is: insert_ptr->data You can read an expression like this from left-to-right. The expression means 1. Start at the pointer named insert_ptr; 2. The -> is the “member selection operator,” used to select a member of the object that insert_ptr points to. 3. The particular member we selected is the member called data. 10 7 13 null entry head_ptr
42
Inserting a Node at the Head
void list_head_insert(node*& head_ptr, const node::value_type& entry); insert_ptr = new node; insert_ptr->set_data(entry); Connect the new node to the front of the list. insert_ptr 13 15 The third step of head_insert is to connect the new node to the rest of the existing list. In other words, we will place a pointer into the link member variable of the new node. Another question: Can you write the assignment statement to place this pointer into the link member variable of the newly-created node? 10 7 13 null entry head_ptr
43
Inserting a Node at the Head
void list_head_insert(node*& head_ptr, const node::value_type& entry); insert_ptr = new node; insert_ptr->set_data(entry); insert_ptr->set_link(head_ptr); insert_ptr 13 ? 15 Here is half of the assignment statement: insert_ptr->link = ____________ How do you fill in this blank? We want the pointer to be a pointer to the first node of the old linked list. And head_ptr is already a pointer to the first node of the old linked list. So... What will be the parameter ? 10 7 13 null entry head_ptr
44
Inserting a Node at the Head
void list_head_insert(node*& head_ptr, const node::value_type& entry); insert_ptr = new node; insert_ptr->set_data(entry); insert_ptr->set_link(head_ptr); insert_ptr 13 15 Here is half of the assignment statement: insert_ptr->link = ____________ How do you fill in this blank? We want the pointer to be a pointer to the first node of the old linked list. And head_ptr is already a pointer to the first node of the old linked list. So... The new node is linked to the node that head_ptr is pointing to. 10 7 13 null entry head_ptr
45
Inserting a Node at the Head
void list_head_insert(node*& head_ptr, const node::value_type& entry); insert_ptr = new node; insert_ptr->set_data(entry); insert_ptr->set_link(head_ptr); Make the head_ptr point to the new head of the linked list. insert_ptr 13 15 The head_insert function needs one last step: Making the head pointer point to the newly-created node. Again, this will be an assignment statement. Can you write the statement before I move to the next slide? 10 7 13 null entry head_ptr
46
Inserting a Node at the Head
void list_head_insert(node*& head_ptr, const node::value_type& entry); insert_ptr = new node; insert_ptr->set_data(entry); insert_ptr->set_link(head_ptr); head_ptr = insert_ptr; insert_ptr 13 15 The assignment statement is: head_ptr = insert_ptr; In English this means: "Make the head pointer point to the same place that insert_ptr is pointing." Or in other words: "Make the head pointer point to the newly-created node." 10 7 13 null entry head_ptr
47
Inserting a Node at the Head
void list_head_insert(node*& head_ptr, const node::value_type& entry); insert_ptr = new node; insert_ptr->set_data(entry); insert_ptr->set_link(head_ptr); head_ptr = insert_ptr; 13 15 When the head_insert function returns, the linked list will have a new node (containing 13). Notice that when the function finishes, the local variable named insert_ptr no longer exists. But the newly created node does still exist, and the head pointer points to the newly created node. One warning: You may have read about the dispose function in C++, which is used to destroy nodes. Never call dispose when you are adding a new node to a linked list! The only time that dispose is called is when you want to have fewer nodes, not when you want to have more nodes. When the function returns, the linked list has a new node at the head, containing 13. 10 7 null head_ptr
48
Inserting a Node at the Head
void list_head_insert(node*& head_ptr, const node::value_type& entry) { node *insert_ptr; insert_ptr = new node; insert_ptr->set_data(entry); insert_ptr->set_link(head_ptr); head_ptr = insert_ptr; } What is the Big-O of the head_insert function? Here's the complete declaration of the head_insert function. Can you find these things: -- the declaration of the local variable, insert_ptr -- the place where the new node is actually created? By the way, the word "created" is probably too strong a word. No new memory is actually created. What does happen is that a portion of memory is set aside for the new operator to use. This portion of memory is called the "heap". Whenever the new operator is called, part of the heap is provided for your new node. Linked List: O(1) cmp: Array: O(n)
49
Inserting a Node at the Head
void list_head_insert(node*& head_ptr, const node::value_type& entry) { node *insert_ptr; insert_ptr = new node; insert_ptr->set_data(entry); insert_ptr->set_link(head_ptr); head_ptr = insert_ptr; } Does the function work correctly for the empty list ? Before we finish the example, we should check one last thing. Does the function work correctly if the list is initially empty? In other words, if the head pointer is null, will the function manage to correctly add the first node of the list? We can check with an example...
50
Inserting a Node at the Head
void list_head_insert(node*& head_ptr, const node::value_type& entry) { node *insert_ptr; insert_ptr = new node; insert_ptr->set_data(entry); insert_ptr->set_link(head_ptr); head_ptr = insert_ptr; } Does the function work correctly for the empty list ? ...as shown here. In this example, the head pointer is null, and the new entry is 13. 13 null entry head_ptr
51
Inserting a Node at the Front
void list_head_insert(node*& head_ptr, const node::value_type& entry) { node *insert_ptr; insert_ptr = new node; insert_ptr->set_data(entry); insert_ptr->set_link(head_ptr); head_ptr = insert_ptr; } The first two statements of the function allocate a new node, and place the number 13 in the data field of the new node. insert_ptr 13 13 null entry head_ptr
52
Inserting a Node at the Head
void list_head_insert(node*& head_ptr, const node::value_type& entry) { node *insert_ptr; insert_ptr = new node; insert_ptr->set_data(entry); insert_ptr->set_link(head_ptr); head_ptr = insert_ptr; } The third statement of the function copies the value null from the head pointer to the link field of the new node, as shown in this slide. insert_ptr 13 13 null entry null head_ptr
53
Inserting a Node at the Head
void list_head_insert(node*& head_ptr, const node::value_type& entry) { node *insert_ptr; insert_ptr = new node; insert_ptr->set_data(entry); insert_ptr->set_link(head_ptr); head_ptr = insert_ptr; } The function's fourth statement makes the head pointer point to the new node. insert_ptr 13 13 entry null head_ptr
54
Inserting a Node at the Head
void list_head_insert(node*& head_ptr, const node::value_type& entry) { node *insert_ptr; insert_ptr = new node; insert_ptr->set_data(entry); insert_ptr->set_link(head_ptr); head_ptr = insert_ptr; } When the function returns, the linked list has one node, containing 13. So, as you can see, when the function finally returns, there is one node in the linked list, and the head pointer correctly points to the new node. In other words, our function works just fine, even if we are adding the first node to a previously empty list. 13 null head_ptr
55
Caution! Always make sure that your linked list functions work correctly with an empty list. This slide is just a warning: Always make sure that your linked list functions work sensibly with the empty list. If you run into a function that fails for the empty list, then you will need to modify the function by adding some special code to deal with a null head pointer. EMPTY LIST
56
Inserting a Node at the Head
void list_head_insert(node*& head_ptr, const node::value_type& entry) { node *insert_ptr; insert_ptr = new node; insert_ptr->set_data(entry); insert_ptr->set_link(head_ptr); head_ptr = insert_ptr; } Here's the complete declaration of the head_insert function. Can you find these things: -- the declaration of the local pointer variable, insert_ptr -- the place where the new node is actually created? -- data and link fields are filled -- head pointer points to the new node By the way, the word "created" is probably too strong a word. No new memory is actually created. What does happen is that a portion of memory is set aside for the new operator to use. This portion of memory is called the "heap". Whenever the new operator is called, part of the heap is provided for your new node. Q: Can you give an implementation with ONLY a single statement?
57
Inserting a Node at the Head
void list_head_insert(node*& head_ptr, const node::value_type& entry) { node *insert_ptr; insert_ptr = new node(entry, head_ptr); head_ptr = insert_ptr; } YES, we can use the constructor with parameters! // CONSTRUCTOR node( const value_type& init_data = value_type( ), node* init_link = NULL ) { data = init_data; link = init_link; } YES, we can use the constructor with parameters!
58
Inserting a Node at the Head
void list_head_insert(node*& head_ptr, const node::value_type& entry) { head_ptr = new node(entry, head_ptr); } YES, we can use the constructor with parameters! // CONSTRUCTOR node( const value_type& init_data = value_type( ), node* init_link = NULL ) { data = init_data; link = init_link; } and assign the return pointer of new directly to the head pointer !
59
Break
60
Declarations for Linked Lists
Each node also contains a link field which is a pointer to another node. 15 data class node { public: typedef int value_type; ... private: value_type data; node *link; }; link 10 data Also inside each Node is a second member variable called link. The purpose of the link member variable is to contain a pointer to the next Node in the sequence of nodes. Question: What appears in the link field of the final node in a linked list such as this? Answer: A special pointer value called null or end marker, which means "This pointer doesn't point to anything." This makes sense because there is no node after the final node. 7 link data null link
61
The Complete node Class Definition
class node { public: // TYPEDEF typedef double value_type; // CONSTRUCTOR node( const value_type& init_data = value_type( ), node* init_link = NULL ) { data = init_data; link = init_link; } // Member functions to set the data and link fields: void set_data(const value_type& new_data) { data = new_data; } void set_link(node* new_link) { link = new_link; } // Constant member function to retrieve the current data: value_type data( ) const { return data; } // Two slightly different member functions to retrieve // the current link: const node* link( ) const { return link; } node* link( ) { return link;} private: value_type data; node* link; }; default argument given by the value_type default constructor The node class is fundamental to linked lists The private member variables data_field link_field The member functions include: A constructor Set data and set link Retrieve data and retrieve link Please read Section 5.1. for details about value_type() and two versions of the function link() Why TWO? p
62
Big-O of list_length Big-O: O (n) if length is n
size_t list_length(const node* head_ptr) { const node *cursor; size_t count = 0; for (cursor = head_ptr; cursor != NULL; cursor = cursor->link()) count++; return count; // step 3 } 15 Well I am going to show 4 functions. In addition to the three insert/delete functions, I want to show how to traverse a linked list by looking at the function list_length. The parameter, head_ptr, is a pointer to the head node of the list, (e.g. with data 10), if the list is not empty. Otherwise it is a null pointer. Our implementation will use another pointer to step through the list, counting the nodes one at a time. Big-O: O (n) if length is n 10 7 3 null head_ptr count cursor
63
The Workings of four functions
This lecture will show four functions: Compute the length of a linked list (code) Insert a new node at the head (code) Insert a node at any location (pseudo-code) Delete a node from the head (pseudo-code) Read Section 5.2 for other functions in the Toolbox will be used in container classes bag and sequence
64
Pseudocode for Inserting Nodes
Nodes are often inserted at places other than the front of a linked list. There is a general pseudocode that you can follow for any insertion function. . . That's the end of our head_insert function. There are two more linked list functions that we'll look at today. Actually, we'll just look at typical pseudocode for the next two functions. The first of these functions is a function for inserting a new node at a place other than the front of a linked list. Actually, the pattern that we'll follow will be capable of inserting a new node at any location in a linked list: Maybe at the front, maybe in the middle, maybe at the end. For example, you might be keeping the nodes sorted from smallest integer to largest integer. Or perhaps there is some other method to your insertions. The pseudocode that I'll describe will work for any method that you might think of. Really!
65
Pseudocode for Inserting Nodes
Determine whether the new node will be the first node in the linked list. If so, then there is only one step: list_head_insert(head_ptr, entry); The first step of the pseudocode is to determine whether the new node will be inserted as the first node of the linked list. If so, then you can simply call the head_insert function which we already wrote, as shown here.
66
Pseudocode for Inserting Nodes
Determine whether the new node will be the first node in the linked list. If so, then there is only one step: list_head_insert(head_ptr, entry); The function we already wrote There are three parts to calling the function we already wrote. First, of course, is the function name: head_insert.
67
Pseudocode for Inserting Nodes
Determine whether the new node will be the first node in the linked list. If so, then there is only one step: A pointer to the head of the list list_head_insert(head_ptr, entry); Next is the first argument, which is the pointer to the head of the linked list.
68
Pseudocode for Inserting Nodes
Determine whether the new node will be the first node in the linked list. If so, then there is only one step: list_head_insert(head_ptr, entry); The data to put in the new node And finally is the data for the new node. So, this function call will add the new data at the front of an existing linked list.
69
Pseudocode for Inserting Nodes
Otherwise (if the new node will not be first): Start by setting a pointer named previous_ptr to point to the node which is just before the new node's position. On the other hand, if the new data does not belong at the front of the linked list, then you will start by setting up a pointer that I call previous_ptr. This pointer must be set up to point to the node which is just before the new node's position.
70
Pseudocode for Inserting Nodes
Otherwise (if the new node will not be first): Start by setting a pointer named previous_ptr to point to the node which is just before the new node's position. In this example, the new node will be the second node 10 As an example, suppose that we want to add 13 to this list, and we want to keep all the entries in order from largest to smallest. We don't want to put 13 first on this list, because 13 is smaller than 15. So, we proceed to set up the previous_ptr to point to the node which is just before the position where 13 should be inserted. In this example, previous_ptr would be set up to point to the first node of the linked list (containing 15). The 13 will be inserted as the new second node of the list (after the 15, but before the 10). previous_ptr 15 7 null head_ptr
71
Pseudocode for Inserting Nodes
Otherwise (if the new node will not be first): Start by setting a pointer named previous_ptr to point to the node which is just before the new node's position Look at the pointer which is in the node *previous_ptr 10 In order to insert the new node at the proper place, we need to examine the link field which is in the node pointed to by previous_ptr. This link field is highlighted in the picture. Question: What is the name of this link field? Can you write the answer before I move to the next slide? previous_ptr 15 7 What is the name of this pointer ? null head_ptr
72
Pseudocode for Inserting Nodes
Otherwise (if the new node will not be first): Start by setting a pointer named previous_ptr to point to the node which is just before the new node's position This pointer is called previous_ptr->link 10 As you see, the highlighted pointer is called previous_ptr->link. In other words: Start at previous_ptr, follow the pointer, and select the link field from the record. There is a reason that previous_ptr->link is important to us... previous_ptr 15 7 Always remember how can you access link null head_ptr
73
Pseudocode for Inserting Nodes
Otherwise (if the new node will not be first): Start by setting a pointer named previous_ptr to point to the node which is just before the new node's position previous_ptr->link points to the head of a smaller linked list, with 10 and 7 10 ...as you can see here, previous_ptr->link actually points to the first node of a small linked list. The small linked list contains 10 and 7 -- and more important, we want to add the new entry at the front of this small linked list. previous_ptr 15 7 null head_ptr
74
Pseudocode for Inserting Nodes
Otherwise (if the new node will not be first): Start by setting a pointer named previous_ptr to point to the node which is just before the new node's position. 13 The new node must be inserted at the head of this small linked list. 10 Here is a small challenge: Can you write just one C++ statement which will insert the new node at the front of the small linked list? Use the name entry for the name of the data that you are placing in the new node... ...think about what functions you already have... previous_ptr 15 7 Write one C++ statement which will do the insertion. null head_ptr
75
Pseudocode for Inserting Nodes
Otherwise (if the new node will not be first): Start by setting a pointer named previous_ptr to point to the node which is just before the new node's position. 13 X 10 list_head_insert(previous_ptr->link, entry); Did anyone come up with this solution? By calling the head_insert function, we can insert entry at the front of the small linked list. The key is that we have the pointer previous_ptr->link which points to the head of the small linked list. previous_ptr 15 private variable?!! 7 Write one C++ statement which will do the insertion. null head_ptr
76
Pseudocode for Inserting Nodes
Otherwise (if the new node will not be first): Start by setting a pointer named previous_ptr to point to the node which is just before the new node's position. 13 sl_head_ptr node *sl_head_ptr; sl_head_ptr = previous_ptr->link(); list_head_insert(sl_head_ptr, entry); previous_ptr->set_link(sl_head_ptr); 10 More precisely, you need to use member function link() as the argument, this also set the link of the node *previous_ptr !!! That’s because in the list_head_insert function, previous_ptr More precisely, you need to use member function link() , and have three lines of code 15 7 null head_ptr
77
Pseudocode for Inserting Nodes
Otherwise (if the new node will not be first): Start by setting a pointer named previous_ptr to point to the node which is just before the new node's position. 13 sl_head_ptr node *sl_head_ptr; sl_head_ptr = previous_ptr->link(); list_head_insert(sl_head_ptr, entry); previous_ptr->set_link(sl_head_ptr); 10 More precisely, you need to use member function link() as the argument, this also set the link of the node *previous_ptr !!! That’s because in the list_head_insert function, previous_ptr More precisely, you need to use member function link() , and have three lines of code 15 7 null head_ptr
78
Pseudocode for Inserting Nodes
Otherwise (if the new node will not be first): Start by setting a pointer named previous_ptr to point to the node which is just before the new node's position. 13 sl_head_ptr node *sl_head_ptr; sl_head_ptr = previous_ptr->link(); list_head_insert(sl_head_ptr, entry); previous_ptr->set_link(sl_head_ptr); 10 More precisely, you need to use member function link() as the argument, this also set the link of the node *previous_ptr !!! That’s because in the list_head_insert function, previous_ptr More precisely, you need to use member function link() , and have three lines of code 15 7 null head_ptr
79
Pseudocode for Inserting Nodes
Determine whether the new node will be the first node in the linked list. If so, then there is only one step: list_head_insert(head_ptr, entry); Otherwise (if the new node will not be first): Set a pointer named previous_ptr to point to the node which is just before the new node's position. Do the following : Here is the complete pseudocode for adding a new node. Remember: this pseudocode can be used for many different methods of inserting, such as keeping nodes in order from largest to smallest. node *sl_head_ptr; sl_head_ptr = previous_ptr->link(); list_head_insert(sl_head_ptr, entry); previous_ptr->set_link(sl_head_ptr);
80
Pseudocode for Inserting Nodes
The process of adding a new node in the middle of a list (only the step after previous_ptr has been set) can also be incorporated as a separate function. This function is called list_insert in the linked list toolkit of Section 5.2. Challenge yourself: The textbook actually gives you a different implementation (p 235, 4 lines of code) Can you implement list_insert with just one line of code? Don’t use list_head_insert See Self-Test Ex 16 Section 5.2 gives a collection of function for manipulating linked lists. One of these functions, called list_insert, places a new node in the middle of a linked list.
81
The Workings of four functions
This lecture will show four functions: Compute the length of a linked list (code) Insert a new node at the head (code) Insert a node at any location (pseudo-code) Delete a node from the head (pseudo-code) Read Section 5.2 for other functions in the Toolbox will be used in container classes bag and sequence
82
Pseudocode for Removing Nodes
Nodes often need to be removed from a linked list. As with insertion, there is a technique for removing a node from the front of a list, and a technique for removing a node from elsewhere. We’ll look at the pseudocode for removing a node from the head of a linked list. Do you have energy for one more function? Or at least for some pseudocode. I’ll just show you how to remove a node from the front of a linked list. You can figure out the code for removing other nodes, or you can read the solution in Section 5.2.
83
Removing the Head Node Start by setting up a temporary pointer named remove_ptr to the head node. As we did before, we'll use an example to illustrate the pseudocode. In the example, we want to delete the head node which contains 13. The first part of the pseudocode sets up a local variable named remove_ptr to point to the node that we want to remove. remove_ptr 13 10 15 7 null head_ptr
84
Removing the Head Node Set up remove_ptr. head_ptr = remove_ptr->link(); Draw the change that this statement will make to the linked list. Since we are removing the first node of the list, we need to change the place where head_ptr is pointing. Can you tell me where the head_ptr will point after the assignment statement that is shown here? Be quick, because I am about to change the slide... remove_ptr 13 10 15 7 null head_ptr
85
Removing the Head Node Set up remove_ptr.
head_ptr = remove_ptr->link(); As you can see, the assignment statement makes the head pointer point to the second node of the list. remove_ptr 13 10 15 7 null head_ptr
86
Removing the Head Node Set up remove_ptr.
head_ptr = remove_ptr->link; delete remove_ptr; // Return the node's memory to heap. There is one last statement that the removal function should execute: delete remove_ptr; This takes the node which is pointed to by remove_ptr and returns it to the heap, so that the memory can be reused at some later date. If you forget this step, then the memory won't be able to be reused -- a situation that's called a "heap leak". Remember this rule of thumb: If you are adding a node to a linked list, then make sure that new ... is called exactly once. If you are removing a node from a linked list, then make sure that delete ... is called exactly once. remove_ptr 13 10 15 7 null head_ptr
87
Removing the Head Node Here’s what the linked list looks like after the removal finishes. Notice that the local variable, remove_ptr, is no longer around. 10 15 7 null head_ptr
88
Summary It is easy to insert a node at the front of a list.
The linked list toolkit also provides a function for inserting a new node elsewhere It is easy to remove a node at the front of a list. The linked list toolkit also provides a function for removing a node elsewhere--you should read about this function and the other functions of the toolkit. A quick summary . . .
89
Key points you need to know
Toolkit Code Linked List Toolkit uses the node class which has set and retrieve functions The functions in the Toolkit are not member functions of the node class length, insert(2), remove(2), search, locate, copy,... compare their Big-Os with similar functions for an array They can be used in various container classes, such as bag, sequence, etc.
90
Homework... Self-Test Exercises (node) Read after class
1-12 Read after class Linked List ToolKit (Section 5.2) Do Self-Test Ex Read before the next lecture Section
91
THE END Presentation copyright 1997, Addison Wesley Longman,
For use with Data Structures and Other Objects Using C++ by Michael Main and Walter Savitch. Some artwork in the presentation is used with permission from Presentation Task Force (copyright New Vision Technologies Inc) and Corel Gallery Clipart Catalog (copyright Corel Corporation, 3G Graphics Inc, Archive Arts, Cartesia Software, Image Club Graphics Inc, One Mile Up Inc, TechPool Studios, Totem Graphics Inc). Students and instructors who use Data Structures and Other Objects Using C++ are welcome to use this presentation however they see fit, so long as this copyright notice remains intact. Feel free to send your ideas to: Michael Main THE END
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.