202 lines
4.2 KiB
C++
202 lines
4.2 KiB
C++
|
#include <cstddef>
|
||
|
#include <iostream>
|
||
|
#ifndef LINKED_LIST
|
||
|
#define LINKED_LIST
|
||
|
|
||
|
using namespace std;
|
||
|
|
||
|
struct node {
|
||
|
int data;
|
||
|
node *next;
|
||
|
node *previous;
|
||
|
};
|
||
|
|
||
|
class List {
|
||
|
// private:
|
||
|
public:
|
||
|
node *head{};
|
||
|
node *tail{};
|
||
|
|
||
|
public:
|
||
|
// A default constructor, which creates an empty list
|
||
|
List() {}
|
||
|
// Not specified in the HW, but needed in my opinion
|
||
|
List(node *head, node *tail) : head(head), tail(tail) {}
|
||
|
// A parametrized constructor, which creates a list out of the elements of an
|
||
|
// array, keeping them in the same given order.
|
||
|
List(char *data, size_t n) {
|
||
|
for (int i{0}; i < n; i++)
|
||
|
appendList(data[i]);
|
||
|
}
|
||
|
// A copy constructor.
|
||
|
List(List const &list) {
|
||
|
auto h = list.head;
|
||
|
while (h != list.tail->next) {
|
||
|
appendList(h->data);
|
||
|
h = h->next;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool isEmptyList();
|
||
|
std::ostream &printList(std::ostream &out);
|
||
|
void prependList(int);
|
||
|
void appendList(int);
|
||
|
bool findInList(int);
|
||
|
void pop();
|
||
|
void popBack();
|
||
|
void removeFromList(node *);
|
||
|
void removeFromList(int);
|
||
|
|
||
|
friend List operator+(int const a, List const list) {
|
||
|
// copy
|
||
|
List newlist(list);
|
||
|
newlist.prependList(a);
|
||
|
return newlist;
|
||
|
}
|
||
|
friend List operator+(List const list, int a) {
|
||
|
// copy
|
||
|
List newlist(list);
|
||
|
newlist.appendList(a);
|
||
|
return newlist;
|
||
|
}
|
||
|
friend List operator+(List const list1, List const list2) {
|
||
|
// copies
|
||
|
List newlist1(list1);
|
||
|
node *h = list2.head;
|
||
|
while (h != list2.tail->next) {
|
||
|
newlist1.appendList(h->data);
|
||
|
h = h->next;
|
||
|
}
|
||
|
|
||
|
return newlist1;
|
||
|
}
|
||
|
|
||
|
node operator[](int i) {
|
||
|
auto h = head;
|
||
|
for (int j{0}; j < i; j++)
|
||
|
h = h->next;
|
||
|
return *h;
|
||
|
}
|
||
|
};
|
||
|
std::ostream &operator<<(std::ostream &out, List list) {
|
||
|
return list.printList(out);
|
||
|
}
|
||
|
|
||
|
bool List::isEmptyList() {
|
||
|
if (head == nullptr && tail == nullptr)
|
||
|
return true;
|
||
|
return false;
|
||
|
}
|
||
|
void List::appendList(int data) {
|
||
|
node *node1 = new node{data, nullptr, tail};
|
||
|
if (head == nullptr && tail == nullptr) {
|
||
|
head = node1;
|
||
|
tail = node1;
|
||
|
} else {
|
||
|
tail->next = node1;
|
||
|
tail = node1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
std::ostream &List::printList(std::ostream &out) {
|
||
|
if (isEmptyList()) {
|
||
|
out << "List is empty" << endl;
|
||
|
return out;
|
||
|
}
|
||
|
node *traveller = head;
|
||
|
while (traveller != tail) {
|
||
|
out << traveller->data << "=>";
|
||
|
traveller = traveller->next;
|
||
|
}
|
||
|
out << tail->data << endl;
|
||
|
return out;
|
||
|
}
|
||
|
|
||
|
void List::prependList(int data) {
|
||
|
node *node1 = new node{data, head, nullptr};
|
||
|
if (head == nullptr && tail == nullptr) {
|
||
|
head = node1;
|
||
|
tail = node1;
|
||
|
} else {
|
||
|
head->previous = node1;
|
||
|
head = node1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool List::findInList(int key) {
|
||
|
// returns a pointer to the first occurrence of the key in the list
|
||
|
node *traveller = head;
|
||
|
while (traveller != tail->next) {
|
||
|
if (traveller->data == key) {
|
||
|
// return traveller;
|
||
|
return true;
|
||
|
}
|
||
|
traveller = traveller->next;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
void List::pop() {
|
||
|
if (isEmptyList())
|
||
|
return;
|
||
|
if (head == tail) // one node
|
||
|
{
|
||
|
delete head;
|
||
|
head = nullptr;
|
||
|
tail = nullptr;
|
||
|
return;
|
||
|
}
|
||
|
node *firstNode = head;
|
||
|
head = head->next;
|
||
|
head->previous = nullptr;
|
||
|
delete firstNode;
|
||
|
}
|
||
|
|
||
|
void List::popBack() {
|
||
|
if (isEmptyList())
|
||
|
return;
|
||
|
if (head == tail) // one node
|
||
|
{
|
||
|
delete head;
|
||
|
head = nullptr;
|
||
|
tail = nullptr;
|
||
|
return;
|
||
|
}
|
||
|
node *lastNode = tail;
|
||
|
tail = tail->previous;
|
||
|
tail->next = nullptr;
|
||
|
delete lastNode;
|
||
|
}
|
||
|
|
||
|
void List::removeFromList(node *node1) {
|
||
|
if (node1 == head) {
|
||
|
pop();
|
||
|
return;
|
||
|
}
|
||
|
if (node1 == tail) {
|
||
|
popBack();
|
||
|
return;
|
||
|
}
|
||
|
if (node1) {
|
||
|
node *tempPrev = node1->previous;
|
||
|
node *tempNext = node1->next;
|
||
|
tempPrev->next = tempNext;
|
||
|
tempNext->previous = tempPrev;
|
||
|
delete node1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void List::removeFromList(int key) {
|
||
|
node *traveller = head;
|
||
|
while (traveller != tail->next) {
|
||
|
if (traveller->data == key) {
|
||
|
removeFromList(traveller);
|
||
|
return;
|
||
|
}
|
||
|
traveller = traveller->next;
|
||
|
}
|
||
|
|
||
|
// note that this deletes only the first occurrence of the key in the list
|
||
|
}
|
||
|
|
||
|
#endif
|