数据结构线性表之队列
队列(Queue)是插入操作限定在表的尾部而其它操作限定在表的头部进行的线性表。把进行插入操作的表尾称为队尾(Rear),把进行其它操作的头部称为队 头(Front)。当对列中没有数据元素时称为空对列(Empty Queue)。
队列Q的操作示意图如图 3.6 所示。

队列的形式化定义为:队列(Queue)简记为 Q,是一个二元组, Q = (D, R)
其中:D 是数据元素的有限集合;
R 是数据元素之间关系的有限集合。
队列接口 IQueue的定义如下所示。
public interface IQueue<T> { int GetLength(); //求队列的长度 bool IsEmpty(); //判断对列是否为空 void Clear(); //清空队列 void In(T item); //入队 T Out(); //出队 T GetFront(); //取对头元素 }
1、顺序队列
用一片连续的存储空间来存储队列中的数据元素,这样的队列称为顺序队列 (Sequence Queue)。类似于顺序栈,用一维数组来存放顺序队列中的数据元素。
图 3.7 是顺序队列的两个指示器与队列中数据元素的关系图。

由图 3.7(d)可知,如果再有一个数据元素入队就会出现溢出。但事实上队列 中并未满,还有空闲空间,把这种现象称为“假溢出”。这是由于队列“队尾入 队头出”的操作原则造成的。解决假溢出的方法是将顺序队列看成是首尾相接的 循环结构,头尾指示器的关系不变,这种队列叫循环顺序队列(Circular sequence Queue)。循环队列如图 3.8 所示。

循环顺序队列类 CSeqQueue的实现说明如下所示。
public class CSeqQueue<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 CSeqQueue(int size) { data = new T[size]; maxsize = size; front = rear = -1; } //求循环顺序队列的长度 public int GetLength() { return (rear - front + maxsize) % maxsize; } //清空循环顺序队列 public void Clear() { front = 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("Queue is full"); return; } data[++rear] = item; } //出队 public T Out() { T tmp = default(T); if (IsEmpty()) { Console.WriteLine("Queue is empty"); return tmp; } tmp = data[++front]; return tmp; } //获取队头数据元素 public T GetFront() { if (IsEmpty()) { Console.WriteLine("Queue is empty!"); return default(T); } return data[front + 1]; } }
2、链队列
队列的另外一种存储方式是链式存储,这样的队列称为链队列(Linked Queue)。同链栈一样,链队列通常用单链表来表示,它的实现是单链表的简化。 所以,链队列的结点的结构与单链表一样,如图 3.10 所示。

链队列结点类(Node)的实现如下所示:
public class Node<T> { private T data; //数据域 private Node<T> next; //引用域 //构造器 public Node(T val, Node<T> p) { data = val; next = p; } //构造器 public Node(Node<T> p) { next = p; } //构造器 public Node(T val) { data = val; next = null; } //构造器 public Node() { data = default(T); next = null; } //数据域属性 public T Data { get { return data; } set { data = value; } } //引用域属性 public Node<T> Next { get { return next; } set { next = value; } } }

链队列类 LinkQueue的实现说明如下所示。
public class LinkQueue<T> : IQueue<T> { private Node<T> front; //队列头指示器 private Node<T> rear; //队列尾指示器 private int num; //队列结点个数 //队头属性 public Node<T> Front { get { return front; } set { front = value; } } //队尾属性 public Node<T> Rear { get { return rear; } set { rear = value; } } //队列结点个数属性 public int Num { get { return num; } set { num = value; } } //构造器 public LinkQueue() { front = rear = null; num = 0; } //求链队列的长度 public int GetLength() { return num; } //清空链队列 public void Clear() { front = rear = null; num = 0; } //判断链队列是否为空 public bool IsEmpty() { if ((front == rear) && (num == 0)) { return true; } else { return false; } } //入队 public void In(T item) { Node<T> q = new Node<T>(item); if (rear == null) { rear = q; } else { rear.Next = q; rear = q; } ++num; } //出队 public T Out() { if (IsEmpty()) { Console.WriteLine("Queue is empty!"); return default(T); } Node<T> p = front; front = front.Next; if (front == null) { rear = null; } --num; return p.Data; } //获取链队列头结点的值 public T GetFront() { if (IsEmpty()) { Console.WriteLine("Queue is empty!"); return default(T); } return front.Data; } }

浙公网安备 33010602011771号