CSCI 123 Introduction to Programming Concepts in C++ Lecture 1staff · 13.1 Nodes and Linked Lists...
Transcript of CSCI 123 Introduction to Programming Concepts in C++ Lecture 1staff · 13.1 Nodes and Linked Lists...
CSCI 123 INTRODUCTION TO PROGRAMMING CONCEPTS IN C++
Brad Rippe
Link Lists, Stacks, and Queues
Overview
13.1 Nodes and Linked Lists
13.2 Stacks and Queues
13.1
Nodes and Linked Lists
10 12 14 endhead
Nodes and Linked Lists
A linked list is a list that can grow and shrink while the program is running
A linked list is constructed using pointers
A linked list often consists of structs or classes that contain a pointer variable connecting them to other dynamic variables
A linked list can be visualized as items, drawn as boxes, connected to other items by arrows
Nodes
The boxes in the previous drawing represent the nodes of a linked list
Nodes contain the data item(s) and a pointer that can point to another node of the same type
The pointers point to the entire node, not an individual item that might be in the node
The arrows in the drawing represent pointers PointerPointer Pointer
Nodes
HEAD
Nodes are implemented in C++ as structs or classes Example: A structure to store two data items and
a pointer to another node of the same type,along with a type definition might be:
struct Node {string data; Node *next;
};
typedef Node* NodePtr;
This circular definitionis allowed in C++
Implementing Nodes
The head of a List
The box labeled head, is not a node, but a pointer variable that points to a node
Pointer variable head is declared as:
NodePtr head;
Pointer-Based Linked Lists
Executing the statement
head = new Node
before
head = NULL
will result in a lost cell
Accessing Items in a Node
This one way to change the string in the first node from “Nissan 350z” to “Porsche 911”:
(*head).data = “Porsche 911”;
head is a pointer variable so *head is the node that head points to
The parentheses are necessary because the dot operator . has higher precedence than the dereference operator *
SimpleLinkList.cpp
The Arrow Operator
The arrow operator -> combines the actions of the dereferencing operator * and the dot operator to specify a member of a struct or object pointed to by a pointer
(*head). data = “Porsche 911”;can be written as
head->data = “Porsche 911”;
The arrow operator is more commonly used
NULL
The defined constant NULL is used as…
An end marker for a linked list
A program can step through a list of nodes by following the pointers, but when it finds a node containing NULL, it knows it has come to the end of the list
The value of a pointer that has nothing to point to
The value of NULL is 0 (zero)
Any pointer can be assigned the value NULL:int *p = NULL;
To Use NULL
A definition of NULL is found in several libraries, including <iostream> and <cstddef>
A using directive is not needed for NULL
Linked Lists A linked list is a list of nodes in which each
node has a member variable that is a pointer that points to the next node in the list
The first node is called the head
The pointer variable head, points to the first node
The pointer named head is not the head of the list…it points to the head of the list
The last node contains a pointer set to NULL
PointerPointer Pointer
Nodes
HEAD
NULL Comparison
cur->next – incorrect
When cur points to the last node of nonempty list cur->next is NULL
The loop would terminate before displaying the data in the last node
for (NodePtr cur = head; cur != NULL; cur = cur->next)
cout << cur->data << endl;
Link List Classstruct Node {
string data;
Node *next;
}; typedef Node* NodePtr;
class LinkList {
public: LinkList();
~LinkList();
void insert(const string& aData);
bool insert(const string& aData1, const string& aData2);
NodePtr search(const string& target) const;
void deleteNode(const string& aData);
int getSize() const;
private:
NodePtr mHead; // users don't have access to the
int mSize;
};
First Function insert
It would be better to create a function to insertnodes at the head of a list, such as:
void insert(const string& aData); The first parameter is a string parameter that the data element
for the node
insert() will create a new node for the string The string will be copied to the new node
The new node will be inserted in the list as the new head node
Pseudocode for insert()
Create a new dynamic variable pointed to by aNode
Place the string in the new aNode->data
Make aNode’s next pointer variable point to the head node (now it will point to the original first node in the list)
Make the head pointer point to aNode
next
Translating insert() to C++
The pseudocode for head_insert can be writtenin C++ using these lines in place of the lines of pseudocode:
// Construct a new node
NodePtr aNode = new Node;
aNode->data = aData; // set data string to the // node’s data
aNode->next = head; // set next pointer to head
head = aNode; // now head pts to the first
// element aNode
An Empty List
A list with nothing in it is called an empty list
An empty linked list has no head node
The head pointer of an empty list is NULL
head = NULL;
Any functions written to manipulate a linked listshould check to see if it works on the empty list
You might be tempted to write insert() usingthe head pointer to construct the new node:
head = new Node;head->data = aData;
Now to attach the new node to the list
The node that head used to point to is now lost!
Losing Nodes
“Data String”
“Original”
“Last Node”
Memory Leaks
Nodes that are lost by assigning their pointers a new address are not accessible any longer
The program has no way to refer to the nodesand cannot delete them to return their memoryto the freestore (Heap)
Programs that lose nodes have a memory leak
Significant memory leaks can cause system crashes
Searching a Linked List
To design a function that will locate a particular node in a linked list:
We pass in a NULL NodePtr and set it to the node with the data we’re looking for
The data (string) we wish to find is the other argument
This declaration will work:
void search(NodePtr& cur, const string& target) const
Revised 4/25
Refining our function
We will use a pointer variable, named cur, to move through the list checking for the target
The only way to move around a linked list is to follow pointers
We will start with here pointing to the first node and move the pointer from node to node following the pointer out of each node
Function search
Pseudocode for search
Parameter pointer variable cur point to the head node
while(cur does not point to the last node) {check if cur data is the target if so, set cur to the node with the data we are looking
for and return}
cur = NULL; // if the data is not found set cur to NULL
Revised 4/25
Moving Through the List
The pseudocode for search requires that pointer cur step through the list
How does cur follow the pointers from node to node?
When cur points to a node, cur->next is theaddress of the next node
To make cur point to the next node, make the assignment:
cur = cur->next;
A code for search
The search function can be refined in this way:
void LinkList::search(NodePtr& cur, const string& target) const {
// transverse the list till we find what we are looking for
for(cur = mHead; cur != NULL; cur = cur->next) {
if(cur->data == target) {
return; // found the node, return
}
}
// if the target is not found we set cur to NULL
cur = NULL;
}
Revised 4/25
Does the search algorithm handle the empty list
If the list is empty, and the pointer is not handled appropriately it can lead to undefined pointer errors
cur->data is undefined
cur->next is undefined
The search function that handles an empty list
Searching an Empty List
Pointers as Iterators
An iterator is a construct that allows you to cycle through the data items in a data structureto perform an action on each item
An iterator can be an object of an iterator class, an array index, or simply a pointer
A general outline using a pointer as an iterator:
for (NodePtr cur = head; cur != NULL; cur = cur->next)
//perform the action on the node iter
head is a pointer to the head node of the list
This is what the search algorithm uses to transverse each node
Inserting a Node after a node
To insert a node after a specified node in the linked list:
Use cur again and iterator through the list to find the node with the data (aData1) we’re looking for
Construct a new node to place the new string (aData2)
Point the new node’s next pointer to cur->next
Set cur->next to the new node
bool insert(const string& aData1, const string& aData2);
Inserting the New Node
Function insert creates the new node just as previous insert did
We do not want our new node at the head of the list however, so…
We use the pointer cur to insert the new node
head
cur
A
2
B
2
D
2
E
0
C
Inserting the New Node
This code will accomplish the insertion of the new node,after the node pointed to by cur:
aNode->next = cur->next;
cur->next = aNode;
Assume we are looking to Insert “C” after “B”
The order of pointer assignments is critical
If we changed cur->next to point to aNode first, we would loose the rest of the list!
Caution!
insert() - CodeNodePtr cur = mHead;
bool found = false;
while(cur != NULL) {
if(cur->data == aData1) {
found = true;
break;
}
cur = cur->next; // go to the next node and test
}
if(found) {
NodePtr aNode = new Node;
aNode->data = aData2; // set the data to the string
aNode->next = cur->next; // set next ptr to the node after cur
cur->next = aNode; // set cur to point to the new node
mSize++;
}
return false;
LinkList.h & LinkList.cpp
Function insert Again
Notice that inserting into a linked list requires that you only change two pointers
This is true regardless of the length of the list
Using an array for the list would involve copying as many as all of the array elements to new locations to make room for the new item
Inserting into a linked list is often more efficient than inserting into an array
To remove a node from a linked list
Position a pointer, prevPtr, to point at the node prior to the node to remove
Position a pointer, targetPtr, to point at the nodeto remove
Perform: prevPtr->next = target->next;
The node is removed from the list, but is still in memory
Return targetPtr to the freestore: delete targetPtr;
Removing a Node
deleteNode()NodePtr targetPtr = mHead;
NodePtr prevPtr = NULL; // no previous for the first node
if(targetPtr == NULL)
return;
for(;targetPtr != NULL;) {
if(targetPtr->data == aData) {
if(prevPtr == NULL) {
mHead = targetPtr->next;
} else {
prevPtr->next = targetPtr->next;
}
delete targetPtr;
targetPtr = NULL;
mSize--;
} else {
prevPtr = targetPtr;
targetPtr = targetPtr->next;
}
}
Deleting and adding Nodes
The best way to understand how a link list works is to draw the nodes out on paper
Trace through your code and determine if it is handling the situations appropriately
Remember a picture is worth a thousand words
Assignment With Pointers
If head1 and head2 are pointer variables and head1 points to the head node of a list:
head2 = head1;causes head2 and head1 to point to the same list
There is only one list!
If you want head2 to point to a separate copy,you must copy the list node by node oroverload the assignment operator appropriately
Section 13.1 Conclusion
Can you
Write type definitions for the nodes and pointers in a linked list? Call the node type NodeType and call the pointer type PointerType. The linked lists will be lists of letters.
Explain why inserting into an array can be less efficient than inserting into a linked list?
13.2
Stacks and Queues
A stack is a data structure that retrieves data inthe reverse order the data was stored If 'A', 'B', and then 'C' are placed in a stack, they
will be removed in the order 'C', 'B', and then 'A‘
A stack is a last-in/first-out (LIFO) data structure like the stack of plates in a cafeteria; adding a plate pushes down the stack and the top plate is the first one removed
A Linked List Application
We will create a stack class to store characters
Adding an item to a stack is pushing onto the stack
Member function push will perform this task
Removing an item from the stack is popping the theitem off the stack
Member function pop will perform this task
Program Example:StackRunner.cpp
StackRunner.cpp, Stack.h and Stack.cpp demonstrates the use of the stack class
Using the Stack Class
Function push
The push function adds an item to the stack It uses a parameter of the type stored in the stack
void push(const string& aString);
Pushing an item onto the stack is precisely the same task accomplished by function insert() of the linked list
For a stack, a pointer named top is used instead of a pointer named head
Function pop
The pop function returns the item that was at the top of the stack
string pop(); Before popping an item from a stack, pop checks
that the stack is not empty
pop stores the top item in a local variable data, and the item is "popped" by: top = top->next;
A temporary pointer must point to the old top item so it can be "deleted" to prevent a memory leak in a variable called, “frame”
pop then returns variable data which is the string that was at the original top
Empty Stack
An empty stack is identified by setting thetop pointer to NULL
top = NULL;
The Copy Constructor
Because the stack class uses a pointer andcreates new nodes using new, a copy constructor is needed
The copy constructor must make a copy of each item in the stack and store the copies in a new stack
Items in the new stack must be in the same position in the stack as in the original
What happens if we don’t define a copy constructor?
The stack destructor
Because function pop calls delete each time anitem is popped off the stack, ~Stack only needs to call pop until the stack is empty
while(!isEmpty()) {
pop();
}
top = NULL;
The stack class implementation is found in Stack.cpp
Stack Class Implementation
Queue
A queue is a first in/first out (FIFO) data structure
It utilizes two pointers one at the front of the queue and one at the back of the queue
We’ll define them as front and back
Queue declaration
class Queue {
public:
Queue();
Queue(const Queue& aQueue);
~Queue();
void enqueue(const string& aString);
string dequeue();
bool isEmpty() const;
friend ostream& operator <<(ostream& out, const Queue& aQueue);
private:
QueueNodePtr front;
QueueNodePtr back;
};
Section 13.2 Conclusion
Can you
Give the definition of member function push?
Create a definition for the stack class copy constructor?
Other Resources
Does C++ have stacks, queues and lists? STL (Standard Template Library) contains stacks,
queues and lists containers
Should you implement your own stacks, queues and lists? Yes! The best way to learn is by doing it. Copy code
initially, step through the code, and make sure you understand what is happening.
What happens if you pass variables by value?
What happens if you pass variables by reference?
What constructors are called?
Additional Information
You will see additional data structures in your data structures courses
You will evaluate these structures more in depth
This course is providing a brief introduction to some of the data structures, however, your data structures will get more detail
You can get more information at
http://cs.fiu.edu~weiss