栈的分类:顺序栈,链栈,双向栈。
①顺序栈,即栈的顺序存储结构(数组),是利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素,同时附设指针top指示栈顶元素在顺序栈中的位置。当top=-1时候,表示为空栈。 由于顺序栈的操作位置基本在栈顶,所以,不需要查找插入和删除的位置,也不需要移动元素,因而顺序栈的基本操作要比顺序表简单的多,其基本操作时间复杂度均为O(1)
②链栈,栈的另外一种存储方式是链式存储,这样的栈称为链栈(Linked Stack)。 链栈通常用单链表来表示,它的实现是单链表的简化。 由于链栈的操作只是在一端进行,为了操作方便,把栈顶设在链表的头部。 单链表获取长度需要遍历整个链表,性能很低,所以我们增加一个count属性记录元素个数。
③双向栈是两个栈高效共享同一数组空间的简捷方法,他是将两个栈的栈底设在数组空间的两端,两个栈顶指针分别向中间移动,即数据压入左栈时,左栈的栈顶指针+1,数据压入右栈时,右栈的栈顶指针-1,如下图:这样左右两个栈可以互相调节空间,逻辑上可以使用整个数组空间,只有在整个数组空间被两个栈占满时才会发生上溢,这样产生上溢出的概率会比两个独立设置时小的多。
今天主要实现链栈。
namespace Stack
{
class StackNode<T>
{
public T data;
public StackNode<T> next;
public StackNode(T value) {
this.data = value;
}
public StackNode() { }
public override string ToString()
{
return data.ToString();
}
}
}
namespace Stack
{
interface IStackDS<T>
{
int Count { get; }//元素个数
int GetLength();
bool IsEmpty(); //是否为空栈
void Clear(); //清空
void Push(T item); //入栈操作
T Pop(); //返回栈顶数据并且出栈
T Peek(); //取栈顶元素,不出栈
}
}
using System;
namespace Stack
{
class LinkedStack<T> : IStackDS<T>
{
//栈顶指针
public StackNode<T> top;
//元素个数
public int count = 0;
public int Count {
get {
return count;
}
}
public void Clear()
{
count = 0;
top = null;
}
public int GetLength()
{
return Count;
}
public bool IsEmpty()
{
return count == 0;
}
public T Peek()
{
if (top == null) {
throw new ArgumentOutOfRangeException("栈下溢,栈内没有数据");
}
return top.data;
}
public T Pop()
{
if (top == null)
{
throw new ArgumentOutOfRangeException("栈下溢,栈内没有数据");
}
T r = top.data;
top = top.next;
count--;
return r;
}
public void Push(T item)
{
StackNode<T> newNode = new StackNode<T>(item);
newNode.next = top;
top = newNode;
count++;
}
}
}