在.net中,值类型在栈上分配,引用类型在托管堆上分配。栈,是线性表的特例,只能对线性表的一端进行插入和删除操作。“先进后出” 或者 “后进先出” 的特点。示意图如下:
1.栈顶:允许进行数据删除和插入操作的一端
2.栈底: 不允许在栈中操作的一端
3.Push: 进栈,将元素放入栈顶处
4.Pop :取出栈顶元素并删除栈中数据
5.Peek:取出栈顶元素,不删除数据在栈中
栈的简单实现:
//存放元素的数组
private object[] _array;
//默认空间大小
private const int _defaultCapacity = 10;
//元素个数
private int _size;
public int Size
{
get
{
return _size;
}
}
public MyStack()
{
this._array = new object[_defaultCapacity];
this._size = 0;
}
public MyStack(int InitCapacity)
{
if (InitCapacity<0)
{
throw new ArgumentOutOfRangeException("Stack Space Cant Less Zero");
}
if (InitCapacity<_defaultCapacity)
{
InitCapacity = _defaultCapacity;
}
//分配栈空间
this._array = new object[InitCapacity];
this._size = 0;
}
当可以预见栈所操作元素大概个数的时候,可以使用第二种构造函数,在一定程度上可以避免数组重复创建和数据的迁移,提高性能,减少内存中垃圾回收的压力。
进栈:
//进栈
public void Push(object obj)
{
//栈已满
if (this._size==this._array.Length)
{
object[] newArray = new object[this._array.Length * 2];
//从一个数组copy 到另一个数组,从哪里开始,copy 多长
Array.Copy(this._array, 0, newArray, 0, this._size);
this._array = newArray;
}
//将新元素放到栈顶,索引为size,之后 size+1
this._array[this._size++] = obj;
}
出栈:
//出栈
public object Pop()
{
if (_size == 0)
{
throw new InvalidOperationException("栈内无元素");
}
object obj = this._array[--this._size];
//删除栈顶元素
this._array[this._size] = null;
return obj;
}
在Stack中指向栈顶的指针实际为元素个数size,栈顶元素在数组中索引比它小一。size为0,表空栈。