#include #include #include #include "HList.h" using namespace std; // ------------------------------------------------------------------- // HNode Implementation // ------------------------------------------------------------------- HNode::HNode() : next(NULL) { // do nothing else } HNode::~HNode() { #ifndef NDEBUG cerr << " HNode destructor\n" ; #endif // do nothing } void HNode::print(ostream& os) const { os << "" ; } HNode *HNode::clone() const { #ifndef NDEBUG cerr << " HNode clone\n" ; #endif return new HNode ; } bool HNode::operator == (const HNode& rhs_ref) const { // virtual return typeid(rhs_ref) == typeid(HNode) ; } // All derived classes should have != opposite of ==, so there's // no need to make != virtual. Note that the non-virtual != invokes // the virtual == and this is actually what we want. // bool HNode::operator != (const HNode& rhs_ref) const { // not virtual return ! operator==(rhs_ref) ; // calls virtual == } // ------------------------------------------------------------------- // HList Implementation // ------------------------------------------------------------------- // Default constructor // HList::HList() : tail_ptr(&header), m_size(0) { // do nothing else } // Copy constructor // HList::HList(const HList &L) { #ifndef NDEBUG cerr << "HList copy constructor:\n" ; #endif duplicate(L) ; } // Destructor // HList::~HList() { #ifndef NDEBUG cerr << "HList Destructor:\n" ; #endif clear(); } // Assignment operator // const HList& HList::operator=(const HList &rhs) { // check for self-assignment if(this == &rhs) return *this; clear(); // delete our old stuff duplicate(rhs) ; return *this ; } // Make a copy of the linked list. // The tail_ptr and m_size members set too. // Note the use of the virtual clone function. // void HList::duplicate(const HList& L) { HNode *previous = &header ; HNode *ptr = L.header.next ; while (ptr !=NULL) { previous->next = ptr->clone() ; // copy using virtual clone() previous = previous->next ; ptr = ptr->next ; } tail_ptr = previous ; m_size = L.m_size ; } // Empty the list. // Make sure that tail_ptr and size are put in a good state. // Note the use of the virtual destructor. // void HList::clear() { HNode *previous ; HNode *current = header.next; header.next = NULL; tail_ptr = &header ; m_size = 0 ; while(current != NULL) { previous = current ; current = current->next ; delete previous; // virtual destructor called } } // Add node to the front of the linked list. // Memory for the node pointed by ptr must be dynamically allocated. void HList::push_front(HNode *ptr) { if (ptr == NULL) { cerr << "Inserting unallocated HNode!\n" ; exit(1) ; } ptr->next = header.next ; header.next = ptr ; // fix tail_ptr, if list was empty if (tail_ptr == &header) { tail_ptr = ptr ; } m_size++ ; } // Add node to the back of the linked list. // Memory for the node pointed by ptr must be dynamically allocated. void HList::push_back(HNode *ptr) { if (ptr == NULL) { cerr << "Inserting unallocated HNode!\n" ; exit(1) ; } tail_ptr->next = ptr ; ; tail_ptr = ptr ; m_size++ ; } // Return pointer to first node. // Note: client can't access next to mess up the linking. // Returns NULL if list is empty. HNode *HList::front() { return header.next ; } // Return pointer to last node. // Note: client can't access next to mess up the linking. // Returns NULL if list is empty. HNode *HList::back() { if (tail_ptr == &header) return NULL ; return tail_ptr ; } // Remove first node, no return value // note the use of the virtual destructor // void HList::pop_front() { HNode *ptr = header.next ; // empty list, do nothing if (ptr == NULL) return ; header.next = ptr->next ; // de-link // deleting last node? if (tail_ptr == ptr) tail_ptr = &header ; delete ptr ; // Calls virtual destructor m_size-- ; } // Look for the node with "value" equal to X and return pointer // to found node or NULL if none found. // Note: client can't access next to mess up the linking. // Note that != is not virtual, but calls the virtual == // HNode *HList::find(const HNode& X) const { HNode* current = header.next ; while (current != NULL && *current != X) { current = current->next ; } return current ; } // Remove first node with "value" equal to X // if none found, return false. // bool HList::remove(const HNode& X) { HNode* previous = &header; HNode* ptr ; while (previous->next != NULL) { if ( *(previous->next) == X ) { // virtual == ptr = previous->next ; previous->next = ptr->next ; // fix tail_ptr if deleting last guy if (tail_ptr == ptr) { tail_ptr = previous ; } delete ptr ; // calls virtual destructor m_size-- ; return true ; } previous = previous->next ; } return false; } // Print entire linked list using virtual HNode::print() void HList::print(ostream& os /*=cout*/) const { HNode* current = header.next ; while(current != NULL) { current->print(os) ; os << " " ; current = current->next; } } unsigned int HList::size() const { return m_size; } // Overloaded << // ostream& operator<< (ostream& os, const HList& L) { L.print(os) ; return os ; }