1 栈
栈(stack),在计算机科学中,是一种特殊的串行形式的数据结构,它的特殊之处在于只能允许在链结串行或阵列的一端(称为栈顶,top)进行加入(push)和输出(pop)的运算。栈可以用一维动态数组或链表的形式来完成。
由于堆栈数据结构只允许在一端进行操作,因而按照后进先出(LIFO, Last In First Out)的原理运作。堆栈数据结构使用两种基本操作:推入(push)和弹出(pop):
推入(push):将数据放入堆栈的顶端(阵列形式或串行形式),堆栈顶端top指标加一。
弹出(pop):将顶端数据资料输出(回传),堆栈顶端资料减一。
先来看栈的架构设计:
首先来看抽象栈实现方式:
class Stack : public virtual Container
{
public:
virtual Object& Top () const = 0;
virtual void Push (Object&) = 0;
virtual Object& Pop () = 0;
};
再来看栈的动态数组实现方式:
class StackAsArray : public Stack
{
Array<Object*> array;
class Iter;
public:
StackAsArray (unsigned int size);
~StackAsArray ();
// ...
Object& Top() const;
void Push(Object& obj);
Object& Pop();
void Purge ();
void Accept (Visitor& visitor) const;
Iterator& NewIterator() const;
friend class Iter;
};
StackAsArray::StackAsArray( unsigned int size )
:array(size)
{
count = 0;
}
void StackAsArray::Purge()
{
if (IsOwner())
{
for (unsigned int i = 0; i < count; ++i)
{
delete array [i];
}
}
count = 0;
}
StackAsArray::~StackAsArray()
{
Purge ();
}
Object& StackAsArray::Top() const
{
if (count == 0)
{
throw domain_error ("stack is empty");
}
return *array [count - 1U];
}
void StackAsArray::Push( Object& obj )
{
if (count == array.Length ())
{
throw domain_error ("stack is full");
}
array [count++] = &obj;
}
Object& StackAsArray::Pop()
{
if (count == 0)
{
throw domain_error ("stack is empty");
}
return *array [--count];
}
void StackAsArray::Accept( Visitor& visitor ) const
{
for (unsigned int i = 0;
i < count && !visitor.IsDone (); ++i)
{
visitor.Visit (*array [i]);
}
}
Iterator& StackAsArray::NewIterator() const
{
return *new StackAsArray::Iter(*this);
}
注意最后一个函数,返回StackAsArray内部类Iter,这是一个迭代器模式的典型应用:
class StackAsArray::Iter : public Iterator
{
StackAsArray const& stack;
unsigned int position;
public:
Iter (StackAsArray const& _stack);
// ...
bool IsDone () const;
Object& operator * () const;
void operator ++ ();
void Reset ();
};
StackAsArray::Iter::Iter( StackAsArray const& _stack )
:stack (_stack)
{
Reset();
}
bool StackAsArray::Iter::IsDone() const
{
return position >= stack.count;
}
Object& StackAsArray::Iter::operator*() const
{
if (position < stack.count)
{
return *stack.array[position];
}
else
{
return NullObject::Instance ();
//return NULL;
}
}
void StackAsArray::Iter::operator++()
{
if (position < stack.count)
{
++position;
}
}
void StackAsArray::Iter::Reset()
{
position = 0;
}
接下来看栈的链表实现方式:
class StackAsLinkedList : public Stack
{
LinkedList<Object*> list;
class Iter;
public:
StackAsLinkedList ();
~StackAsLinkedList ();
void Purge();
void Accept (Visitor& visitor) const;
Iterator& NewIterator() const;
// ...
void Push (Object& object);
Object& Pop ();
Object& Top () const;
friend class Iter;
};
class StackAsLinkedList::Iter : public Iterator
{
StackAsLinkedList const& stack;
ListElement<Object*> const* position;
public:
Iter (StackAsLinkedList const& _stack);
// ...
bool IsDone () const;
Object& operator * () const;
void operator ++ ();
void Reset ();
};
StackAsLinkedList::StackAsLinkedList()
:list()
{
}
void StackAsLinkedList::Purge()
{
if (IsOwner ())
{
ListElement<Object*> const* ptr;
for (ptr = list.Head (); ptr != 0; ptr = ptr->Next ())
{
delete ptr->Datum ();
}
}
list.Purge ();
count = 0;
}
StackAsLinkedList::~StackAsLinkedList()
{
Purge();
}
void StackAsLinkedList::Push( Object& object )
{
list.Prepend (&object);
++count;
}
Object& StackAsLinkedList::Pop()
{
if (count == 0)
{
throw domain_error ("stack is empty");
}
Object& result = *list.First ();
list.Extract (&result);
--count;
return result;
}
Object& StackAsLinkedList::Top() const
{
if (count == 0)
{
throw domain_error ("stack is empty");
}
return *list.First ();
}
void StackAsLinkedList::Accept( Visitor& visitor ) const
{
ListElement<Object*> const* ptr;
for (ptr = list.Head ();
ptr != 0 && !visitor.IsDone (); ptr = ptr->Next ())
{
visitor.Visit (*ptr->Datum ());
}
}
Iterator& StackAsLinkedList::NewIterator() const
{
return *new StackAsLinkedList::Iter(*this);
}
StackAsLinkedList::Iter::Iter( StackAsLinkedList const& _stack )
:stack (_stack)
{
Reset ();
}
bool StackAsLinkedList::Iter::IsDone() const
{
return position == 0;
}
Object& StackAsLinkedList::Iter::operator*() const
{
if (position != 0)
{
return *position->Datum ();
}
else
{
return NullObject::Instance ();
}
}
void StackAsLinkedList::Iter::operator++()
{
if (position != 0)
{
position = position->Next ();
}
}
void StackAsLinkedList::Iter::Reset()
{
position = stack.list.Head ();