Last active
December 18, 2015 12:29
-
-
Save zxteloiv/5782789 to your computer and use it in GitHub Desktop.
An C++ implementation of linked list resembling STL list
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/////////////////////////////////////////////////////////////// | |
// Filename : MyList.h | |
// Author : Zhang Xiang | |
// Date : 2010-8-18 | |
// Comment : A two-direction list class and it implemented part of the | |
// functions as the list container of STL come with Visual | |
// studio. | |
// | |
// Iterator class name is MyListIterator, and the value is a | |
// four-byte integer, which may need a type cast in the pointer | |
// case. | |
/////////////////////////////////////////////////////////////// | |
#pragma once | |
namespace ZX | |
{ | |
// forward declaration | |
class KMyList; | |
struct _list_node | |
{ | |
_list_node* previous; | |
_list_node* next; | |
union { | |
int nValue; | |
void* pAddr; | |
}; | |
}; | |
class _list_iterator | |
{ | |
friend class KMyList; // permit KMyList objects only to access its pNode member. | |
_list_node* pNode; | |
public: | |
_list_iterator() {} | |
_list_iterator(_list_node* node) : pNode(node) {} | |
~_list_iterator() {} | |
// overload some operators for easier use of the iterator | |
int& operator*() { return pNode->nValue; } // "*it" will get the node value, like a pointer | |
// this may not used widely because the return value is int* and an int has not any method. | |
int* operator->() { return &(pNode->nValue); } // "it->" will access the value address | |
bool operator==(_list_iterator iterToComp) { return (pNode == iterToComp.pNode); } | |
bool operator!=(_list_iterator iterToComp) { return (pNode != iterToComp.pNode); } | |
_list_iterator& operator=(_list_iterator& other) { pNode = other.pNode; return (*this); } | |
_list_iterator& operator++() { // prefix increment | |
pNode = pNode->next; | |
return (*this); | |
} | |
_list_iterator operator++(int) { // postfix increment | |
// Here comes the copy constructor, and itTmp is initialized as a copy of (*this) then. | |
_list_iterator itTmp = *this; | |
++*this; // thus the prefix increment will not affect itTmp | |
return itTmp; | |
} | |
_list_iterator& operator--() { // prefix decrement | |
pNode = pNode->previous; | |
return (*this); | |
} | |
_list_iterator operator--(int) { // postfix decrement | |
// Here comes the copy constructor, and itTmp is initialized as a copy of (*this) then. | |
_list_iterator itTmp = *this; | |
--*this; // thus the prefix decrement will not affect itTmp | |
return itTmp; | |
} | |
}; | |
class KMyList | |
{ | |
////////////////////////////////// | |
// Type definition | |
public: | |
typedef _list_iterator MyListIterator; | |
////////////////////////////////// | |
// Data members | |
private: | |
int m_nCount; // Element amount of the list | |
_list_node* m_pListHead; // This is not the first element in a list but a junk node | |
// that can identify a list and the end of the list. | |
////////////////////////////////// | |
// Interfaces | |
public: | |
KMyList() : m_nCount(0) { | |
// m_pListHead acts as a pre-set value, for some boundary usage. and it doesn't contain | |
// any value that are inserted by users of the KMyList class. | |
m_pListHead = new _list_node; | |
m_pListHead->next = m_pListHead; | |
m_pListHead->previous = m_pListHead; | |
m_pListHead->nValue = 0xfeeefeee; // ^_^, fill it with junk value | |
} | |
~KMyList() { | |
Clear(); | |
delete m_pListHead; | |
} | |
// Assign some value from another list, when the list is not empty it will be cleared. | |
void Assign(MyListIterator& first, MyListIterator& last) { | |
Clear(); | |
for (MyListIterator iter = first; iter != last; ++iter) { | |
PushBack(*iter); | |
} | |
} | |
// Insert a new value before the pWhere position | |
MyListIterator Insert(const MyListIterator& pWhere, int nVal) { | |
_list_node* pNewNode = new _list_node; | |
pNewNode->nValue = nVal; | |
pNewNode->next = pWhere.pNode; | |
pNewNode->previous = (pWhere.pNode)->previous; | |
pNewNode->previous->next = pNewNode; | |
(pWhere.pNode)->previous = pNewNode; | |
m_nCount++; | |
return MyListIterator(pNewNode); | |
} | |
// Insert a new value for nCount times before the pWhere position | |
void Insert(const MyListIterator& pWhere, const int nCount, int nVal) { | |
for (int nInserted = 0; nInserted < nCount; ++nInserted) { | |
Insert(pWhere, nVal); | |
} | |
} | |
// Insert a range of value before the pWhere position | |
void Insert(const MyListIterator& pWhere, const MyListIterator& first, const MyListIterator& last) { | |
for (MyListIterator iter = first; iter != last; ++iter) { | |
Insert(pWhere, *iter); | |
} | |
} | |
// Erase the node designated by pWhere iterator and return the node after the erased one | |
MyListIterator Erase(MyListIterator& pWhere) { | |
if (pWhere != m_pListHead) { | |
_list_node* pNextNode = pWhere.pNode->next; // backup old node | |
(pWhere.pNode)->previous->next = (pWhere.pNode)->next; | |
(pWhere.pNode)->next->previous = (pWhere.pNode)->previous; | |
delete (pWhere.pNode); | |
m_nCount--; | |
return MyListIterator(pNextNode); | |
} | |
throw; | |
return pWhere; | |
} | |
// Erase a range of nodes and return the node after those, or the list end. | |
MyListIterator Erase(MyListIterator& first, MyListIterator& last) { | |
if (first == Begin() && last == End()) { | |
Clear(); | |
return End(); | |
} | |
MyListIterator iter = first; | |
while (iter != last) { | |
Erase(iter); | |
} | |
return last; | |
} | |
// insert a new node at the beginning of the list | |
void PushFront(int nVal) { | |
Insert(Begin(), nVal); | |
} | |
// insert a node at the tail of the list | |
void PushBack(int nVal) { | |
Insert(End(), nVal); | |
} | |
// clear all nodes in the list, reset it to the initial state | |
void Clear() { | |
_list_node* pNextNode; | |
_list_node* pNode = m_pListHead->next; | |
while (pNode != m_pListHead) { | |
pNextNode = pNode->next; | |
delete pNode; | |
pNode = pNextNode; | |
} | |
m_pListHead->next = m_pListHead; | |
m_pListHead->previous = m_pListHead; | |
m_nCount = 0; | |
} | |
// first value in the list | |
int Front() const { return (*Begin()); } | |
// last value in the list | |
int Back() const { return (*(--End())); } | |
// first iterator of the list | |
MyListIterator Begin() const { return MyListIterator(m_pListHead->next); } | |
// last iterator of the list | |
MyListIterator End() const { return MyListIterator(m_pListHead); } | |
// Check if the list contains none elements | |
bool IsEmpty() const { return (0 == m_nCount); } | |
// Get the amount of the nodes in the whole list | |
int Size() const { return m_nCount; } | |
}; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment