隊列(Queue)是插入操作限定在表的尾部而其他操作限定在表的頭部進行的線性表。把進行插入操作的表尾稱為隊尾(Rear).把進行其他操作的頭部稱為隊頭(Front).
隊列的操作使按照先進先出后進后出的原則進行的。
用一片連續的存儲空間來存儲隊列中的數據元素,稱為順序隊列(Sequence Queue)。類似於順序表,用一維數組來存放隊列中的數據元素。
解決順序隊列的假溢出的方法是將順序隊列看成是首位相接的循環結構,叫循環順序隊列(Circular sequence Queue)。
隊列的另外一種存儲方式是鏈式存儲,稱為鏈隊列(Linked Queue)。通常用單鏈表表示。
Queue using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace DataStructure { /// <summary> /// 隊列接口 /// </summary> interface IQueue<T> { void EnQueue(T elem); //入隊列操作 T DeQueue(); //出隊列操作 T GetFront(); //取對頭元素 int GetLength(); //求隊列的長度 bool IsEmpty(); //判斷隊列是否為空 void Clear(); //清空隊列 bool IsFull(); //判斷隊列是否為滿 } /// <summary> /// 銀行隊列接口 /// </summary> interface IBankQueue : IQueue<int> { int GetCallnumber(); //獲取服務號碼 } /// <summary> /// 循環順序隊列 /// </summary> /// <typeparam name="T"></typeparam> 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() { } public CSeqQueue(int size) { data = new T[size]; maxsize = size; front = rear = -1; } //判斷循環順序隊列是否為滿 public bool IsFull() { if ((front == -1 && rear == maxsize - 1) || (rear + 1) % maxsize == front) return true; else return false; } //清空循環順序列表 public void Clear() { front = rear = -1; } //判斷循環順序隊列是否為空 public bool IsEmpty() { if (front == rear) return true; else return false; } //入隊操作 public void EnQueue(T elem) { if (IsFull()) { Console.WriteLine("Queue is Full !"); return; } rear = (rear + 1) % maxsize; data[rear] = elem; } //出隊操作 public T DeQueue() { if (IsEmpty()) { Console.WriteLine("Queue is Empty !"); return default(T); } front = (front + 1) % maxsize; return data[front]; } //獲取對頭數據元素 public T GetFront() { if (IsEmpty()) { Console.WriteLine("Queue is Empty !"); return default(T); } return data[(front + 1) % maxsize];//front從-1開始 } //求循環順序隊列的長度 public int GetLength() { return (rear - front + maxsize) % maxsize; } } /// <summary> /// 鏈隊列結點類 /// </summary> /// <typeparam name="T"></typeparam> class QueueNode<T> { private T data; //數據域 private QueueNode<T> next; //引用域 public QueueNode(T val, QueueNode<T> p) { data = val; next = p; } public QueueNode(QueueNode<T> p) { next = p; } public QueueNode(T val) { data = val; next = null; } public QueueNode() { data = default(T); next = null; } //數據域屬性 public T Data { get { return data; } set { data = value; } } //引用域屬性 public QueueNode<T> Next { get { return next; } set { next = value; } } } /// <summary> /// 鏈隊列類 /// </summary> /// <typeparam name="T"></typeparam> class LinkQueue<T> : IQueue<T> { private QueueNode<T> front; //隊列頭指示器 private QueueNode<T> rear; //隊列尾指示器 private int size; //隊列結點個數 //隊列屬性 public QueueNode<T> Front { get { return front; } set { front = value; } } public QueueNode<T> Rear { get { return rear; } set { rear = value; } } public int Size { get { return size; } set { size = value; } } //初始化鏈隊列 public LinkQueue() { front = rear = null; size = 0; } public int GetLength() { return size; } public void Clear() { front = rear = null; size = 0; } public bool IsEmpty() { if ((front == rear) && (size == 0)) return true; else return false; } //鏈隊列沒有容量限制 返回false public bool IsFull() { return false; } //入隊操作 public void EnQueue(T item) { QueueNode<T> q = new QueueNode<T>(item); if (IsEmpty()) { front = q; rear = q; } else { rear.Next = q; rear = q; } ++size; } //出對操作 public T DeQueue() { if (IsEmpty()) { Console.WriteLine("Queue is Empty !"); return default(T); } QueueNode<T> p = front; front = front.Next; if (front == null) { rear = null; } --size; return p.Data; } //獲取鏈隊列頭結點的值 public T GetFront() { if (IsEmpty()) { Console.WriteLine("Queue is Empty !"); return default(T); } return front.Data; } } /// <summary> /// 銀行叫號鏈隊列類 /// </summary> class LinkBankQueue : LinkQueue<int>, IBankQueue { private int callnumber; public int Callnumber { get { return callnumber; } set { callnumber = value; } } //獲取服務號碼 public int GetCallnumber() { if ((IsEmpty()) && callnumber == 0) { callnumber = 1; } else callnumber++; return callnumber; } } /// <summary> /// 銀行叫號順序隊列類 /// </summary> class CSeqBankQueue : CSeqQueue<int>, IBankQueue { private int callnumber; //記錄系統自動產生的新來顧客的服務號碼 public int Callnumber { get { return callnumber; } set { callnumber = value; } } public CSeqBankQueue() { } public CSeqBankQueue(int size) : base(size) { } //獲得服務號碼 public int GetCallnumber() { if ((IsEmpty()) && callnumber == 0) { callnumber = 1; } else { callnumber++; } return callnumber; } } /// <summary> /// 服務窗口類 /// </summary> class ServiceWindow { IBankQueue bankQ; //服務隊列屬性 public IBankQueue BankQ { get { return bankQ; } set { bankQ = value; } } public void Service() { while (true) { Thread.Sleep(10000); if (!bankQ.IsEmpty()) { Console.WriteLine(); lock (bankQ) { Console.WriteLine("請{0}號到{1}號窗口!", bankQ.DeQueue(), Thread.CurrentThread.Name); } } } } } class Queue { static void Main() { IBankQueue bankQueue = null; Console.WriteLine("請選擇存儲結構的類型:1.順序隊列 2.鏈隊列:"); char selectFlag = Convert.ToChar(Console.ReadLine()); switch (selectFlag) { /*初始化順序隊列*/ case '1': int count; //接受循環順序隊列的容量 Console.WriteLine("請輸入隊列可容納的人數:"); count = Convert.ToInt32(Console.ReadLine()); bankQueue = new CSeqBankQueue(count); break; /*初始化鏈隊列*/ case '2': bankQueue = new LinkBankQueue(); break; } int windowcount = 4; //設置銀行櫃台的服務窗口數 ServiceWindow[] sw = new ServiceWindow[windowcount]; Thread[] swt = new Thread[windowcount]; for (int i = 0; i < windowcount; i++) { sw[i] = new ServiceWindow(); sw[i].BankQ = bankQueue; swt[i] = new Thread(new ThreadStart(sw[i].Service)); swt[i].Name = "" + (i + 1); swt[i].Start(); } while (true) { Console.WriteLine("請點擊觸摸屏獲取號碼:"); Console.ReadLine(); int callnumber; if (!bankQueue.IsFull()) { callnumber = bankQueue.GetCallnumber(); Console.WriteLine("您的號碼是:{0},您前面有{1}位,請等待!", callnumber, bankQueue.GetLength()); bankQueue.EnQueue(callnumber); } else Console.WriteLine("現在業務繁忙,請稍后再來!"); Console.WriteLine(); } } } }