线性表
栈和队列属于线性结构,线性表、栈和队列这三种数据结构的数据元素以及数据元素间的逻辑关系完全相同。
差别是线性表的操作不受限制,而栈和队列的操作受到限制。
栈的操作只能在表的一端进行,队列的插入操作在表的一端进行而其它操作在表的另一端进行,所以,把栈和队列称为操作受限的线性表。
1、栈接口
/// <summary> /// 栈的接口定义 /// </summary> /// <typeparam name="T"></typeparam> public interface IStack<T> { int GetLength(); //获得栈的长度 bool IsEmpty(); //判空 //bool IsFull(); //是否满 void Clear(); //清空 void Push(T t); //入栈 T Pop(); //出栈 T GetTop(); //取栈顶元素 }
2、顺序栈
/// <summary> /// 1、顺序栈 用一片连续的存储空间来存储栈中的数据元素 /// </summary> /// <typeparam name="T"></typeparam> public class SeqStack<T> : IStack<T> { private int maxsize;//栈的容量 private T[] data;//数组表示,存放栈元素 private int top;//栈顶 public T this[int index] { get { return data[index]; } set { data[index] = value; } } public int MaxSize { get { return this.maxsize; } set { this.maxsize = value; } } public int Top { get { return this.top; } set { this.top = value; } } public SeqStack(int i) { this.maxsize = i; this.data = new T[i]; this.top = -1; } public int GetLength() { return this.top + 1; } public void Clear() { this.top = -1; } public bool IsEmpty() { if (this.top == -1) return true; else return false; } public bool IsFull() { if (top == maxsize - 1) { return true; } else { return false; } } public void Push(T t) { if (IsFull()) { Console.WriteLine("-----满了------"); return; } data[++top] = t; } public T Pop() { T tmp = default(T); if (IsEmpty()) { Console.WriteLine("----已经空了----"); return tmp; } tmp = data[top]; --top; return tmp; } public T GetTop() { T tmp = default(T); if (IsEmpty()) { Console.WriteLine("----已经空了----"); return tmp; } tmp = data[top]; return tmp; } }
3、链栈
/// <summary> /// 2、链栈 链式存储 单链表表示 /// </summary> /// <typeparam name="T"></typeparam> public class LinkStack<T> : IStack<T> { StackNode<T> top; private int num;//栈中节点数 public StackNode<T> Top { get { return this.top; } set { this.top = value; } } public int Num { get { return this.num; } set { this.num = value; } } public LinkStack() { this.top = null; this.num = 0; } public int GetLength() { return num; } public bool IsEmpty() { if ((top == null) && (num == 0)) { return true; } else { return false; } } //public bool IsFull() //{ // top = null; // num = 0; //} public void Push(T t) { StackNode<T> q = new StackNode<T>(t); if (IsEmpty()) { top = q; } else { q.Next = top; top = q; } ++num; } public T Pop() { if (IsEmpty()) { Console.WriteLine("------已经空了-----"); return default(T); } StackNode<T> tmp = top; top = top.Next; --num; return tmp.Data; } public T GetTop() { if (IsEmpty()) { Console.WriteLine("----空了----"); return default(T); } return top.Data; } public void Clear() { this.num = 0; this.top = null; } } public class StackNode<T> { private T data; private StackNode<T> next; public T Data { get { return this.data; } set { this.data = value; } } public StackNode<T> Next { get { return this.next; } set { this.next = value; } } public StackNode() { this.data = default(T); this.next = null; } public StackNode(T t) { this.data = t; this.next = null; } }
4、例子
public class OpStack { //数制转换问题。数制转换问题是将任意一个非负的十进制数转换为其它进制的数 //算法思想如下:当 N>0 时,重复步骤 1 和步骤 2。 //步骤 1:若 N≠0,则将 N%8 压入栈中,执行步骤 2;若 N=0。则将栈的内 //容依次出栈,算法结束。 //步骤 2:用 N/8 代替 N,返回步骤 1。 public void Conversion(int n) { LinkStack<int> stack = new LinkStack<int>(); while (n > 0) { stack.Push(n % 8); n = n / 8; } while (!stack.IsEmpty()) { n = stack.Pop(); Console.WriteLine("{0}", n); } } public void Run() { Conversion(2002); } }
* C#中的栈:
* C#2.0以下版本提供非泛型的栈,继承自接口ICollection,IEnumerable和ICloneable。
* C#2.0以上版本提供泛型栈(Stack<T>),继承自接口IEnumerable<T>, ICollection, IEnumerable。
5、队列接口
/// <summary> /// 队列的接口定义 /// </summary> /// <typeparam name="T"></typeparam> public interface IQueue<T> { int GetLength(); //求队列的长度 bool IsEmpty(); //判断对列是否为空 void Clear(); //清空队列 void In(T item); //入队 T Out(); //出队 T GetFront(); //取队列头元素 }
6、顺序队列
/// <summary> ///1、顺序队列 用一片连续的存储空间来存储队列中的数据元素 /// </summary> public class SeqQueue<T> : IQueue<T> { private int maxsize; //顺序队列的容量 private T[] data; //数组, 用于存储顺序队列中的数据元素 private int front; //指示循环顺序队列的队头 private int rear; //指示循环顺序队列的队尾 //索引器 public T this[int index] { get { return data[index]; } set { data[index] = value; } } //容量 public int Maxsize { get { return maxsize; } set { maxsize = value; } } //队头 public int Front { get { return front; } set { front = value; } } //队尾 public int Rear { get { return rear; } set { rear = value; } } //构造器 public SeqQueue(int size) { data = new T[size]; maxsize = size; front = rear = -1; } //队列长度 public int GetLength() { return (rear - front + maxsize) % maxsize; } //清空队列 public void Clear() { front = -1; rear = -1; } //判空 public bool IsEmpty() { if (front == rear) { return true; } else { return false; } } //判是否满 public bool IsFull() { if ((rear + 1) % maxsize==front) { return true; } else { return false; } } //入队 public void In(T item) { if (IsFull()) { Console.WriteLine("----已经空了----"); return; } data[++rear] = item; } //出队 public T Out() { T tmp = default(T); if (IsEmpty()) { Console.WriteLine("----已经空了----"); return tmp; } tmp = data[++front]; return tmp; } //获取队头 public T GetFront() { if (IsEmpty()) { Console.WriteLine("----已经空了----"); return default(T); } return data[front + 1]; } }
7、链队列
//链队列类 class LinkedQueue<T>:IQueueDs<T> { private Node<T> nFront; private Node<T> nRear;//以空间换时间的策略 private int intNum; public Node<T> Front { get { return this.nFront; } set { this.nFront = value; } } public Node<T> Rear { get { return this.nRear; } set { this.nRear = value; } } public int Num { get { return this.intNum; } set { this.intNum = value; } } public LinkedQueue() { this.nFront = null; this.nRear = null; this.intNum = 0; } public LinkedQueue(T t) { Node<T> node = new Node<T>(t); this.nFront = node; this.nRear = node; this.intNum = 1; } #region IQueueDs<T> 成员 public int GetLength() { return this.intNum; } public bool IsEmpty() { return this.intNum == 0; } public bool IsFull() { Console.WriteLine("No limit for LinkedQueue!"); return false; } public void In(T t) { Node<T> node = new Node<T>(t); if (this.IsEmpty()) { this.nFront = node; this.nRear = node; this.intNum++; return; } this.nRear.Next = node; this.nRear = node; this.intNum++; } public T Out() { if (this.IsEmpty()) { Console.WriteLine("No more elements!"); return default(T); } else { Node<T> node = this.nFront; this.nFront = node.Next; this.intNum--; return node.Val; } } public T GetFront() { if (!this.IsEmpty()) { return this.nFront.Val; } else { Console.WriteLine("The queue has no elements!"); return default(T); } } #endregion }
//链队列的结点类 class Node<T> { private T tVal; private Node<T> nNext; public T Val { get { return this.tVal; } set { this.tVal = value; } } public Node<T> Next { get { return this.nNext; } set { this.nNext = value; } } public Node() { this.tVal = default(T); this.nNext = null; } public Node(T t) { this.tVal = t; this.nNext = null; } }
8、例子
/// <summary> /// 队列例子 /// 编程判断一个字符串是否是回文。回文是指一个字符序列以中间字符 /// 为基准两边字符完全相同,如字符序列'ACBDEDBCA'是回文。 /// </summary> public class OpQueue { public void Run() { SeqStack<char> s = new SeqStack<char>(50); SeqQueue<char> q = new SeqQueue<char>(50); string str = Console.ReadLine(); for(int i = 0; i < str.Length; ++i) { s.Push(str[i]); q.In(str[i]); } while(!s.IsEmpty() && !q.IsEmpty()) { if(s.Pop() != q.Out()) { break; } } if(!s.IsEmpty() || !q.IsEmpty()) { Console.WriteLine("这不是回文!"); } else { Console.WriteLine("这是回文!"); } } }
* C#中的队列:
* C#2.0以下版本提供非泛型的队列,继承自接口ICollection,IEnumerable和ICloneable。
* C#2.0以上版本提供泛型队列(Queue<T>),继承自接口IEnumerable<T>, ICollection, IEnumerable。
小结:
1)栈和队列是操作受限的线性表。
2)栈和队列有两种存储结构,顺序存储结构和链式存储结构
3)栈是先进后出的线性表,适用于括号匹配、表达式求值等问题。
4)队列的删除操作在队头进行,而插入、查找等操作在队尾进行
5)队列是先进先出的线性表,适用于排队等问题