Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- template <typename ElemT>
- class List
- {
- class Node
- {
- ElemT data;
- Node* next;
- Node* prev;
- public:
- Node(const ElemT& dataP, Node* nextP = nullptr, Node* prevP = nullptr)
- : data{ dataP }, next{ nextP }, prev{prevP} {}
- friend List;
- };
- Node* head;
- Node* tail;
- size_t size;
- Node* getNode(size_t idx);
- public:
- List() : head{ nullptr }, tail{ nullptr }, size{ 0 } {}
- bool empty()const { return size == 0; }
- size_t get_size()const { return size; }
- ElemT& front() { return head->data; }
- const ElemT& front()const { return head->data; }
- ElemT& back() { return tail->data; }
- const ElemT& back()const { return tail->data; }
- void push_front(const ElemT& data);
- void push_back(const ElemT& data);
- bool pop_front();
- bool pop_back();
- void insert_at(size_t idx, const ElemT& data);
- bool delete_at(size_t idx);
- ElemT& operator[](size_t idx);
- const ElemT& operator[](size_t idx)const;
- void clear();
- ~List();
- void print()
- {
- for (auto curr{ head }; curr; curr = curr->next)
- {
- std::cout << curr->data << ' ';
- }
- std::cout << '\n';
- }
- };
- template <typename ElemT>
- void List<ElemT>::push_back(const ElemT& data)
- {
- Node* oldTail{ tail };
- tail = new Node{ data, nullptr, tail };
- ++size;
- if (oldTail)
- {
- oldTail->next = tail;
- }
- if (!head)
- {
- head = tail;
- }
- }
- template <typename ElemT>
- void List<ElemT>::push_front(const ElemT& data)
- {
- Node* oldHead{ head };
- head = new Node{ data, head, nullptr };
- ++size;
- if (oldHead)
- {
- oldHead->prev = head;
- }
- if (!tail)
- {
- tail = head;
- }
- }
- template <typename ElemT>
- bool List<ElemT>::pop_front()
- {
- if (head)
- {
- if (tail == head)
- {
- delete head;
- head = nullptr;
- tail = nullptr;
- size = 0;
- return true;
- }
- Node* oldHead{ head };
- head = head->next;
- head->prev = nullptr;
- delete oldHead;
- --size;
- return true;
- }
- return false;
- }
- template <typename ElemT>
- bool List<ElemT>::pop_back()
- {
- if (tail)
- {
- if (tail == head)
- {
- delete tail;
- head = nullptr;
- tail = nullptr;
- size = 0;
- return true;
- }
- Node* oldTail{ tail };
- tail = tail->prev;
- tail->next = nullptr;
- delete oldTail;
- --size;
- return true;
- }
- return false;
- }
- template <typename ElemT>
- void List<ElemT>::clear()
- {
- while (head)
- {
- std::cout << "Clear for: " << front() << '\n';
- pop_front();
- }
- }
- template <typename ElemT>
- typename List<ElemT>::Node* List<ElemT>::getNode(size_t idx)
- {
- Node* curr{ nullptr };
- size_t currIdx;
- if (idx >= 0 and idx < size)
- {
- if (idx > (size / 2))
- {
- for (curr = tail, currIdx = size - 1; currIdx > idx; curr = curr->prev, --currIdx);
- }
- else
- {
- for (curr = head, currIdx = 0; currIdx < idx; curr = curr->next, ++currIdx);
- }
- }
- return curr;
- }
- template <typename ElemT>
- void List<ElemT>::insert_at(size_t idx, const ElemT& data)
- {
- Node* curr{ getNode(idx) };
- if (!curr or curr == tail) { push_back(data); return; }
- Node* newNode = new Node{ data, curr->next, curr };
- curr->next = newNode;
- newNode->next->prev = newNode;
- ++size;
- }
- template <typename ElemT>
- bool List<ElemT>::delete_at(size_t idx)
- {
- Node* curr{ getNode(idx) };
- if (curr)
- {
- if (head == tail) // curr == head and curr == tail
- {
- head = nullptr;
- tail = nullptr;
- size = 0;
- delete curr;
- return true;
- }
- if (curr->prev) { curr->prev->next = curr->next; }
- else { head = curr->next; }
- if (curr->next) { curr->next->prev = curr->prev; }
- else { tail = curr->prev; }
- --size;
- delete curr;
- return true;
- }
- return false;
- }
- template <typename ElemT>
- ElemT& List<ElemT>::operator[](size_t idx)
- {
- return getNode(idx)->data;
- }
- template <typename ElemT>
- const ElemT& List<ElemT>::operator[](size_t idx)const
- {
- return getNode(idx)->data;
- }
- template <typename ElemT>
- List<ElemT>::~List()
- {
- while (tail)
- {
- std::cout << "Destruct for: " << back() << '\n';
- pop_back();
- }
- }
- template <typename ElemT>
- void printListState(const List<ElemT>& l)
- {
- std::cout << "Size: " << l.get_size() << '\n';
- std::cout << "Front: " << l.front() << '\n';
- std::cout << "Back: " << l.back() << '\n';
- }
- int main()
- {
- List<int> l;
- // [3,2,1,0]
- for (int i{ 0 }; i < 6; l.push_front(i++));
- l.print();
- l.insert_at(2, 22);
- l.print();
- l.delete_at(3);
- l.print();
- // do not do like this!!! tottaly bad idea!!! :(
- for (int i{ 0 }; i < l.get_size(); ++i)
- {
- std::cout << l[i] << ' ';
- }
- std::cout << '\n';
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement