Professional Documents
Culture Documents
Lec13. Linked List
Lec13. Linked List
– Deletions of students
– Writes to disk
16-3
Singly Linked List
• We now explore the implementation of an alternate sequence,
known as the singly linked list
• A linked list, in its simplest form, is a collection of nodes that
together form a linear ordering
• What would happen if we had a class that declared one of its own
type as a field?
class Strange {
public:
name Other
string name;
“Adam”
Strange *other;
};
• Strange object has two fields:
− One can store a single string name
− One is a pointer to another Strange object.
• We can use it to store a list of string values
A list node class
• List Node: a single element/object of a list structure.
• Each node contains its own data.
• Each list node object stores data and pointer(s):
– data can be of any primitive types or object of any class, etc.
– pointer (usually called next) is an object address that points to the next node
in the list.
Pseudocode
Class ListNode Data portion of Node
dataType data1;
dataType data2;
• ? Will be replaced with a reference to a node which means this box does not have
data or next field.
• We do not have the actual node yet. To have it, we should call new:
elem next
list = new IntNode(); list 0
• .
IntNode default construct initializes the fields as:
– Data initialized to 0
– Next initialized to null ( in these slides / indicates null)
#include <iostream>
using namespace std;
class IntNode {
public: List node
int elem;
IntNode* next; tester
IntNode();
}; example
int main() {
IntNode *list;
list = new IntNode();
list->elem = 42;
list->next = new IntNode();
list->next->elem = -3;
list->next->next = new IntNode();
list->next->next->elem = 17;
cout << list->elem;
cout <<" " << list->next->elem;
cout <<" " << list->next->next->elem;
}
IntNode::IntNode():elem (0), next(NULL){}
42
Output 42 -3 17
List node with constructor, private data, friends
#include <iostream>
using namespace std;
class IntNode {
private:
int elem;
IntNode* next;
public:
IntNode();
IntNode(int elem);
friend void manipulateList(IntNode *p);
};
int main() {
IntNode *list;
manipulateList(list);
}
42 -3 null
Output 42 -3 17
Pointers vs. objects
variable = value; //assume left side is a pointer variable, right can be an address
null
a variable (left side of = ) is an arrow (the base of an arrow)
a value (right side of = ) is an object (a box; what an arrow points at)
• For the list at right: ele nex
– q = a->next; p m t
2
means to make q point at 20
– a->next = p; 1 ele nex 2 ele nex
a m m
means to adjust where points t1 t
Reassigning references 10 20
• a->next = b->next; q
– "Make the variable a->next refer to the
same value as b->next." elem next elem next
a
– Or, "Make a->next point to the same 10 20
place that b->next points."
elem next elem next
b
30 40
Traversing a list?
• Suppose we have a long chain of list nodes:
InLinkedtList
IntNode IntNode IntNode
head ele nex ele nex ele nex
empty() m t m t m t
addFront(value)
front() 42 -3 17
removeFront(i)
showList()
A IntLinkedList class
class IntNode {
private:
int elem;
IntNode* next;
public:
IntNode();
IntNode(int data);
friend class IntLinkedList;
};
class IntLinkedList {
private:
IntNode *head;
public:
IntLinkedList();
~IntLinkedList();
void addFront(int value); // add to front of list
bool empty() const; // is list empty?
int front() const; // get front element
void removeFront(); // remove front item list
void showList();
};
Adding to an empty list or to its front
• Before adding -3, list is empty:
head ele next
m
head -3
ele next
v m
42
– To add -3, we must create a new node and attach it to the list.
head = new IntNode(-3);
– To add 42 to the front, we must create a new node and attach it
to the list.
IntNode *v = new IntNode(42);
v->next = head;
head = v;
void IntLinkedList::addFront(int value){
IntNode *v = new IntNode(value);
v->next = head;
head = v;
}
Getting/removing the front node
• To get the front node element: return head->elem
ele next ele next ele next
m m m
head
42 -3 17
int IntLinkedList::front() const {
return head->elem;
}
v
ele next ele next ele next
m m m
head
42 -3 17
Check If a list is empty and print a list
• To check if a list is empty or not just we check the head
return (head==NULL); bool IntLinkedList::empty() const{
return (head==NULL);
}
16-19
Construct and destruct
• To check if a list is empty or not just we check the head
IntLinkedList::IntLinkedList():head(NULL) {}
IntLinkedList *list;
list = new IntLinkedList();
List->addFront(5);
list head ele next
m
empty()
addFront(value) 5
front()
removeFront(i)
show()
void IntLinkedList::removeFront(){
IntNode *v = head;
head = head->next;
delete v;
v=NULL;
}
void IntLinkedList::showList() {
IntNode *v = head;
while (v!=NULL){
cout << v->elem << " ";
v=v->next;
}
}
int main() {
IntLinkedList *list = new IntLinkedList();
list->addFront(43);
list->addFront(143);
list->addFront(243);
list->showList();
list head
ele next
empty() ele next m
addFront(value)
ele next m
front() m 43
removeFront(i) 143
show() 243
Implementing Singly Linked List of String Nodes
• Similar to what we have done with IntNode and IntLinkedNode, we define
two classes StringNode and StringLinkedList
– member elem in StringNode stores the element stored in this node, which in this
case is a string and memember next stores a pointer to the next node
– We make StringLinkedList class a friend to StringNode, so that it can access
the StringNode’s private members
class StringNode { // a node in a list of strings
private:
string elem; // element value
StringNode* next; // next item in the list
friend class StringLinkedList; // provide StringLinkedList access
};
StringLinkedList::~StringLinkedList(){ // destructor
while (!empty()) removeFront();
}
template <class> class SLinkedList; //you add this line to let SNode become aware of
int main() {
SLinkedList<string> list;
string first = "Laure";
list.addFront("kkkk");
list.addFront(first);
cout <<endl<<list.front();
SLinkedList<int> *list1 = new SLinkedList<int>();
list1->addFront(1);
list1->addFront(6);
list1->showList();
cout <<endl<<list1->front();
}
Arrays vs. Linked Lists
CMPS 212 29
Adding to the tail of the list
• Consider following list:
data next data next
head 42 -3
data next
current v 17
– To add a node, we must modify the next pointer of the node before the
place you want to add/change
IntNode *v = new IntNode(17);
IntNode current = head;
while (current->next != null) {
current = current->next;
}
current->next = v; void IntLinkedList::addEnd(int value){
IntNode *v = new IntNode(value);
if (head==NULL)
head=v;
else{
IntNode *current = head;
while (current->next!=NULL){
current=current->next;
}
current->next=v;
}
}
Remove from the tail of the list
• Consider following list:
data next data next data next
head 42 -3 17
v
• In order to delete a node, we need to update the next link of the
node immediately preceding the deleted node
void IntLinkedList::removeEnd(){
if (head->next==NULL)
removeFront();
else{
IntNode *v = head;
while (v->next->next!=NULL){
v=v->next;
}
delete v->next;
v->next = NULL;
}
}
The size() method
// Returns current number of elements
int IntLinkedList::size(){
int count = 0;
IntNode * current = head;
while( current != NULL) {
current = current->next;
count++;
}
return count;
}
count 3
01
2
data next data next data next
head 42 -3 17
current
Adding a node between two nodes
• Consider the following list:
element 0 element 1 element 2
head data next data next data next
42 -3 17
before data next
5
v
• To add a node between two nodes, we first point to the node before
the location of the new node (Example: to add at index 2)
IntNode *v = new IntNode(5);
IntNode *before = head;
for (int i = 0; i < index - 1; i++)
before = before->next;
v->next = before->next;
before->next = v;
remove a node between two nodes
// Removes value at given index from list.
// Precondition: 0 <= index < size()
void IntLinkedList::remove(int index){
IntNode* v = head;
if (index == 0) {
// special case: removing first element
head = head->next;
} else {
IntNode* current = head;
// removing from elsewhere in the list
for (int i = 0; i < index - 1; i++) {
current = current->next;
}
v= current->next;
current->next = current->next->next;
}
delete v;
v=NULL;
}
data next data next data next
front 42 -3 17
current
v
Doubly Linked Lists
• Removing/adding an element at the tail of a singly linked list is not
easy.
– Indeed, it is time consuming to remove/add any node other than the head in a
singly linked list,
– we do not have a quick way of accessing the node immediately preceding the
one we want to remove or add.
– For some applications, it would be nice to have a way of going both directions
in a linked list.
• Concretly, How to see a doubly linked list?
• A sequence of nodes « back to back ».
• Each node gives one hand to its successor and one hand to its predecessor.
Doubly Linked List
• Doubly linked list allows to traverse backward as well as forward
through the list.
–Each node has two references to other nodes instead of one
next: points to the next node in the list
• Last node has no next node (no successor)
prev: points to the previous node in the list
• first node has no previous node (no predecessor)
–Each list uses two pointer to access its first and last nodes
header : refers to the first node
trailer : refers to the last node
trailer
header
trailer
header
37
Doubly Linked List- DLinkedList
class DLinkedList { // doubly linked list
public:
DLinkedList(); // constructor
~DLinkedList(); // destructor
bool empty() const; // is list empty?
const Elem& front() const; // get front element
const Elem& back() const; // get back element
void addFront(const Elem& e); // add to front of list
void addBack(const Elem& e); // add to back of list
void removeFront(); // remove from front
void removeBack(); // remove from back
private: // local type definitions
private:
DNode* header;
DNode* trailer;
};
trailer
header
value
next null
null prev
trailer
header
v
trailer
v
header
41
Doubly Linked List-Deletion
void DLinkedList::removeFront()
{
DNode* v=header;
if (header->next == NULL) //if only one item in the list
trailer = NULL;
else
header->next->prev = NULL;
header = header->next;
delete v;
v=NULL;
}
trailer
header
header
v
Doubly Linked List
•Forward Traversal: start at the first node until the end of the list
DNode *current = header;
while (current != null)
current = current->next;
trailer
header
current
44
Doubly Linked List
•Backward Traversal: start at the last node until the beginning of the list
DNode current =trailer;
while (current != NULL)
current = current->prev;
trailer
header
current
45
Doubly Linked List
Add a node at a specific insertion point in the list
DNode *v = new DNode(e);
DNode *current = header;
trailer
header current
next
prev
v 46