In this lecture, we will develop a single linked list which is a simplification of the std::list. Note that the std::list is a double linked list which allows forward and backwards iteraitons over the list. For simplificaiton we use the single linked list and only implement the forward iterator. However, adding the backward iterator is not much more additional work.
Each element of type T is stored in a struct/class data and inside there is stored
template<typename T>
struct data{
data(T in){
element = in;
}
// Element of the type std::list<T>
T element;
// Pointer of type of the class/struct
data<T>* next = nullptr;
};
// Struct for our implementation of the list
template<typename T>
struct myList{
//Pointer to the first element
data<T>* first = nullptr;
myList(){}
myList(T in){
first = new data<T>(in);
}
bool empty(){
if (first == nullptr)
return true;
return false;
}
};
#include<list>
#include<iostream>
// CST list
std::list<double> list;
// Our list
myList<double> mylist;
std::cout<< list.empty() << " " << mylist.empty() << std::endl;
1 1
list = {1};
mylist = myList<double>(1);
mylist.print();
1
For a linked list, we always have to keep the pointer to the first element, since we use this pointer to access all other elements of the list. The pointer to the second element will be added to the next pointer of the first element.
list.push_back(2);
mylist.push_back(2);
void push_back(T element){
data<T>* tmp = first;
while (tmp->next != nullptr)
tmp = tmp->next;
tmp->next = new data<T>(element);
}
void push_front(T element){
data<T>* tmp = first;
first = new data<T>(element);
first->next = tmp;
}
list.push_front(-1);
mylist.push_front(-1);
mylist.print();
-1 1 2
#include<iostream>
void print(std::list<double> list){
std::list<double>::iterator it;
for (it = list.begin(); it != list.end(); it++)
std::cout << *it << " " ;
}
print(list);
-1 1 2
void print(){
data<T>* tmp = first;
while (tmp->next != nullptr){
std::cout << tmp->element << " ";
tmp = tmp->next;
}
std::cout << tmp->element;
}
mylist.print();
-1 1 2
void pop_back(){
data<T>* tmp = first;
data<T>* prev;
while (tmp->next->next != nullptr){
tmp = tmp->next;
}
delete tmp->next;
tmp->next = nullptr;
}
list.pop_back();
print(list);
std::cout << std::endl;
mylist.pop_back();
mylist.print();
-1 1 -1 1
void insert(T element, size_t index){
data<T>* newNode = new data<T>(element);
data<T>* tmp = first;
data<T>* prev = nullptr;
//Case: Replace the head node
if (index == 0 && tmp != nullptr){
newNode->next = tmp;
*first = newNode;
return;
}
//tmp = tmp->next;
// Case: search for the node
size_t i = 0;
while(i < index && tmp != nullptr){
prev = tmp;
tmp = tmp->next;
i++;
}
if (tmp == nullptr)
{
std::cout << "Index " << index << " out of range" << std::endl;
return;
}
prev->next = newNode;
newNode->next = tmp;
}
std::cout << "Initial list" << std::endl;
mylist.print();
std::cout << std::endl;
std::cout << "Inserting at the beginning" << std::endl;
mylist.insert(1.0,0);
mylist.print();
std::cout << std::endl;
std::cout << "Inserting somewhere" << std::endl;
mylist.insert(40.0,1);
mylist.print();
std::cout << std::endl;
mylist.insert(40.0,10);
Initial list -1 1 Inserting at the beginning 1 -1 1 Inserting somewhere 1 40 -1 1 Index 10 out of range
void remove(T element){
data<T>* tmp = first;
data<T>* prev = nullptr;
// Case I: Delete the head node
if (tmp != nullptr && tmp->element == element){
first = tmp->next;
delete tmp;
return;
}
while (tmp != nullptr && tmp->element != element)
{
prev = tmp;
tmp = tmp->next;
}
// Node was not found
if (tmp == nullptr)
return;
// Unlink the node from linked list
prev->next = tmp->next;
// Free memory
delete tmp;
}
mylist.remove(2.0);
mylist.print();
1 40 -1 1
bool find(T element){
bool found = false;
data<T>* tmp = first;
while (tmp != nullptr){
if (tmp->element == element)
return true;
tmp = tmp->next;
}
return false;
}
#include <algorithm>
auto p = std::find(list.begin(),list.end(),5.0);
if ( p != list.end())
{
std::cout << "Element " << *p << " was found!\n";
}
else
{
std::cout << "Element was not found!\n";
}
Element was not found!
p = std::find(list.begin(),list.end(),1.0);
if ( p != list.end())
std::cout << "Element " << *p << " was found!\n";
else
std::cout << "Element was not found!\n";
std::cout << mylist.find(5.0) << std::endl;
std::cout << mylist.find(1.0) << std::endl;
Element 1 was found! 0 1