实现一个简单的列表,基于双向链表,要求支持删除,插入,下标等操作。
#ifndef _DOUBLELINKEDLIST_
#define _DOUBLELINKEDLIST_
#include <iostream>
#include <stdexcept>
using namespace std;
template <typename T>
class DoubleLinkedList
{
private:
struct DoubleLinkedListNode
{
T data;
DoubleLinkedListNode* previous;
DoubleLinkedListNode* next;
DoubleLinkedListNode(const T& v,DoubleLinkedListNode* p = NULL,DoubleLinkedListNode* n= NULL) : data(v), previous(p),next(n) {}
};
public:
DoubleLinkedList() : size(0),currentIndex(-1),current(NULL) {}
~DoubleLinkedList() { Clear(); }
DoubleLinkedList(const DoubleLinkedList& rhs) : size(0),currentIndex(-1),current(NULL)
{
operator=(rhs);
}
const DoubleLinkedList& operator= ( const DoubleLinkedList& rhs )
{
if( this != &rhs )
{
Clear();
if(!rhs.IsEmpty())
{
int oldCurrentIndex = rhs.currentIndex;
rhs.SetCurrentIndex(0);
DoubleLinkedListNode* temp = rhs.current;
while(temp != NULL)
{
Add(temp->data);
temp = temp->next;
}
rhs.SetCurrentIndex(oldCurrentIndex);
this->SetCurrentIndex(oldCurrentIndex);
}
}
return *this;
}
int Size() const { return size; }
bool IsEmpty() const { return size == 0; }
void Clear()
{
if(!IsEmpty())
{
SetCurrentIndex(0);
DoubleLinkedListNode* temp = current;
while(temp != NULL)
{
current = current->next;
delete temp;
temp = current;
}
size = 0;
currentIndex = -1;
current = NULL;
}
}
void Print()
{
cout << "Size=" << size << endl;
cout << "CurrentIndex=" << currentIndex << endl;
cout << "Current=" << current;
cout << endl;
if(!IsEmpty())
{
SetCurrentIndex(0);
DoubleLinkedListNode* temp = current;
while(temp != NULL)
{
cout << temp->data << ",";
temp = temp->next;
}
cout << endl;
}
}
void Insert(int index,const T& value)
{
if( index < 0 || index > size )
throw logic_error("Index is not valid for insertion");
if(IsEmpty())
{
current = new DoubleLinkedListNode(value,NULL,NULL);
currentIndex = 0;
++size;
return;
}
else if(index == size)
{
SetCurrentIndex(index-1);
current->next = new DoubleLinkedListNode(value,current,current->next);
++currentIndex;
current=current->next;
++size;
return;
}
else
{
SetCurrentIndex(index);
DoubleLinkedListNode* temp = new DoubleLinkedListNode(value,current->previous,current);
current->previous = temp;
if(temp->previous != NULL)
temp->previous->next = temp;
current = temp;
++size;
return;
}
}
void Add(const T& value)
{
Insert(size, value);
}
T Remove(int index)
{
if(IsEmpty())
throw logic_error("List is empty");
CheckRange(index);
SetCurrentIndex(index);
T value;
DoubleLinkedListNode* temp = current;
value = temp->data;
if(size == 1)
{
current = NULL;
currentIndex = -1;
}
else
{
if(index == 0)
{
current->next->previous = current->previous;
current = current->next;
}
else if(index == size -1 )
{
current->previous->next = current->next;
current = current->previous;
--currentIndex;
}
else
{
current->previous->next = current->next;
current->next->previous = current->previous;
current = current->next;
}
}
delete temp;
--size;
return value;
}
T Remove()
{
return Remove(size-1);
}
T& operator[](int index)
{
return ElementAt(index);
}
const T& operator[](int index) const
{
return ElementAt(index);
}
private:
T& ElementAt(int index) const
{
if(IsEmpty())
throw logic_error("List is empty");
SetCurrentIndex(index);
return current->data;
}
void SetCurrentIndex(int index) const
{
CheckRange(index);
if(currentIndex == index)
return;
else if(currentIndex < index)
{
for( ; currentIndex < index; ++currentIndex)
current = current->next;
}
else
{
for( ; currentIndex > index; --currentIndex)
current = current->previous;
}
}
void CheckRange(int index) const
{
if( index < 0 || index >= size)
throw logic_error("Invalid index value");
}
int size;
mutable int currentIndex;
mutable DoubleLinkedListNode* current;
};
#endif
测试代码:
#include "DoubleLinkedList.cpp"
void DoubleLinkedListTest1();
void Test( void (*fp)() );
int main(int argc, char** argv)
{
Test(DoubleLinkedListTest1);
return 0;
}
void DoubleLinkedListTest1()
{
DoubleLinkedList<int> v;
int removed = 0 ;
v.Print();
v.Add(5);
v.Add(8);
v.Add(10);
v.Print();
v.Insert(3,20);
v.Print();
v.Insert(1,22);
v.Print();
v.Insert(0,28);
v.Print();
v.Add(101);
v.Add(102);
v.Add(103);
v.Add(104);
v.Print();
removed = v.Remove();
v.Print();
cout<< "Removed=" << removed << endl;
v.Add(105);
v.Print();
removed = v.Remove(0);
v.Print();
cout<< "Removed=" << removed << endl;
v.Add(106);
removed = v.Remove(v.Size()-1);
v.Print();
cout<< "Removed=" << removed << endl;
v.Add(107);
removed = v.Remove(5);
v.Print();
cout<< "Removed=" << removed << endl;
v.Add(109);
v.Add(110);
v.Print();
for(int i=9;i>0;--i)
v.Insert(11,110+i);
v.Print();
v.Insert(11,150);
v.Print();
for(int i=0;i<v.Size();++i)
cout << v[i] << ",";
cout<<endl;
v.Remove(30);
}
void Test( void (*fp)() )
{
try
{
fp();
}
catch(out_of_range& e)
{
cout<< "Catch Exception:" << e.what() << endl;
}
catch(overflow_error& e)
{
cout<< "Catch Exception:" << e.what() << endl;
}
catch(logic_error& e)
{
cout<< "Catch Exception:" << e.what() << endl;
}
}