后进先出结构:栈
栈(Stack)是操作限定在表的尾端进行的线性表。表尾由于要进行插入、删除等操作,所以,它具有特殊的含义,把表尾称为栈顶( Top),另一端是固定的,叫栈底( Bottom)。当栈中没有数据元素时叫空栈(Empty Stack)。
栈通常记为: S= (a1,a2,…,an),S是英文单词stack的第 1 个字母。a1为栈底元素,an为栈顶元素。这n个数据元素按照a1,a2,…,an的顺序依次入栈,而出栈的次序相反,an第一个出栈,a1最后一个出栈。所以,栈的操作是按照后进先出(Last In First Out,简称LIFO)或先进后出(First In Last Out,简称FILO)的原则进行的,因此,栈又称为LIFO表或FILO表。栈的操作示意图如图所示。
BCL中的栈
C#2.0 一下版本只提供了非泛型的Stack类(存储object类型)
C#2.0 提供了泛型的Stack<T>类
重要的方法如下
1,Push()入栈(添加数据)
2,Pop()出栈(删除数据,返回被删除的数据)
3,Peek()取得栈顶的数据,不删除
4,Clear()清空所有数据
5,Count取得栈中数据的个数
程序操作:
//1.使用BCL中的Stsck 栈类 Stack<char> stack=new Stack<char>(); //2.使用我们自己的顺序栈 //IStackDS<char> stack=new SeqStack<char>(30); //3.使用我们自己的链栈 //IStackDS<char> stack=new LinkStackle<char>(); stack.Push('a'); stack.Push('b'); stack.Push('c'); Console.WriteLine("push a b c之后的数据个数为:" + stack.Count); char temp = stack.Pop();//取得栈顶数据,并把它删除 Console.WriteLine("pop之后得到的数据为"+temp); Console.WriteLine("pop之后的数据个数为:" + stack.Count); char temp2 = stack.Peek();//取得栈顶数据,不删除 Console.WriteLine("peek之后得到的数据为" + temp2); Console.WriteLine("peek之后的数据个数为:" + stack.Count); stack.Clear(); Console.WriteLine("clear之后的数据个数为:" + stack.Count); Console.ReadKey();
结果显示:
自己实现的栈:
栈的接口定义:
interface IStackDS<T> { int Count { get; }//栈内数量 int GetLength();//求栈的长度 bool IsEmpty();//判断栈是否为空 void Clear();//清空操作 void Push(T item);//入栈操作 T Pop();//出栈操作 T Peek();//取栈顶元素 }
顺序栈:用一片连续的存储空间来存储栈中的数据元素(使用数组),这样的栈称为顺序栈(Sequence Stack)。类似于顺序表,用一维数组来存放顺序栈中的数据元素。栈顶指示器 top 设在数组下标为 0 的端, top 随着插入和删除而变化,当栈为空时,top=-1。下图是顺序栈的栈顶指示器 top 与栈中数据元素的关系图。
程序实现:
class SeqStack<T>:IStackDS<T> { private T[] data; private int top; public SeqStack(int size) { data = new T[size]; top = -1; } public SeqStack() : this(10) { } public int Count { get { return top + 1; } } public int GetLength() { return Count; } public bool IsEmpty() { return Count == 0; } public void Clear() { top = -1; } public void Push(T item) { data[top + 1] = item; top++; } public T Pop() { T temp = data[top]; top--; return temp; } public T Peek() { return data[top]; } }
链栈:栈的另外一种存储方式是链式存储,这样的栈称为链栈(Linked Stack)。链栈通常用单链表来表示,它的实现是单链表的简化。所以,链栈结点的结构与单链表结点的结构一样,如图 3.3 所示。由于链栈的操作只是在一端进行,为了操作方便,把栈顶设在链表的头部,并且不需要头结点。
链栈结点实现:
class Node<T> { private T data; private Node<T> next; public Node() { data = default(T); next = null; } public Node(T data) { this.data = data; next = null; } public Node(T data, Node<T> next) { this.data = data; this.next = next; } public Node(Node<T> next) { this.next = next; data = default(T); } public T Data { get { return data; } set { data = value; } } public Node<T> Next { get { return next; } set { next = value; } } }
程序实现:
class LinkStackle<T>:IStackDS<T> { private Node<T> top;//栈顶元素节点 private int count = 0;//栈中元素的个数 public int Count { get { return count; } } public int GetLength() { return count; } public bool IsEmpty() { return count == 0; } public void Clear() { count = 0; top = null; } public void Push(T item) { //把新添加的元素作为头节点(栈顶) Node<T> newNode=new Node<T>(item); newNode.Next = top; top = newNode; count++; } public T Pop() { T data = top.Data; top = top.Next; count--; return data; } public T Peek() { return top.Data; } }
看到这里 可以发现 多少有些相似。