(java版)html
(C版)前端
隊列也是表,使用隊列時,插入在一端進行,而刪除在另外一端進行。java
經常使用的操做:node
Queue.cpython
Queue接口與List、Set同一級別,都是繼承了Collection接口。LinkedList實現了Queue接 口。Queue接口窄化了對LinkedList的方法的訪問權限(即在方法中的參數類型若是是Queue時,就徹底只能訪問Queue接口所定義的方法 了,而不能直接訪問 LinkedList的非Queue的方法),以使得只有恰當的方法纔可使用。BlockingQueue 繼承了Queue接口。ios
隊列是一種數據結構.它有兩個基本操做:在隊列尾部加人一個元素,和從隊列頭部移除一個元素就是說,隊列以一種先進先出的方式管理數據,若是你試圖向一個 已經滿了的阻塞隊列中添加一個元素或者是從一個空的阻塞隊列中移除一個元索,將致使線程阻塞.在多線程進行合做時,阻塞隊列是頗有用的工具。工做者線程可 以按期地把中間結果存到阻塞隊列中而其餘工做者線線程把中間結果取出並在未來修改它們。隊列會自動平衡負載。若是第一個線程集運行得比第二個慢,則第二個 線程集在等待結果時就會阻塞。若是第一個線程集運行得快,那麼它將等待第二個線程集遇上來。下表顯示了jdk1.5中的阻塞隊列的操做:數組
add 增長一個元索 若是隊列已滿,則拋出一個IIIegaISlabEepeplian異常
remove 移除並返回隊列頭部的元素 若是隊列爲空,則拋出一個NoSuchElementException異常
element 返回隊列頭部的元素 若是隊列爲空,則拋出一個NoSuchElementException異常
offer 添加一個元素並返回true 若是隊列已滿,則返回false
poll 移除並返問隊列頭部的元素 若是隊列爲空,則返回null
peek 返回隊列頭部的元素 若是隊列爲空,則返回null
put 添加一個元素 若是隊列滿,則阻塞
take 移除並返回隊列頭部的元素 若是隊列爲空,則阻塞數據結構
remove、element、offer 、poll、peek 實際上是屬於Queue接口。 多線程
阻塞隊列的操做能夠根據它們的響應方式分爲如下三類:aad、removee和element操做在你試圖爲一個已滿的隊列增長元素或從空隊列取得元素時 拋出異常。固然,在多線程程序中,隊列在任什麼時候間均可能變成滿的或空的,因此你可能想使用offer、poll、peek方法。這些方法在沒法完成任務時 只是給出一個出錯示而不會拋出異常。app
注意:poll和peek方法出錯進返回null。所以,向隊列中插入null值是不合法的。
還有帶超時的offer和poll方法變種,例如,下面的調用:
boolean success = q.offer(x,100,TimeUnit.MILLISECONDS);
嘗試在100毫秒內向隊列尾部插入一個元素。若是成功,當即返回true;不然,當到達超時進,返回false。一樣地,調用:
Object head = q.poll(100, TimeUnit.MILLISECONDS);
若是在100毫秒內成功地移除了隊列頭元素,則當即返回頭元素;不然在到達超時時,返回null。
最後,咱們有阻塞操做put和take。put方法在隊列滿時阻塞,take方法在隊列空時阻塞。
java.ulil.concurrent包提供了阻塞隊列的4個變種。默認狀況下,LinkedBlockingQueue的容量是沒有上限的(說的不許確,在不指定時容量爲Integer.MAX_VALUE,不要然的話在put時怎麼會受阻呢),可是也能夠選擇指定其最大容量,它是基於鏈表的隊列,此隊列按 FIFO(先進先出)排序元素。
ArrayBlockingQueue在構造時須要指定容量, 並能夠選擇是否須要公平性,若是公平參數被設置true,等待時間最長的線程會優先獲得處理(其實就是經過將ReentrantLock設置爲true來 達到這種公平性的:即等待時間最長的線程會先操做)。一般,公平性會使你在性能上付出代價,只有在的確很是須要的時候再使用它。它是基於數組的阻塞循環隊 列,此隊列按 FIFO(先進先出)原則對元素進行排序。
PriorityBlockingQueue是一個帶優先級的 隊列,而不是先進先出隊列。元素按優先級順序被移除,該隊列也沒有上限(看了一下源碼,PriorityBlockingQueue是對 PriorityQueue的再次包裝,是基於堆數據結構的,而PriorityQueue是沒有容量限制的,與ArrayList同樣,因此在優先阻塞 隊列上put時是不會受阻的。雖然此隊列邏輯上是無界的,可是因爲資源被耗盡,因此試圖執行添加操做可能會致使 OutOfMemoryError),可是若是隊列爲空,那麼取元素的操做take就會阻塞,因此它的檢索操做take是受阻的。另外,往入該隊列中的元 素要具備比較能力。
最後,DelayQueue(基於PriorityQueue來實現的)是一個存放Delayed 元素的無界阻塞隊列,只有在延遲期滿時才能從中提取元素。該隊列的頭部是延遲期滿後保存時間最長的 Delayed 元素。若是延遲都尚未期滿,則隊列沒有頭部,而且poll將返回null。當一個元素的 getDelay(TimeUnit.NANOSECONDS) 方法返回一個小於或等於零的值時,則出現期滿,poll就以移除這個元素了。此隊列不容許使用 null 元素。 下面是延遲接口:
放入DelayQueue的元素還將要實現compareTo方法,DelayQueue使用這個來爲元素排序。
下面的實例展現瞭如何使用阻塞隊列來控制線程集。程序在一個目錄及它的全部子目錄下搜索全部文件,打印出包含指定關鍵字的文件列表。從下面實例能夠看出,使用阻塞隊列兩個顯著的好處就是:多線程操做共同的隊列時不須要額外的同步,另外就是隊列會自動平衡負載,即那邊(生產與消費兩邊)處理快了就會被阻塞掉,從而減小兩邊的處理速度差距。下面是具體實現:
/*******公用的一個報警配置類*******************************************************/
public class AlarmConfig {//AlarmConfig 報警配置類
public static final boolean FIND_ENABLE = true;//FINDENABLE 啓用檢測
public static final boolean FIND_UNABLE = false;//FINDUNABLE 關閉檢測 當發生線程開啓時,偵測線程是關閉的。
public static boolean ReceiveFind = FIND_UNABLE ;//ReceiveFind 接收檢測 初始狀態是關閉的
public static QueueArray queueArray = new QueueArray();//QueueArray 類裏放這一個循環隊列
public AlarmConfig() {
}
}
/***********循環隊列類****************************************************/
public class QueueArray {//隊列
private Object[] obj; //初始化儲存空間
private int front; //頭指針,若隊列不爲空,指向隊列頭元素
private int rear; //尾指針,若隊列不爲空,指向隊列尾元素的下一個位置
public QueueArray() {
this(10);
}
public QueueArray(int size){
//隊列進行初始化
obj=new Object[size];
front=0;
rear=0;
}
public Object dequeue(){//出隊
if(rear==front){
return null;
}
Object ob=obj[front];
front=(front+1)%obj.length;
return ob;
}
public boolean enqueue(Object obje){//入隊
if((rear+1)%obj.length==front){
return false;
}
obj[rear]=obje;
rear=(rear+1)%obj.length;
return true;
}
public static void main(String[] args) {
QueueArray d=new QueueArray(10);
for(int i=0;i<=20;i++){
System.out.println(i+" "+ d.enqueue(i));
if(i>8){
System.out.println(i+" "+d.dequeue());
}
}
}
}
/*********偵測線程****************************************************************/
public class MonitorThread implements Runnable{ //MonitorThread 是 偵測線程
private Thread thread; // 分配新的 線程 對象。
private boolean stop = true;
public void strat() {//開啓方法
if (stop) {//若是stop等於true 那麼就給stop賦值false,而後開啓一個線程
thread = new Thread(this);// this 是其 run 方法被調用的對象
stop = false;
thread.start(); // 開始一個線程
}
}
public void stop() {//中止方法
stop = true;//給stop 賦值爲true
thread = null;
}
public void run() {
while (!stop) {
if (AlarmConfig.ReceiveFind) {
Object num=AlarmConfig.queueArray.dequeue();
System.out.println("檢測接收:"+num);
look(num);
AlarmConfig.ReceiveFind = AlarmConfig.FIND_UNABLE;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void look(Object ob){
if(ob.equals(2)||ob.equals(12)){
System.out.println("報警! 發現錯誤報告! ======");
}
}
}
/********發生器線程********************************************************************/
public class ThreadA implements Runnable {
private Thread thread;// 分配新的 線程 對象。
private boolean stop = true;
private int num = 1;
public ThreadA() {// 無參的構造方法
//自動生成構造函數存根
}
public void strat() {//開啓方法
if (stop) {//若是stop等於true 那麼就給stop賦值false,而後開啓一個線程
thread = new Thread(this);// this 是其 run 方法被調用的對象
stop = false;
thread.start(); // 開始一個線程
System.out.println("**當前stop爲*******" + stop);
}
}
public void stop() {//中止方法
stop = true;//給stop 賦值爲true
System.out.println(" stop true");
thread = null;
}
public void run() {
System.out.println("*test**");
while (!stop) {
if (!AlarmConfig.ReceiveFind) {
System.out.println(num + " 發生器: "+ AlarmConfig.queueArray.enqueue(num));
AlarmConfig.ReceiveFind = AlarmConfig.FIND_ENABLE;
num++;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/*************測試類******************************************************/
public class TestMainThread {
public TestMainThread() {
// TODO Auto-generated constructor stub
}
public static void main(String[] args) {
ThreadA treadA = new ThreadA();
treadA.strat();
//treadA.stop();
MonitorThread monitorThread=new MonitorThread();
monitorThread.strat();
//monitorThread.stop();
}
}
實驗要求:
(1)編寫連接隊列的基本操做函數
1.進隊函數 EnQueue(LinkQueue *Q,QElemType e)
2.出隊函數 ,隊空 DeQueue(LinkQueue *Q,QElemType e)
3.輸出隊列中元素 OutputQueue(LinkQueue *Q)
(2)調用上述函數實現下列操做,操做步驟以下
1.調用進隊函數創建一個隊列
2.讀取隊列中的第一個元素
2.從隊列中刪除元素
4.輸出隊列中的全部元素
(3)編寫環形隊列的基本操做函數
1.進隊函數 EnQueue(SqQueue *Q,QElemType e)
2.出隊函數 ,隊空 DeQueue(SqQueue *Q,QElemType e)
3.輸出隊列中元素 OutputQueue(SqQueue *Q)
(4)調用上述函數實現下列操做,操做步驟以下
1.調用進隊函數創建一個隊列
2.讀取隊列中的第一個元素
2.從隊列中刪除元素
4.輸出隊列中的全部元素
1.連接隊列:
#include<stdio.h>
#include<malloc.h>
typedef struct node
{int data;
struct node *next;
};
typedef struct
{struct node *front;
struct node *rear;
}LinkQueue;
InitQueue(LinkQueue *Q)
{ Q->front=(struct node *)malloc(sizeof( struct node));
Q->rear=Q->front;
Q->front->next=NULL;
}
EnQueue(LinkQueue *Q,int e)
{struct node *p;
p=(struct node *)malloc(sizeof(struct node ));
p->data=e;
p->next=NULL;
Q->rear->next=p;
Q->rear=p;
}
DeQueue(LinkQueue *Q,int e)
{ struct node *p;
if(Q->front==Q->rear)
return 0;
else{
p=Q->front->next;
Q->front->next=p->next;
if(p->next=NULL)Q->rear=Q->front;
return(p->data);
free(p);
}
}
OutputQueue(LinkQueue *Q)
{ struct node *p;
p=Q->front->next;
while(p!=NULL)
{ printf("%d ",p->data);
p=p->next;
}
}
GetFront(LinkQueue *Q)
{ struct node *p;
p=Q->front->next;
printf("%d",p->data);
}
void main()
{ LinkQueue s;
int i,max,e,item;
InitQueue(&s);
printf("put a max:");
scanf("%d",&max);
printf("shu ru yuan su");
for(i=0;i<max;i++){
scanf("%d",&e);
EnQueue(&s,e);}
OutputQueue(&s);
printf("\n");
printf("di yi ge yuan su wei:");
GetFront(&s);
printf("\n");
printf("shu ru shan chu yuan su :");
scanf("%d",&item);
DeQueue(&s,item);
OutputQueue(&s);
printf("\n");
}
2.環形隊列:
#define MAXQSIZE 100
#include<stdio.h>
#include<malloc.h>
typedef struct{
int *base;
int front;
int rear;
}SqQueue;
InitQueue(SqQueue *Q)
{ Q->base=(int *)malloc(MAXQSIZE * sizeof(int));
if(!Q->base)exit(1);
Q->front=Q->rear=0;
}
EnQueue(SqQueue *Q,int e)
{ Q->base[Q->rear]=e;
Q->rear=(Q->rear+1)%MAXQSIZE;
}
DeQueue(SqQueue *Q,int *e)
{ if(Q->front==Q->rear)return 0;
e=Q->base[Q->front];
Q->front=(Q->front+1)%MAXQSIZE;
}
GetFront(SqQueue *Q)
{ if(Q->front==Q->rear)return 0;
else printf("%d",Q->base[(Q->front)%MAXQSIZE]);
}
OutputQueue(SqQueue *Q)
{ int i;
i=Q->front;
if(!(Q->front==Q->rear))
{
while((i%MAXQSIZE)!=Q->rear)
{ printf("%d ",Q->base[i%MAXQSIZE]);
i++;
}
}
}
void main()
{ SqQueue *s;
int i,max,e,item;
InitQueue(&s);
printf("put a max:");
scanf("%d",&max);
printf("shu ru yuan su :");
for(i=0;i<max;i++){
scanf("%d",&e);
EnQueue(&s,e);}
OutputQueue(&s);
printf("\n");
printf("di yi ge yuan su wei :");
GetFront(&s);
printf("\n");
printf("shu ru shan chu yuan su:");
scanf("%d",&item);
DeQueue(&s,item);
OutputQueue(&s);
}
#include<iostream.h>
#include<malloc.h>
#include<stdlib.h>
#define MAXSIZE 100
#define TRUE 1
#define FALSE 0
typedef int DataType;
typedef struct
{
DataType data[MAXSIZE];
int front; //頭指針指示器
int rear; //爲指針指示器
}SeqQueue;
//初始化操做
void InitQueue(SeqQueue *Q)
{//將*Q初始化爲一個空的循環隊列
Q->front=Q->rear=0;
}
//判斷隊列是否爲空或滿
void IsEmpty_full(SeqQueue *Q)
{
if(Q->front==Q->rear)
cout<<"該隊列爲空"<<endl;
else if((Q->rear+1)%MAXSIZE==Q->front)
cout<<"該隊列爲滿"<<endl;
else
cout<<"該隊列既不爲空也不爲滿"<<endl;
}
//入隊操做
int EnterQueue(SeqQueue *Q,DataType x)
{//將元素x入隊
if((Q->rear+1)%MAXSIZE==Q->front) //隊列已經滿了
return(FALSE);
Q->data[Q->rear]=x;
Q->rear=(Q->rear+1)%MAXSIZE; //從新設置隊尾指針
return(TRUE); //操做成功
}
//出隊操做
int DeleteQueue(SeqQueue *Q,DataType *x)
{//刪除隊列的隊頭元素,用x返回其值
if(Q->front==Q->rear) //隊列爲空
return(FALSE);
*x=Q->data[Q->front];
Q->front=(Q->front+1)%MAXSIZE; //從新設置隊頭指針
return(TRUE); //操做成功
}
//清空元素
void ClearQueue_Sq(SeqQueue &Q)
{
Q.front=Q.rear=0;
}
//構造隊列,數據元素由鍵盤輸入
void CreateQueue_Sq(SeqQueue &Q)
{
DataType temp;
cout<<"輸入數據元素(按-1結束)"<<endl;
cin>>temp;
while(temp!=-1)
{
if((Q.rear+1)%MAXSIZE == Q.front) cout<<"隊列已經滿了";
else
{
Q.data[Q.rear]=temp;
Q.rear=(Q.rear+1)%MAXSIZE;
cin>>temp;
}
}
}
//隊列的長度
int QueueLength_Sq(SeqQueue Q)
{
return (Q.rear-Q.front+MAXSIZE) % MAXSIZE;
}
//由頭到尾依次輸出隊列的數據元素
void OutputQueue_Sq(SeqQueue Q)
{
if(Q.front==Q.rear) cout<<"空隊列,沒有元素"<<endl;
else
{
cout<<"該循環隊列各元素依次爲:";
for(int k=0; k<=QueueLength_Sq(Q)-1; k++)
cout<<Q.data[(Q.front+k)%MAXSIZE]<<" ";
cout<<endl;
}
}
void main()
{
int flag=1,select;
cout<<" ☆☆☆☆循環隊列的基本操做☆☆☆☆"<<endl;
cout<<" ☆1.請輸入循環隊列元素:☆ "<<endl;
cout<<" ☆2.判斷隊列是否爲空或是否爲滿☆"<<endl;
cout<<" ☆3.當前隊頭元素出隊並將其輸出循環隊列的各元素☆ "<<endl;
cout<<" ☆4.將x入隊並輸出循環隊列的各元素☆ "<<endl;
cout<<" ☆5.當前循環隊列的長度☆ "<<endl;
cout<<" ☆6.清空隊列☆ "<<endl;
cout<<" ☆7.退出☆ "<<endl;
while(flag)
{
cout<<"請選擇: ";
cin>>select;
SeqQueue Q;
int x,a,e;
switch(select)
{
case 1:
InitQueue(&Q);
CreateQueue_Sq(Q);
OutputQueue_Sq(Q);
break;
cout<<"請選擇: ";
case 2:
IsEmpty_full(&Q);
break;
cout<<"請選擇: ";
case 3:
DeleteQueue(&Q,&a);
OutputQueue_Sq(Q);
break;
cout<<"請選擇: ";
case 4:
cout<<"請輸入入隊的元素x:";
cin>>x;
EnterQueue(&Q,x);
OutputQueue_Sq(Q);
break;
cout<<"請選擇: ";
case 5:
cout<<"當前循環隊列的長度是:"<<(Q.rear-Q.front+MAXSIZE) % MAXSIZE<<endl;
break;
cout<<"請選擇: ";
case 6:
ClearQueue_Sq(Q);
cout<<"該循環隊列已清空, ";
break;
case 7:
flag=0;
break;
}
}
}
隊列是先進先出的數據結構,出隊的一端叫隊首,入隊的一端叫隊尾,就像是平常生活中排隊買火車票同樣,下面是隊列的基本操做
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef int QElemType;
typedef struct QNode
{
QElemType data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct
{
QueuePtr front;
QueuePtr rear;
}LinkQueue;
int InitQueue(LinkQueue *Q);
int DestroyQueue(LinkQueue *Q);
int ClearQueue(LinkQueue *Q);
int QueueEmpty(LinkQueue Q);
int QueueLength(LinkQueue Q);
int GetHead(LinkQueue Q,QElemType *e);
int InsertQueue(LinkQueue *Q,QElemType e);
int DelQueue(LinkQueue *Q,QElemType *e);
int PrintQueue(LinkQueue Q);
int InitQueue(LinkQueue *Q)
{
Q->front = Q->rear = (QueuePtr )malloc(sizeof(QNode));
if(!Q->front)
{
perror("malloc error\n");
return -1;
}
Q->front->next = NULL;
Q->front->data = 0;
return 0;
}
int DestroyQueue(LinkQueue *Q)
{
while(Q->front)
{
Q->rear = Q->front->next;
free(Q->front);
Q->front = Q->rear;
}
Q = NULL;
return 0;
}
int ClearQueue(LinkQueue *Q)
{
return 0;
}
int QueueEmpty(LinkQueue Q)
{
if(Q.front == Q.rear)
{
return 1;
}
else
{
return 0;
}
}
int QueueLength(LinkQueue Q)
{
return Q.front->data;
}
int GetHead(LinkQueue Q,QElemType *e)
{
if(Q.front->next == NULL)
{
perror("Queue is empty!\n");
*e = -1;
return -1;
}
*e = Q.front->next->data;
return 0;
}
int InsertQueue(LinkQueue *Q,QElemType e)
{
QueuePtr p = (QueuePtr )malloc(sizeof(QNode));
if(p == NULL)
{
perror("malloc error!\n");
return -1;
}
p->data = e;
p->next = NULL;
(Q->rear)->next = p;
Q->rear = p;
Q->front->data++;
return 0;
}
int DelQueue(LinkQueue *Q,QElemType *e)
{
if(Q->front == Q->rear)
{
perror("The queue is empty!");
return -1;
}
QueuePtr p = (QueuePtr )malloc(sizeof(QNode));
p = Q->front->next;
*e = p->data;
Q->front->next = p->next;
if(Q->rear == p)
{
Q->rear = Q->front;
}
free(p);
Q->front->data--;
return 0;
}
int PrintQueue(LinkQueue Q)
{
Q.front = Q.front->next;
while(Q.front != NULL)
{
printf("%d-----",Q.front->data);
Q.front = Q.front->next;
}
return 0;
}
1.鏈式隊列
//隊列結點結構體
typedef struct QNode
{ QElemType data;
QNode *next;
}*Queueptr;
------------------------------
//指向結點的指針
struct LinkQueue
{ Queueptr front,rear;
}
2.順序隊列---循環隊列
性質以下:
1.頭指針指向對頭元素,尾指針指向隊尾的下一個位置。(這裏的指針都是爲指針,實際是數組序號)
2.爲了區分隊滿與對空,則定義一個存儲空間爲MAX_QSIZE大小的隊列只容許存放MAX_QSIZE-1個數據。
3.判空條件爲:if(Q.front ==Q.rear) return true;
判滿條件爲:if((Q.rear+1)%MAX_QSIZE==Q.front) return true;
4.循環隊列的長度爲:(Q.read-Q.front+MAX_SIZE)%MAX_QSIZE
5.當刪除對頭元素或者在對尾插入元素時指針均需向後移動。操做爲:
Q.rear=(Q.rear+1)%MAX_QSIZE;
Q.front=(Q.front+1)%MAX_QSIZE;
結構體定義以下:
struct SqQueue
{QElemType *base;//指向開闢的空間的首地址
int front;
int rear;
}
#include<iostream.h>
#include <stdlib.h>
#include <malloc.h>
#include<stdio.h>
#define FALSE 0
#define TRUE 1
#define OK 1
#define ERROR 0
#define MAXSIZE 100
typedef int QueueElementType;
typedef struct
{
QueueElementType element[MAXSIZE];
int front;
int rear;
}SeqQueue;
//初始化
int InitQueue(SeqQueue *Q)
{
Q->front=Q->rear=0;
return(TRUE);
}
//入隊
int EnterQueue(SeqQueue *Q,QueueElementType x)
{
if((Q->rear+1)%MAXSIZE==Q->front)
return(FALSE);
Q->element[Q->rear]=x;
Q->rear=(Q->rear+1)%MAXSIZE;
return(TRUE);
}
//出隊
int DeleteQueue(SeqQueue *Q,QueueElementType *x)
{
if(Q->front==Q->rear)
return(FALSE);
*x=Q->element[Q->front];
Q->front=(Q->front+1)%MAXSIZE;
return(TRUE);
}
//求長度
int LengthQueue(SeqQueue *Q)
{
printf("%d",(Q->rear-Q->front+MAXSIZE) % MAXSIZE);
printf("\n");
return(TRUE);
}
//輸出鏈表
void PrintfQueue(SeqQueue *Q)
{
int j;
if(Q->front==Q->rear)
cout<<"隊列爲空"<<endl;
else
{
j=((Q->rear-Q->front+MAXSIZE) % MAXSIZE)-1;
for(int i=0; i<=j; i++)
printf("%d",Q->element[(Q->front+i)%MAXSIZE]);
printf("\n");
}
}
//判斷循環隊列是否爲空或爲滿
void JudgeQueue(SeqQueue *Q)
{
if(Q->front==Q->rear)
{
printf("該隊列爲空");
printf("\n");
}
else if((Q->rear+1)%MAXSIZE==Q->front)
{
printf("該隊列爲滿");
printf("\n");
}
else
{
printf("該隊列既不爲空也不爲滿");
printf("\n");
}
}
//銷燬隊列
void DestroyQueue(SeqQueue *Q)
{
Q->front=Q->rear=0;
}
void main()
{
SeqQueue Q;
InitQueue(&Q);
int flag=1;
printf(" ************^^^^^^^循環隊列功能菜單^^^^^^^************");
printf("\n");
printf("請選擇操做:");
printf("\n");
printf("1.入隊操做");
printf("\n");
printf("2.出隊操做");
printf("\n");
printf("3.判斷隊列空或滿");
printf("\n");
printf("4. 求隊列長度");
printf("\n");
printf("5.銷燬隊列");
printf("\n");
printf("6.退出");
printf("\n");
while(flag)
{
int x,e;
cin>>e;
switch(e){
case 1:printf("請輸入要入隊的整型值:(限一個)");
printf("\n");
cin>>x;
EnterQueue(&Q,x);
printf("隊列爲:");
PrintfQueue(&Q);
break;
case 2: DeleteQueue(&Q,&x);
printf("隊列爲:");
PrintfQueue(&Q);
break;
case 3:JudgeQueue(&Q);
break;
case 4:printf("鏈表長度爲:");
LengthQueue(&Q) ;
break;
case 5:DestroyQueue(&Q);
printf("銷燬成功!");
break;
case 6:flag=0;
break;
}
}
}
(C版之雙端隊列)
用數組實現棧,循環隊列,雙端隊列的方法其實很是簡單。
deque雙端隊列容器
1、基本原理
deque的元素數據採用分塊的線性結構進行存儲,如圖所示。deque分紅若干線性存儲塊,稱爲deque塊。塊的大小通常爲512個字節,元素的數據類型所佔用的字節數,決定了每一個deque塊可容納的元素個數。
全部的deque塊使用一個Map塊進行管理,每一個Map數據項記錄各個deque塊的首地址。Map是deque的中心部件,將先於deque塊,依照deque元素的個數計算出deque塊數,做爲Map塊的數據項數,建立出Map塊。之後,每建立一個deque塊,都將deque塊的首地址存入Map的相應數據項中。
在Map和deque塊的結構之下,deque使用了兩個迭代器M_start和M_finish,對首個deque塊和末deque塊進行控制訪問。迭代器iterator共有4個變量域,包括M_first、M_last、M_cur和M_node。M_node存放當前deque塊的Map數據項地址,M_first和M_last分別存放該deque塊的首尾元素的地
址(M_last實際存放的是deque塊的末尾字節的地址),M_cur則存放當前訪問的deque雙端隊列的元素地址。
2、應用
1、建立
(1)deque()
建立一個沒有任何元素的deque對象。此構造函數的更通常形式是「deque(const A& a = A())」,A是一個內存分配器,可缺省。如deque<int> d;
(2)deque(size_type n)
建立一個具備n個元素的deque對象,每一個元素採用它的類型下的默認值。deque<int> d(10); //默認值爲0
(3)deque(size_type n, const T& value)
建立一個具備n個元素的deque對象,這些元素的初始值爲value。
(4)deque(const deque&)
deque的拷貝構造函數,經過拷貝一個deque對象的元素值,建立一個新的deque對象。此時,新舊deque對象具備相同塊數的deque塊,各自內部的元素也對應相等。
deque<char> d1(5,'k');
deque<char> d2(d1);
(5)deque(const InputIterator first, const InputIterator last, const A& a=A())
將迭代器區間[first,last)所指的元素拷貝到一個新建立的deque對象中,其中內存分配器可缺省。
//利用int數組iArray,建立了一個deque對象d
int iArray [] = {11, 13, 19, 23, 27};
deque<int> d(iArray, iArray + 5);
2、初始化
利用deque提供的push_back()函數,可在尾部壓入新元素value,經常使用做deque容器的初始化賦值。
3、訪問
deque的元素一樣可採用數組和迭代器方式進行訪問,用「d[i]」取得deque對象d的第i個元素(0≤i<d.size()),或用迭代器i的「*」操做「*i」取得i所指向的元素。
(1)iterator begin()
(2)iterator end()
可反向遍歷deque雙端隊列中元素迭代器:
(1)reverse_iterator rbegin()
(2)reverse_iterator rend()
4、插入
1)deque 具備高效的頭部插入元素的函數push_front()。
void push_front(const T&)
2)將在pos位置以前,插入新元素x。
iterator insert(iterator pos, const T& x)
5、刪除
(1)void pop_front()
刪除deque的第一個元素。
(2)void pop_back()
刪除deque的最後一個元素。
(3)iterator erase(iterator pos)
刪除pos所指向的元素。
(4)iterator erase(iterator first, iterator last)
刪除迭代器區間[first,last)所指向的全部元素。
(5)void clear()
刪除全部元素。
6、交換
void swap(deque&)
如d1.swap(d2);
7、其它
(1)bool empty()
判斷deque容器是否已有元素,是則返回true,不然返回false。
(2)size_type size()
當前deque容器的元素個數。
(3)size_type max_size()
系統所支持的deque容器的最大元素個數。
(4)reference front()
deque容器的首元素(引用返回),要求deque不爲空。
(5)reference back()
deque容器的末元素(引用返回),要求deque不爲空。
(C++版雙端隊列)
(python版之雙端隊列)
什麼是雙端隊列
deque,全名double-ended queue)是一種具備隊列和棧的性質的數據結構。雙端隊列中的元素能夠從兩端彈出,其限定插入和刪除操做在表的兩端進行。
下面簡單的介紹一下python中雙端隊列的操做函數;
from collections import deque #首先從collections 模塊中導入deque類
下來咱們定義一個雙端隊列
1.A=deque([]) #建立一個空的雙隊列
2.A.append(n) #從右邊像隊列中增長元素 ,n表示增長的元素
3.A.appendleft(n) #從左邊像隊列中增長元素,n表示增長的元素
4.A.clear() #清空隊列
5.A.count(n) #在隊列中統計元素的個數,n表示統計的元素
6.A.extend(n) #從右邊擴展隊列,n表示擴展的隊列
7.A.extendleft(n) #從左邊擴展隊列,n表示擴展的隊列
8.A.pop() #從隊列的右邊刪除元素,而且返回刪除值
9.A.popleft() #從隊列的左邊刪除元素,而且返回刪除值
10.A.remove(n) #從隊列中刪除指定的值
11.A.reverse() #翻轉隊列
12.A.rotate(n) #旋轉隊列,默認時值爲1,由右邊開始旋轉,負值表明左邊旋轉,n表明從隊列的第一個元素開始,n從1開始計數
雙端隊列旋轉演示圖
(C++之兩個普通隊列和一個優先權隊列)
#ifndef QUEUE_H_
#define QUEUE_H_
#include "Chain.h"
#include <cassert>
#include <cstddef>
#include <stdexcept>
//固定事務數的隊列
//用數組實現
template <class Type>
class FixQueue {
public:
FixQueue( size_t sz );
virtual ~FixQueue();
bool EnQueue( const Type& item);
Type DeQueue();
Type GetFront();
void MakeEmpty() { m_ifront = m_irear = 0; }
bool IsEmpty() const { return m_ifront == m_irear; }
bool IsFull() const { return (m_irear+1)%m_uiMaxSize == m_ifront; }
size_t Length() const { return (m_irear+m_uiMaxSize-m_ifront)%m_uiMaxSize; }
private:
int m_irear, m_ifront;
Type* m_pElement;
size_t m_uiMaxSize;
};
//--------------------------------------
//FixQueue template implementation
//
template <class Type>
FixQueue<Type>::FixQueue( size_t sz = 15) : m_uiMaxSize(sz)
{
m_pElement = new Type[m_uiMaxSize];
assert( m_pElement != 0); //其實這樣作沒有做用
m_ifront = m_irear = 0;
}
template <class Type>
FixQueue<Type>::~FixQueue()
{
delete []m_pElement;
}
template <class Type>
bool FixQueue<Type>::EnQueue( const Type& item )
{
//隊列不滿則加入元素
if(IsFull()) return false;
m_irear = (m_irear+1) % m_uiMaxSize; //計算隊尾值
m_pElement[m_irear] = item;
return true;
}
template <class Type>
Type FixQueue<Type>::DeQueue()
{
if(IsEmpty())
{
MakeEmpty();
throw std::out_of_range("Out Of bounds of Queue!/n");
}
else
{
m_ifront = (m_ifront+1) % m_uiMaxSize;
return m_pElement[m_ifront];
}
}
template <class Type>
Type FixQueue<Type>::GetFront()
{
//返回隊列頭元素的值
if(IsEmpty())
{
MakeEmpty();
throw std::out_of_range("Out Of bounds of Queue!/n");
}
else
{
return m_pElement[(m_ifront+1) % m_uiMaxSize];
}
}
//FixQueue Over!
//ChainQueue
//鏈式隊列,雖然鏈式隊列從抽象意義上來講"is a Chain"
//可是仔細分析,很容易發現鏈式隊列只不過是可以在"鏈頭刪除元素","鏈尾添加元素"的普通鏈表
//更好的表示是: 鏈式隊列"has a general Chain for specific use"
template <class Type>
class ChainQueue {
public:
ChainQueue();
virtual ~ChainQueue();
virtual void EnQueue( const Type& item);
virtual Type DeQueue();
Type GetFront();
void MakeEmpty();
bool IsEmpty() const;
size_t Length() const ;
private:
Chain<Type> chain;
};
template <class Type>
ChainQueue<Type>::ChainQueue() {}
template <class Type>
ChainQueue<Type>::~ChainQueue() {}
template <class Type>
void ChainQueue<Type>::EnQueue( const Type& item)
{
//新加元素
try
{
chain.Appen(item);
}
catch (...)
{ throw; }
}
template <class Type>
Type ChainQueue<Type>::DeQueue()
{
Type tmp;
try
{
chain.Delete(1,tmp);
}
catch(...)
{
throw;
}
return tmp;
}
template <class Type>
Type ChainQueue<Type>::GetFront()
{
Type tmp;
if(!chain.Find(1,tmp)) throw std::out_of_range("Out Of bounds of Queue!/n");
return tmp;
}
template <class Type>
void ChainQueue<Type>::MakeEmpty()
{
chain.Erase();
}
template <class Type>
bool ChainQueue<Type>::IsEmpty() const
{
return (chain.Length() == 0);
}
template <class Type>
size_t ChainQueue<Type>::Length() const
{
return (size_t)chain.Length();
}
//============================================================
//PRQueue 實現一個按優先權重操做的隊列
//顯然,無需從新實現完整的優先權隊列
//優先權隊列只不過是一個特殊的隊列罷了,優先級隊列插入元素方式不一樣,
//要overwrite EnQueue();
//這裏採用繼承鏈式隊列(考慮到元素插入的效率因素,鏈表划算)
//一個更好的方法是利用交叉鏈表實現優先級隊列,優先級別爲行列表,同優先級的任務放到列鏈表中,這裏只是從新實現按權重插入元素
//=============================================================
//定義一個帶優先權的結構
template <class Type>
typedef struct PRItem
{
int priority; //優先權
Type item; //元
//只須要重載一個 <=就好了,這樣恰好可以實現
//1:先按照優先級處理
//2:同優先級的FIFO方式處理
bool operator<=( const PRItem& item) {
return priority <= item.priority;
}
};
template <class Type>
class PRQueue : public ChainQueue< PRItem<Type> > //鬱悶,模板中模板類型
{
public:
PRQueue();
~PRQueue();
void EnQueue( const PRItem<Type>& item) //overwrite
{
typedef PRItem<Type> PRITEM;
typename Chain<PRITEM>::iterator iter = Chain<PRITEM>::chain.begin();
int x=1;
//按優先權插入尋找插入位置
while(iter != Chain<PRITEM>::chain.end() && iter.current() <= item)
{
x++;
iter++;
}
Chain<PRITEM>::chain.Insert(x, item);
}
void EnQueue( const Type& item, int priority) //overload
{
PRItem<Type> tmp;
tmp.item = item;
tmp.priority = priority;
EnQueue(tmp);
}
};
#endif /*QUEUE_H_*/