順序隊列代碼
隊列:一種特殊的線性表,其特性就是先進先出(FIFO),即從一端進從另一端出
隊頭:允許刪除的一端 front
隊尾:允許插入的一端 rear
如下圖所示,出隊和入隊的流程:
---------------------------------------------------------------------------------------------------------------------------------------------------
可以發現,無論是出隊還是入隊,front指針 和 rear指針都會增加而不是減少,因此很容易造成溢出 和 空間浪費
因此隊列因為存在溢出問題所以日常的軟件很少使用隊列,那麽如何解決,先說說兩個概念:
假設最大的存儲空間是6
假溢出:front != 0 ,rear = M ,再有元素插入時發生溢出 稱為假溢出,存儲空間還有剩余,如上圖最後一張
真溢出:front = 0 ,rear = M, 再有元素插入時發生溢出 稱為真溢出,存儲空間已滿。
因此為了使得空間不被,因此需要允許假溢出行為,即像時鐘那樣超過最大值則從頭開始存儲。
所以可以 與 最大值 QUEUE_ MAX_SIZE 取余(mod) 來繼續從頭開始利用空間。
而真溢出會導致存儲值被破壞因此不能允許發生。如果找到滿足隊列滿了的條件就可以阻止真溢出行為。
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
如上圖,可以發現當隊列空和滿時,front == rear,因此為了判斷隊列是否真的滿了,有如下三種方法:
方法一:少用一個存儲單元
滿的條件為
(rear + 1)%QUEUE_MAX_SIZE == front
空的條件為
rear == front
方法二:標誌位
添加一個標誌位 tag = 0
當入隊成功 tag = 1,出隊成功 tag = 0
滿的條件為
rear == front && tag = 1
空的條件為
rear == front && tag = 0
方法三:計數器
添加一個計數器 count = 0
當入隊成功 count++ ,出隊成功 count0--
滿的條件為
count > 0 && rear == front
空的條件為
count == 0
下面是隊列的實現代碼,使用第一種方法防止溢出
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#define OK 1
#define TRUE 1
#define FALSE 0
#define ERROR 0
#define OVERFLOW -2
#define QUEUE_MAX_LEN 1024
typedef int Status;
typedef int ElemType;
typedef struct{
ElemType * base; //基地址
int front; //頭偏移量
int rear; //尾偏移量
} sqQueue;
/***********初始化**********/
Status initQueue(sqQueue *Q){
Q->base = (ElemType*)malloc(QUEUE_MAX_LEN * sizeof(ElemType));
Q->front = Q->rear = 0;
return OK;
}
/**********是否空**********/
Status isEmpty(sqQueue Q){
if(Q.front == Q.rear)return TRUE;
else return FALSE;
}
/**********是否滿**********/
Status isFull(sqQueue Q){
if(Q.rear % QUEUE_MAX_LEN +1 == Q.front)return TRUE;
else return FALSE;
}
/**********獲取長度**********/
Status getLength(sqQueue Q){
return (Q.rear - Q.front + QUEUE_MAX_LEN) % QUEUE_MAX_LEN;
}
/*********獲取頭值**********/
Status getHead(sqQueue Q,ElemType *e){
if(isEmpty(Q))return ERROR;
*e = *(Q.base + Q.front);
return OK;
}
/***********入隊**********/
Status enQueue(sqQueue *Q,ElemType e){
if(isFull(*Q))return OVERFLOW;
*( Q->base + Q->rear ) = e;
Q->rear = (Q->rear + 1)%QUEUE_MAX_LEN;
return OK;
}
/***********出隊**********/
Status deQueue(sqQueue *Q,ElemType *e){
if(isEmpty(*Q))return OVERFLOW;
*e = *(Q->base + Q->front);
Q->front = (Q->front +1 )%QUEUE_MAX_LEN;
return OK;
}
/***********打印隊列**********/
//事實上隊列是不能這麽用的
//這裏只是為了能看到先進先出的效果
/****************************/
Status printQueue(sqQueue Q){
if(isEmpty(Q))
printf("queue is empty\n");
int len = getLength(Q);
while(Q.rear - Q.front){
printf("[%d] ",*(Q.base+Q.front));
Q.front = (Q.front+1)%QUEUE_MAX_LEN;
}
printf("\n");
return OK;
}
int main(){
char sel;
int val;
sqQueue Q;
initQueue(&Q);
while(1){
system("clear");
printf("\n");
printQueue(Q);
printf("e = enQueue\nd = deQueue\n");
printf("g = getHead\n");
printf("plese enter your choose[e|d|g]:");
sel = getchar();
if(sel == ‘e‘){
printf("[EnQueue]enter value:");
scanf("%d",&val);
enQueue(&Q,val);
}
else if(sel == ‘d‘){
deQueue(&Q,&val);
printf("[DeQueue]value is %d\n",val);
sleep(1);
}
else if(sel == ‘g‘){
getHead(Q,&val);
printf("[HeadVal]value is %d\n",val);
sleep(1);
}
}
return 0;
}
運行結果
順序隊列代碼