1. 程式人生 > >順序隊列代碼

順序隊列代碼

ron eof 取余 isf blog dequeue sel true erro

隊列:一種特殊的線性表,其特性就是先進先出(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; }

運行結果

技術分享

順序隊列代碼