栈(Stack)是操作限定在表的尾端进行的线性表。表尾由于要进行插入、删除等操作,所以,它具有特殊的含义,把表尾称为栈顶(Top),另一端是固定的,叫栈底(Bottom)。当栈中没有数据元素时叫空栈(Empty Stack)。
栈的操作是按照后进先出(Last In First Out,简称LIFO)或先进后出(First In Last Out,简称FILO)的原则进行的,因此,栈又称为LIFO表或FILO表。
操作示意图:
顺序栈
用一片连续的存储空间来存储栈中的数据元素,这样的栈称为顺序栈(Sequence Stack)。类似于顺序表,用一维数组来存放顺序栈中的数据元素。栈顶指示器top设在数组下标为0的端,top随着插入和删除而变化,当栈为空时,top=-1。下图是顺序栈的栈顶指示器top与栈中数据元素的关系图。
下面对栈的基本操作进行说明。
1、求栈的长度:GetLength()
初始条件:栈存在;
操作结果:返回栈中数据元素的个数。
2、判断栈是否为空:IsEmpty()
初始条件:栈存在;
操作结果:如果栈为空返回true,否则返回false。
3、清空操作:Clear()
初始条件:栈存在;
操作结果:使栈为空。
4、入栈操作:Push(T item)
初始条件:栈存在;
操作结果:将值为item的新的数据元素添加到栈顶,栈发生变化。
5、出栈操作:Pop()
初始条件:栈存在且不为空;
操作结果:将栈顶元素从栈中取出,栈发生变化。
6、取栈顶元素:GetTop()
初始条件:栈表存在且不为空;
操作结果:返回栈顶元素的值,栈不发生变化。
下面我们来看一下代码实现
1 public class StackDemo<T> : IEnumerable<T> 2 { 3 private T[] data;//数组,用来存储顺序栈中数据的元素 4 private int top; //顺序栈的栈顶 5 private int maxsize; //顺序栈的容量 6 7 public StackDemo(int size)//构造器 8 { 9 data = new T[size]; 10 maxsize = size; 11 top = -1; 12 } 13 14 public T this[int index] 15 { 16 get { return data[index]; } 17 set { data[index] = value; } 18 } 19 public int MaxSize 20 { 21 get { return maxsize; } 22 set { maxsize = value; } 23 } 24 25 public bool IsEmpty() 26 { 27 if (top==maxsize-1) 28 { 29 return true; 30 } 31 else 32 { 33 return false; 34 } 35 } 36 37 public int GetLength() 38 { 39 return top + 1; 40 } 41 42 public void Push(T item) 43 { 44 if (IsEmpty()) 45 { 46 Console.WriteLine("栈已满!!!"); 47 } 48 else 49 { 50 data[++top] = item; 51 } 52 } 53 54 public T Pop() 55 { 56 T temp = default(T); 57 if (top==-1) 58 { 59 Console.WriteLine("栈没有元素!!!"); 60 return temp; 61 } 62 else 63 { 64 temp = data[top]; 65 66 top--; 67 return temp; 68 } 69 } 70 71 public T Top() 72 { 73 return data[top]; 74 } 75 76 public void Clear() 77 { 78 top = -1; 79 } 80 81 public IEnumerator<T> GetEnumerator() 82 { 83 84 for (int i = top; i >=0; i--) 85 { 86 yield return data[i]; 87 } 88 } 89 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 90 { 91 throw new NotImplementedException(); 92 } 93 }
要实现foreach遍历必须实现IEnumerable 接口 和GetEnumerator()
yield return 在迭代器块中用于向枚举数对象提供值或发出迭代结束信号
下面我们来使用一下我们模拟的栈
private static void Main(string[] args) { StackDemo<int> stackDemo=new StackDemo<int>(5); stackDemo.Push(1); stackDemo.Push(2); stackDemo.Push(3); stackDemo.Push(4); stackDemo.Push(5); //Console.WriteLine(stackDemo.Pop()+" "); //Console.WriteLine(stackDemo.Top() + " "); //Console.WriteLine(stackDemo.GetLength() + " "); //stackDemo.Clear(); foreach (var item in stackDemo) { Console.WriteLine(item); } Console.ReadKey(); }