队列
顺序队列:用一片连续的存储空间来存储队列中的数据元素,这样的队列称为顺序队列(Sequence Queue)。用一维数组来存放顺序队列中的数据元素。队头位置设在数组下标为 0 的端,用 front 表示;队尾位置设在数组的另一端,用 rear 表示。 front 和 rear 随着插入和删除而变化。当队列为空时, front=rear=-1。
图是顺序队列的两个指示器与队列中数据元素的关系图。
入队:进队列的元素 从队首开始排 慢慢排到队尾
出队:出队列的元素 从队首开始出 一个个排下去
顺序队列-(循环顺序队列):如果再有一个数据元素入队就会出现溢出。但事实上队列中并未满,还有空闲空间,把这种现象称为“假溢出”。这是由于队列“队尾入队头出”的操作原则造成的。解决假溢出的方法是将顺序队列看成是首尾相接的循环结构,头尾指示器的关系不变,这种队列叫循环顺序队列(Circular sequence Queue)。循环队列如图所示。
来自系统的队列:
BCL 中的队列
C#2.0 以下版本提供了非泛型的Queue类
C#2.0 提供了泛型Queue<T>类
方法
1,Enqueue()入队(放在队首)
2,Dequeue()出队(移除队首元素,并返回被移除的元素)
3,Peek()取得队首的元素,不移除
4,Clear()清空元素
5,Count获取队列中元素的个数
程序实现:
//1.使用BCL中的队列 Queue<int> queue = new Queue<int>(); //入队 queue.Enqueue(23);//队首 queue.Enqueue(45); queue.Enqueue(67); queue.Enqueue(89); Console.Write("添加了23 45 67 89之后队列为:"); foreach (int a in queue) { Console.Write(a + " "); } Console.WriteLine(); Console.WriteLine("添加了23 45 67 89之后队列的大小为:"+queue.Count); //出队(取得队首的数据,并删除) int i = queue.Dequeue(); Console.WriteLine("取得队首的数据为:" + i); Console.WriteLine("出队之后队列的大小为:" + queue.Count); int j = queue.Peek(); Console.WriteLine("Peek得到的结果是:" + j); Console.WriteLine("Peek之后队列的大小为:" + queue.Count); queue.Clear(); Console.WriteLine("Clear之后队列的大小为:" + queue.Count); Console.ReadKey();
结果:
自己实现队列:
队列接口定义
internal interface IQueue<T> { int Count { get; } //取得队列长度的属性 int GetLength(); //求队列的长度 bool IsEmpty(); //判断对列是否为空 void Clear(); //清空队列 void Enqueue(T item); //入队 T Dequeue(); //出队 T Peek(); //取队头元素 }
顺序队列的实现:
class SeqQueue<T>:IQueue<T> { private T[] data; private int count;//表示当前有多少个元素 private int front;//队首(队首元素索引减一) private int rear;//队尾(队尾元素索引) //构造函数 public SeqQueue(int size) { data=new T[size]; count = 0; front = -1; rear = -1; } //默认构造函数 public SeqQueue() : this(10) { } //返回队列内数量 public int Count { get { return count; } } //取得队列长度 public int GetLength() { return count; } //判断队列是否唯为空 public bool IsEmpty() { return count == 0; } //清除队列 public void Clear() { count = 0; front = rear = -1; } //往队列里添加 public void Enqueue(T item) { if (count==data.Length) { Console.WriteLine("队列已满,不可以再添加新的数据"); } else { if (rear == data.Length-1) { data[0] = item; rear = 0; } else { data[rear + 1] = item; rear++; } count++; } } //移除队首元素 并返回该值 public T Dequeue() { if (count > 0) { T temp = data[front + 1]; front++; count--; return temp; } else { Console.WriteLine("队列为空,无法取得队首的数据"); return default(T); } } //取得队首元素 不移除 public T Peek() { T temp = data[front + 1]; return temp; } }
结果和之前是一样的,在这里就不贴出了。
栈队列:队列的另外一种存储方式是链式存储,这样的队列称为链队列(Linked Queue)。链队列通常用单链表来表示,它的实现是单链表的简化。所以,链队列的结点的结构与单链表一样,如图所示。由于链队列的操作只是在一端进行,为了操作方便,把队头设在链表的头部,并且不需要头结点。
链队列结点类:
class Node<T> { private T data;//数据域 private Node<T> next;//引用域 //构造方法 public Node(T data) { this.data = data; } //数据域属性 public T Data { get { return data; } set { data = value; } } //引用域属性 public Node<T> Next { get { return next; } set { next = value; } } }
栈队列的实现:
class LinkQueue<T>:IQueue<T> { private Node<T> front;//头结点 private Node<T> rear;//尾节点 private int count;//表示元素的个数 public LinkQueue() { front = null; rear = null; count = 0; } public int Count { get { return count; } } public int GetLength() { return count; } public bool IsEmpty() { return count == 0; } public void Clear() { front = null; rear = null; count = 0; } public void Enqueue(T item) { Node<T> newNode=new Node<T>(item); if (count == 0) { front = newNode; rear = newNode; count = 1; } else { rear.Next = newNode; rear = newNode; count++; } } public T Dequeue() { if (count == 0) { Console.WriteLine("对列为空,无法出队"); return default(T); } else if (count == 1) { T item = front.Data; front = rear = null; count = 0; return item; } else { T item = front.Data; front = front.Next; count--; return item; } } public T Peek() { if (front != null) { return front.Data; } else { return default(T); } } }
结果同上。