Skip to content

Instantly share code, notes, and snippets.

@zxteloiv
Last active December 18, 2015 12:29
Show Gist options
  • Save zxteloiv/5782789 to your computer and use it in GitHub Desktop.
Save zxteloiv/5782789 to your computer and use it in GitHub Desktop.
An C++ implementation of linked list resembling STL list
///////////////////////////////////////////////////////////////
// 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