18 del 1
This commit is contained in:
parent
5a3aa29482
commit
e3b70d57ed
@ -10,36 +10,11 @@ size_t DoublyLinkedList::size() const
|
||||
return count;
|
||||
}
|
||||
|
||||
// return pointer to the node at position i, counting from 0
|
||||
// for negative numbers, count from the tail (-1) backward (-2, -3, ...)
|
||||
DoublyLinkedListNode* DoublyLinkedList::index(int i) const
|
||||
{
|
||||
DoublyLinkedListNode* n = this->head;
|
||||
if(i > 0)
|
||||
{
|
||||
for(int k = 0; k < i; k++)
|
||||
{
|
||||
assert(n != nullptr);
|
||||
n = n->get_next();
|
||||
}
|
||||
}
|
||||
else /** in the doubly linked list, we can walk backward, so let us allow it for negative i **/
|
||||
{
|
||||
DoublyLinkedListNode* n = this->tail;
|
||||
for(int k = -1; k > i; k--)
|
||||
{
|
||||
assert(n != nullptr);
|
||||
n = n->get_prev();
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
// add an item at the end of the list
|
||||
void DoublyLinkedList::push_back(const int& pushed_item)
|
||||
void DoublyLinkedList::enqueue(int value)
|
||||
{
|
||||
DoublyLinkedListNode* new_node = new DoublyLinkedListNode;
|
||||
new_node->set_item(pushed_item);
|
||||
new_node->set_item(value);
|
||||
|
||||
if(this->empty()) this->head = new_node;
|
||||
else
|
||||
@ -50,115 +25,16 @@ void DoublyLinkedList::push_back(const int& pushed_item)
|
||||
this->tail = new_node;
|
||||
}
|
||||
|
||||
// add an item at the beginning of the list
|
||||
void DoublyLinkedList::push_front(const int& pushed_item)
|
||||
{
|
||||
DoublyLinkedListNode* new_node = new DoublyLinkedListNode;
|
||||
new_node->set_item(pushed_item);
|
||||
|
||||
if(this->empty()) this->tail = new_node;
|
||||
else
|
||||
{
|
||||
new_node->set_next(this->head); // FIX BUG from the previous version, which was "new_node->set_next(this->head->get_next());"
|
||||
this->head->set_prev(new_node); // FIX BUG from the previous version, which was "this->head->get_next()->set_prev(new_node);"
|
||||
}
|
||||
this->head = new_node;
|
||||
}
|
||||
|
||||
// remove the head node and item
|
||||
void DoublyLinkedList::pop_front()
|
||||
int DoublyLinkedList::dequeue()
|
||||
{
|
||||
if(this->empty()) return; // nothing there to remove
|
||||
if(this->empty()) return 0; // nothing there to remove
|
||||
DoublyLinkedListNode* successor = this->head->get_next();
|
||||
|
||||
if(successor) successor->set_prev(nullptr); /** we must detach the previous head node from its successor **/
|
||||
int outgoing = this->head->item;
|
||||
delete this->head;
|
||||
this->head = successor; // successor of the previous head is the new head
|
||||
if(this->head == nullptr) this->tail = nullptr; // catch special case: the list is now empty
|
||||
}
|
||||
|
||||
// remove the tail node and item
|
||||
/** note how this is much easier for the doubly than for the singly linked list; **
|
||||
** we can simply take the "pop_front()" implementation and do everything symmetrically **/
|
||||
void DoublyLinkedList::pop_back()
|
||||
{
|
||||
if(this->empty()) return; // nothing there to remove
|
||||
DoublyLinkedListNode* predecessor = this->tail->get_prev();
|
||||
|
||||
if(predecessor) predecessor->set_next(nullptr);
|
||||
delete this->tail;
|
||||
this->tail = predecessor; /** predecessor of the previous tail is the new tail **/
|
||||
if(this->tail == nullptr) this->head = nullptr; /** catch special case: the list is now empty **/
|
||||
}
|
||||
|
||||
// insert an item at index i
|
||||
// for negative numbers, count from the tail (-1) backward (-2, -3, ...)
|
||||
void DoublyLinkedList::insert_at(int i, const int& inserted_item)
|
||||
{
|
||||
if(i == 0)
|
||||
{
|
||||
this->push_front(inserted_item);
|
||||
return;
|
||||
}
|
||||
else if(i == -1)
|
||||
{
|
||||
this->push_back(inserted_item);
|
||||
return;
|
||||
}
|
||||
DoublyLinkedListNode* predecessor = this->index(i-1);
|
||||
this->insert_successor_to(predecessor, inserted_item);
|
||||
}
|
||||
|
||||
// remove the item at index i
|
||||
// for negative numbers, count from the tail (-1) backward (-2, -3, ...)
|
||||
void DoublyLinkedList::erase_at(int i)
|
||||
{
|
||||
if(i == 0)
|
||||
{
|
||||
this->pop_front();
|
||||
return;
|
||||
}
|
||||
else if(i == -1)
|
||||
{
|
||||
this->pop_back();
|
||||
return;
|
||||
}
|
||||
DoublyLinkedListNode* erased_node = this->index(i);
|
||||
this->erase_node(erased_node);
|
||||
}
|
||||
|
||||
// insert an item after given node
|
||||
void DoublyLinkedList::insert_successor_to(DoublyLinkedListNode* predecessor, const int& inserted_item)
|
||||
{
|
||||
DoublyLinkedListNode* new_node = new DoublyLinkedListNode;
|
||||
new_node->set_item(inserted_item);
|
||||
|
||||
DoublyLinkedListNode* successor = predecessor->get_next();
|
||||
predecessor->set_next(new_node);
|
||||
new_node->set_prev(predecessor); /** attach both ways **/
|
||||
new_node->set_next(successor);
|
||||
|
||||
if(!successor) this->tail = new_node;
|
||||
else successor->set_prev(new_node); /** attach both ways **/
|
||||
}
|
||||
|
||||
/** remove "erased_node" from the doubly linked list **/
|
||||
void DoublyLinkedList::erase_node(DoublyLinkedListNode* erased_node)
|
||||
{
|
||||
if(erased_node->get_prev() == nullptr) /** erase the head **/
|
||||
{
|
||||
this->pop_front();
|
||||
return;
|
||||
}
|
||||
if(erased_node->get_next() == nullptr) /** erase the tail **/
|
||||
{
|
||||
this->pop_back();
|
||||
return;
|
||||
}
|
||||
|
||||
/** now attach predecessor and successor to each other **/
|
||||
erased_node->get_prev()->set_next(erased_node->get_next());
|
||||
erased_node->get_next()->set_prev(erased_node->get_prev());
|
||||
|
||||
delete erased_node; /** "erased_node" detached now, we can delete it **/
|
||||
return outgoing;
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
#define DOUBLY_LINKED_LIST_H
|
||||
|
||||
#include <cassert>
|
||||
#include "queue.h"
|
||||
#include "sequence.h"
|
||||
|
||||
namespace seq
|
||||
@ -37,61 +38,20 @@ namespace seq
|
||||
friend class DoublyLinkedList; // allow DoublyLinkedList to access private members
|
||||
};
|
||||
|
||||
class DoublyLinkedList: public Sequence
|
||||
class DoublyLinkedList: public Queue
|
||||
{
|
||||
public:
|
||||
bool empty() const { return (this->head == nullptr); } // test whether the doubly linked list is empty
|
||||
size_t size() const; // return the size (number of items in the doubly linked list)
|
||||
|
||||
// it is the caller's responsibility to ensure that the list is not empty when calling front() or back()!
|
||||
int& front() { assert(this->head); return this->head->get_item(); } // return a reference to the first item
|
||||
int& back() { assert(this->tail); return this->tail->get_item(); } // return a reference to the final item
|
||||
|
||||
// return a reference to the item at position i of the list, counting from 0
|
||||
// for negative numbers, count from the tail (-1) backward (-2, -3, ...)
|
||||
// it is the caller's responsibility that the index is within range
|
||||
int& at(int i) { return this->index(i)->get_item(); }
|
||||
void enqueue(int element);
|
||||
int dequeue();
|
||||
|
||||
// return pointer to the head/tail node
|
||||
DoublyLinkedListNode* begin() const { return this->head; }
|
||||
DoublyLinkedListNode* end() const { return this->tail; }
|
||||
|
||||
// return pointer to the node at position i, counting from 0
|
||||
// for negative numbers, count from the tail (-1) backward (-2, -3, ...)
|
||||
DoublyLinkedListNode* index(int i) const;
|
||||
|
||||
/*
|
||||
* accepts an additional item into the doubly linked list;
|
||||
* by default, this is done at the back end of the list
|
||||
* call push_front(...) to push an element at the front
|
||||
*
|
||||
* the list takes ownership of the copy (but not of the original!)
|
||||
*/
|
||||
void push(const int& pushed_item) { this->push_back(pushed_item); }
|
||||
void push_back(const int& pushed_item);
|
||||
void push_front(const int& pushed_item);
|
||||
|
||||
/*
|
||||
* removes an item from the list (front end by default)
|
||||
* to do the same at the back, call pop_back()
|
||||
*/
|
||||
void pop() { this->pop_front(); }
|
||||
void pop_front();
|
||||
void pop_back();
|
||||
void clear() { while(!this->empty()) this->pop(); } // remove all the items from the list
|
||||
|
||||
// it is the caller's responsibility that the index is within range
|
||||
// for negative numbers, count from the tail (-1) backward (-2, -3, ...)
|
||||
void insert_at(int i, const int& inserted_item); // insert an item at index i
|
||||
void erase_at(int i); // remove the item at index i
|
||||
|
||||
// it is the caller's responsibility that the node is actually part of the list
|
||||
void insert_successor_to(DoublyLinkedListNode* predecessor, const int& inserted_item); // insert an item after given node
|
||||
void erase_successor_to(DoublyLinkedListNode* predecessor) // remove the item after given node
|
||||
{
|
||||
this->erase_node(predecessor->get_next());
|
||||
}
|
||||
void erase_node(DoublyLinkedListNode* erased_node);
|
||||
void clear() { while(!this->empty()) this->dequeue(); } // remove all the items from the list
|
||||
|
||||
~DoublyLinkedList() { this->clear(); }
|
||||
|
||||
|
@ -56,12 +56,12 @@ int main()
|
||||
std::cout << "\n\n*** test with singly linked list ***\n";
|
||||
seq::SinglyLinkedList sll;
|
||||
float sll_time = test_with_time_measurement(&sll, iterations);
|
||||
/*
|
||||
|
||||
std::cout << "\n\n*** test with doubly linked list ***\n";
|
||||
seq::DoublyLinkedList dll;
|
||||
float dll_time = test_with_time_measurement(&dll, iterations);
|
||||
*/
|
||||
|
||||
//std::cout << "\n\nRuntime for dynamic array:\t" << dyna_time << " s\n";
|
||||
std::cout << "Runtime for singly linked list:\t" << sll_time << " s\n";
|
||||
//std::cout << "Runtime for doubly linked list:\t" << dll_time << " s\n";
|
||||
std::cout << "Runtime for doubly linked list:\t" << dll_time << " s\n";
|
||||
}
|
||||
|
@ -25,9 +25,9 @@ int SinglyLinkedList::dequeue()
|
||||
{
|
||||
if(this->empty()) return 0; // nothing there to remove
|
||||
SinglyLinkedListNode* successor = this->head->get_next();
|
||||
int result = this->head->item;
|
||||
int outgoing = this->head->item;
|
||||
delete this->head;
|
||||
this->head = successor; // successor of the previous head is the new head
|
||||
if(this->head == nullptr) this->tail = nullptr; // catch special case: the list is now empty
|
||||
return result;
|
||||
return outgoing;
|
||||
}
|
Loading…
Reference in New Issue
Block a user