溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

數(shù)據(jù)結(jié)構(gòu)之隊(duì)列(C語(yǔ)言版)

發(fā)布時(shí)間:2020-07-13 02:13:23 來源:網(wǎng)絡(luò) 閱讀:1532 作者:捕風(fēng)的xiao_k 欄目:編程語(yǔ)言


   


     本來此篇是準(zhǔn)備總結(jié)堆棧順序表的一些應(yīng)用,但是覺得先接著上篇把隊(duì)總結(jié)完,然后再將應(yīng)用總結(jié)。ok,廢話不多數(shù),我們先來看隊(duì)定義:

    和棧相反,隊(duì)列是一種先進(jìn)先出的線性表。它只允許在表的一端進(jìn)行插入,而在另一端刪除元素。這和我們?nèi)粘I钪械呐抨?duì)是一樣的,最早進(jìn)入隊(duì)列的元素最早離開。在隊(duì)列中允許插入的一端叫隊(duì)尾(rear),允許刪除的一端稱為隊(duì)頭(front)。隊(duì)在程序中經(jīng)常用到。一個(gè)最典型的例子就是操作系統(tǒng)的排隊(duì)作業(yè)。ok我們先來看隊(duì)的結(jié)構(gòu)圖:


數(shù)據(jù)結(jié)構(gòu)之隊(duì)列(C語(yǔ)言版)


    隊(duì)的基本概念,以及結(jié)構(gòu)圖弄明白了的話,我們來看隊(duì)列的抽象數(shù)據(jù)類型的定義:


ADT Queue

{

    

    數(shù)據(jù)對(duì)象:D = {ai| ai屬于ElemSet,i = 1,2,……,n, n >= 0 }

    約定a1端為隊(duì)頭,an隊(duì)尾。

    基本操作:

    //初始化函數(shù)

    Status  InitLinkQueue(LinkQueue *q);

    //入隊(duì),入隊(duì)成功返回TRUE,入隊(duì)失敗返回FALSE

    Status  EnterQueue(LinkQueue *q,ElemType x);

    //出隊(duì),出隊(duì)成功返回TRUE,失敗返回FALSE

    Status DeQueue(LinkQueue *q);

    //獲取隊(duì)頭元素值,用x帶回隊(duì)頭的值

    Status GetHead(LinkQueue *q,ElemType *x);

    //求長(zhǎng)度,返回隊(duì)的長(zhǎng)度

    int GetLength(LinkQueue *q);

    //清空隊(duì)列,摧毀成功返回TRUE,否則返回FALSE

    Status ClearQueue(LinkQueue *q);

    //摧毀隊(duì)

    Status DestortQueue(LinkQueue *q);

    //打印隊(duì)列,打印成功返回TRUE,失敗返回FALSE

    Status Show_Queue(LinkQueue *q);

}



    對(duì)于隊(duì)列也是受限的線性表,所以,隊(duì)列也有兩種存儲(chǔ)結(jié)構(gòu),順序隊(duì)列和鏈?zhǔn)疥?duì)列。但是由于順序存儲(chǔ)會(huì)出現(xiàn)假溢出,所以出現(xiàn)了循環(huán)隊(duì)列的結(jié)構(gòu),鏈隊(duì)列不會(huì)出現(xiàn)這種情況。但是從存儲(chǔ)結(jié)構(gòu)上看依然是兩種鏈?zhǔn)胶晚樞?。我們就按照順序,先看順序?duì)列:


順序隊(duì)列


#define ElemType  int 
#define TRUE      1
#define FALSE     0
#define Status    int
#define MAX_SIZE   8
typedef struct listqueue
  {
    ElemType *base;
    int front;
    int rear;
  }ListQueue;



按照我個(gè)人理解的順序隊(duì)的結(jié)構(gòu)就是這樣:


數(shù)據(jù)結(jié)構(gòu)之隊(duì)列(C語(yǔ)言版)


既然隊(duì)的結(jié)構(gòu)弄清了,我們來看隊(duì)列的的基本操作:


順序隊(duì)列初始化:


    順序隊(duì)就像順序表一樣,所以就要初始化的時(shí)候動(dòng)態(tài)開辟內(nèi)存或者用數(shù)組的形式為其開辟內(nèi)存,除了要開辟內(nèi)存外,還要初始化結(jié)構(gòu)中的其他項(xiàng)。當(dāng)front和rear相等時(shí)表示空,且是指向基地址下表。


Status InitListQueue(ListQueue  *lq)
  {
     lq->base = (ElemType*)malloc(sizeof(ElemType) * MAX_SIZE);
     if(NULL == lq->base)
          {
                printf("out of memory\n");
                return FALSE;
           }
           
     lq->front = 0;
     lq->rear = 0;
     return TRUE;
   }



順序隊(duì)列入隊(duì)出隊(duì)


    隊(duì)列的兩項(xiàng)重要操作就是入隊(duì)和出隊(duì),隊(duì)列我們也一直強(qiáng)調(diào)是受限的線性表,主要不同就在這里,入隊(duì)和出隊(duì),入隊(duì)操作只能從表尾,出隊(duì)操作只能從表頭,入隊(duì)我們先要保證內(nèi)存空間要有,所以就要先判斷是否隊(duì)已滿,然后就是尾插,rear表示的是隊(duì)尾的存儲(chǔ)值的空間的下一個(gè),也就是直接把值存進(jìn)下標(biāo)為rear 的空間。


數(shù)據(jù)結(jié)構(gòu)之隊(duì)列(C語(yǔ)言版)


//入隊(duì)操縱,入隊(duì)成功返回TRUE,入隊(duì)失敗返回FALSE

Status EnListQueue(ListQueue *lq,ElemType x)
 {
    if(lq->rear >= MAX_SIZE)
     {
        printf("隊(duì)已滿\n");
        return FALSE;
      }
      
    lq->base[lq->rear++] = x;
    return TRUE;
  }



    順序隊(duì)的出隊(duì),只能從隊(duì)頭出隊(duì),對(duì)于順序隊(duì),只需要修改隊(duì)頭標(biāo)志front 就可以,這樣就可以把數(shù)據(jù)從邏輯上刪除。


數(shù)據(jù)結(jié)構(gòu)之隊(duì)列(C語(yǔ)言版)


//出隊(duì)操作,出隊(duì)成功返回TRUE,出隊(duì)失敗返回FALSE

Status DeListQueue(ListQueue *lq)
  {
      if(lq->front == lq->rear)
        {
            printf("隊(duì)已空\(chéng)n");
            return FALSE;
         }
    
    lq->front++;
    return TRUE;
  }




順序隊(duì)列獲取隊(duì)列元素個(gè)數(shù)


    由于順序隊(duì)的內(nèi)存是連續(xù)的,所以獲取隊(duì)列數(shù)據(jù)元素個(gè)數(shù),只需要把rear與front相減就可以得到隊(duì)列的長(zhǎng)度。


//獲取長(zhǎng)度,

int Get(ListQueue lq)
    {
        int  length = lq.rear - lq.front;
        return length;
    }




順序隊(duì)列對(duì)頭元素


    對(duì)于獲取隊(duì)頭元素操作,由于front表示的就是首元素的下標(biāo),所以只需要把數(shù)組中front下標(biāo)中的值返回就好。


//獲取隊(duì)頭,獲取成功返回TRUE,獲取失敗返回FALSE

Status GetHead(ListQueue *lq,ElemType *val)
{
    if(lq->front == lq->rear)
    {
        printf("隊(duì)已空\(chéng)n");
        return FALSE;
    }
    *val = lq->base[lq->front];
    return TRUE;
}


順序隊(duì)列清空隊(duì)列


    清空順序隊(duì)列,我們只需要把front和rear下標(biāo)從新指向數(shù)組的0下邊即可。


//清空,清空成功返回TRUE

Status ClearListQueue(ListQueue *lq)
{
    lq->front = lq->rear = 0;
    return TRUE;
}



順序隊(duì)列的摧毀


    對(duì)于摧毀操作,我們就要把初始化中開辟的內(nèi)存釋放掉并且把rear和front賦值為0


//摧毀,摧毀成功返回TRUE.

Status DestoryListQueue(ListQueue *lq)
{
    free(lq->base);
    lq->base = NULL;
    lq->front = lq->rear = 0;
    return TRUE;
}




順序隊(duì)列的輸出打印


    順序隊(duì)的打印輸出我們時(shí),隊(duì)結(jié)構(gòu)中front表示著隊(duì)頭元素的下標(biāo),rear表示隊(duì)尾下一個(gè)位置,所以只需要打印輸出從front到rear的元素。


//打印,打印成功返回TRUE,失敗返回FALSE

Status ShowListQueue(ListQueue *lq)
{
    if(lq->rear == 0)
    {
        printf("隊(duì)已空\(chéng)n");
        return FALSE;
      }
    for(int i = lq->front; i < lq->rear; i++)
        {
            printf("%d ",lq->base[i]);
        }
    printf("\n");
    return TRUE;
}

鏈隊(duì)列



    用鏈表 表示的隊(duì)列稱為鏈隊(duì)列,如下圖,分別是按照理解畫的圖,一個(gè)鏈隊(duì)列得分別有指向隊(duì)頭和隊(duì)尾的指針(分別稱作頭指針和尾指針)才能唯一確定。由于隊(duì)列是限定在進(jìn)行頭刪尾插,那么我們之前總結(jié)鏈表的時(shí)候說過,帶頭結(jié)點(diǎn)的頭單鏈表更方便頭刪,所以這里采用帶頭結(jié)點(diǎn)的單鏈表表示隊(duì)列。


數(shù)據(jù)結(jié)構(gòu)之隊(duì)列(C語(yǔ)言版)


    開篇已經(jīng)把隊(duì)列的抽象數(shù)據(jù)類型介紹了,所以這里直接實(shí)現(xiàn)鏈隊(duì)列。



鏈隊(duì)列定義結(jié)點(diǎn)類型和管理結(jié)構(gòu)



#define Status   int
#define TRUE     1
#define FALSE    0
#define ElemType int 


//定義結(jié)點(diǎn)類型
typedef struct  QueueNode
{
	ElemType data;
	struct QueueNode *next;

}QueueNode;

//定義管理結(jié)構(gòu)
typedef struct LinkQueue
{
	QueueNode *front;
	QueueNode *tail;
}LinkQueue;


鏈隊(duì)列初始化


    我們一直強(qiáng)調(diào),對(duì)于棧、隊(duì)是受限的線性表,所以,初始化鏈隊(duì)列的時(shí)候,我們聯(lián)想一下之前的帶頭結(jié)點(diǎn)的單鏈表如何初始化,就明白了鏈隊(duì)如何初始化了。


//初始化隊(duì)列
Status  InitLinkQueue(LinkQueue *Q)
{
	QueueNode  *s = (QueueNode *)malloc(sizeof(QueueNode));

	if(NULL == s)
	{
		printf("out of memory\n");
		return FALSE;
	}

	Q->front = s;
	Q->tail = s;
	s->next = NULL;
	return TRUE;	
}


鏈隊(duì)列進(jìn)隊(duì)出隊(duì)


    隊(duì)是受限的線性表,那么對(duì)于隊(duì)列進(jìn)隊(duì)、出隊(duì)是需要注意的操作,隊(duì)的先進(jìn)先出,映射到鏈表中就是進(jìn)行頭刪,尾插。這里由于帶頭結(jié)點(diǎn)頭插的時(shí)候,也就是入隊(duì)的時(shí)候操作就簡(jiǎn)化了好多.入隊(duì)出隊(duì)操作就是帶頭結(jié)點(diǎn)的頭刪尾插,所以,我就不過多廢話。


//入隊(duì)操作,入隊(duì)成功返回TRUE,入隊(duì)失敗返回FALSE
Status  EnterQueue(LinkQueue *q,ElemType x)
{
	QueueNode  *s = (QueueNode *)malloc(sizeof(QueueNode));

	if(NULL == s)
	{
		printf("out of memory\n");
		return FALSE;
	}

	s->data = x;
	s->next = NULL;
	q->tail->next = s;
	return TRUE;
}

//出隊(duì)操作,出隊(duì)成功返回TRUE,出隊(duì)失敗返回FALSE,出隊(duì)的時(shí)候,需要注意釋放內(nèi)存,防止內(nèi)存泄露
Status DeQueue(LinkQueue *q)
{
	if(q->front == q->tail )
	{
		printf("隊(duì)已空\(chéng)n");
		return FALSE;
	}

	QueueNode *p = q->front->next;

	q->front->next = p->next;
	free(p);
	p = q->front->next; 

	if(q->tail == p)
	{
		q->tail = q->front;
	}
	return TRUE;
}


鏈隊(duì)列獲取隊(duì)頭元素



    獲取對(duì)頭元素這里需要強(qiáng)調(diào)一下,獲取隊(duì)頭元素大多數(shù)課本上是用參數(shù)中一個(gè)值帶回,或者用return語(yǔ)句直接返回返回值,這樣做呢對(duì)于順序隊(duì)、隊(duì)中只有一個(gè)值的時(shí)候沒有錯(cuò),但是不知道你有沒有想過,假如說隊(duì)的結(jié)點(diǎn)中不是一個(gè)數(shù)據(jù)域呢?還可以用return語(yǔ)句直接返回直接返回返回?cái)?shù)據(jù)域嗎?不可以吧!所以呢,個(gè)人覺得用return語(yǔ)句直接將整個(gè)結(jié)點(diǎn)返回,這樣需要不論他是幾個(gè)都可以,之前的鏈表、棧中是按照之前的操作做的,后邊的操作將改掉這部分的操作,采用返回結(jié)點(diǎn)。



//獲取對(duì)頭元素,獲取成功返回頭結(jié)點(diǎn),獲取失敗返回NULL
 QueueNode *GetHead(LinkQueue *q)
{
	QueueNode *p = q->front->next;
	if(q->front == q->tail )
	{
		printf("隊(duì)已空\(chéng)n");
		return NULL;
	}

	return q->front->next;
}


鏈隊(duì)求數(shù)據(jù)個(gè)數(shù)


    鏈隊(duì)求隊(duì)中元素個(gè)數(shù),不在像順序隊(duì)中,直接用reat和front直接相減就可以獲取隊(duì)列的元素個(gè)數(shù),鏈隊(duì)不可以,鏈隊(duì)的內(nèi)存不連續(xù),這里就需要用一個(gè)變量計(jì)算隊(duì)列的長(zhǎng)度,防止頭指針被修改就需要用臨時(shí)指針遍歷鏈表,然后計(jì)算其長(zhǎng)度。或者在隊(duì)列管理結(jié)構(gòu)中在添加一項(xiàng)數(shù)據(jù)項(xiàng),記住隊(duì)列的個(gè)數(shù)。這樣的話就可以方便的獲取隊(duì)列的元素個(gè)數(shù)。



//求長(zhǎng)度
int GetLength(LinkQueue *q)
{
	int length;
	QueueNode *p = q->front->next;
	while(NULL != p)
	{
		length++;
		p = p->next;
	}
	return length;
}


鏈隊(duì)打印輸出隊(duì)中元素


    鏈表不空的話,遍歷整個(gè)鏈表輸出整個(gè)鏈表的數(shù)據(jù)域,為了防止頭指針被修改就需要定義一個(gè)臨時(shí)變量指向隊(duì)列

//遍歷成功返回TRUEM,遍歷失敗返回FALSE
Status Show_Queue(LinkQueue *q)
{
	QueueNode *p = q->front->next;
	if(q->front == q->tail )
	{
		printf("隊(duì)已空\(chéng)n");
		return FALSE;
	}
	while(NULL != p)
	{
		printf("%d",p->data);
	}
	printf("\n");
	return TRUE;
}



鏈隊(duì)的清空


    鏈表的清空就需要把申請(qǐng)的所有結(jié)點(diǎn)釋放掉,防止內(nèi)存空間泄露。



//清空隊(duì)列
Status ClearQueue(LinkQueue *q)
{
	if(q->front == q->tail)
	{
		return FALSE;
	}
	QueueNode *p = q->front->next;
	while(NULL != p)
	{
		q->front->next = p->next;
		free(p);
		p = q->front->next;
	}
	p = NULL;
	q->tail = q->front;
	return TRUE;
}


鏈隊(duì)的摧毀 


    鏈隊(duì)的摧毀就是在釋放了所有結(jié)點(diǎn)后,再把頭結(jié)點(diǎn)釋放掉。


//鏈隊(duì)的摧毀
Status DestortQueue(LinkQueue *q)
{
	ClearQueue(q);
	free(q->front);
	q->front = NULL;
	q->tail = NULL;
	return TRUE;
}


循環(huán)隊(duì)列


    為什么會(huì)出現(xiàn)循環(huán)隊(duì)列?上邊總結(jié)順序隊(duì)列的時(shí)候提到一個(gè)問題就是順序隊(duì)列會(huì)出現(xiàn)假溢出,對(duì)于鏈隊(duì)不會(huì)出現(xiàn)假溢出,也就不需要處理這種情況。這下我們先來看前邊講的順序隊(duì)列,當(dāng)進(jìn)行不斷的進(jìn)隊(duì)出隊(duì)操作后,會(huì)出現(xiàn)什么情況?

數(shù)據(jù)結(jié)構(gòu)之隊(duì)列(C語(yǔ)言版)


    我們可以從圖中清晰的看出來,隊(duì)列只能再插入一個(gè)元素了,但是事實(shí)上隊(duì)的空間是空的。為了解決這個(gè)問題就出現(xiàn)了循環(huán)隊(duì)列。關(guān)于循環(huán)隊(duì)列大多數(shù)的書上會(huì)畫下邊這樣一個(gè)圖,來解釋循環(huán)隊(duì)列:


數(shù)據(jù)結(jié)構(gòu)之隊(duì)列(C語(yǔ)言版)

    關(guān)于這個(gè)圖,不是我畫的是我從課本上截的,不知道大家第一眼從課本上看到這個(gè)圖什么感覺,反正我看完,沒有感覺,這畫的什么???不是隊(duì)啊,咋就成圈了!后來當(dāng)我理解了以后,這個(gè)圖好也不好,好就是形象的說明了循環(huán)隊(duì)列的情況,但是這會(huì)讓人產(chǎn)生誤會(huì),會(huì)以為計(jì)算機(jī)中就是這樣存的,ok,當(dāng)然不是,如果是那就厲害了。其實(shí)呢。在C語(yǔ)言中實(shí)現(xiàn)環(huán)是通過求模實(shí)現(xiàn)的,當(dāng)你想實(shí)現(xiàn)一個(gè)多大的環(huán)通過求它的模就可以把數(shù)字控制在0 到 n-1,這個(gè)想必大家沒有疑問吧?那么循環(huán)隊(duì)列就是通過這樣控制順序隊(duì)列的下表來實(shí)現(xiàn)順序隊(duì)列。 ok。我們來邊看代碼邊解釋。


     循環(huán)隊(duì)列是建立在順序隊(duì)列上的,所以結(jié)構(gòu)一樣的只是基本操作處理上不一樣。



定義循環(huán)隊(duì)列的結(jié)構(gòu)

#define ElemType  int 
#define TRUE      1
#define FALSE     0
#define Status    int
#define MAX_SIZE   12

typedef struct listqueue
{
	ElemType *base;
	int front;
	int rear;
}ListQueue;


 循環(huán)隊(duì)列的初始化


    循環(huán)鏈表的初始化與順序鏈表的操作也一樣。這也不用說


Status InitListCycQueue(ListQueue  *lq)
{
	lq->base = (ElemType*)malloc(sizeof(ElemType) * MAX_SIZE);
	if(NULL == lq->base)
	{
		printf("out of memory\n");
		return FALSE;
	}
	lq->front = 0;
	lq->rear = 0;
	return TRUE;
}


 循環(huán)隊(duì)列的入隊(duì)、出隊(duì)


    ok入隊(duì)出隊(duì)進(jìn)入循環(huán)隊(duì)列的重點(diǎn),循環(huán)隊(duì)列為什么可以實(shí)現(xiàn)循環(huán)?我們先看順序隊(duì)列遇到了那些問題:

    問題一:由于順序隊(duì)列是通過數(shù)組實(shí)現(xiàn)的,即就是你的數(shù)組開辟的很大,那么也會(huì)隨著不斷的插入的數(shù)據(jù)導(dǎo)入隊(duì)滿是吧?這個(gè)沒有錯(cuò)吧?也會(huì)出現(xiàn)上面圖中那種情況rear大小等于了數(shù)組的空間大小,已經(jīng)越界不能再增大了雖然front隨著數(shù)據(jù)的不斷出隊(duì)也不斷向后指向,就造成了前邊的空間無法訪問,那么我們可不可通過讓rear從新指向數(shù)組是開頭,這樣就可以從新插入數(shù)據(jù),那么實(shí)現(xiàn)這個(gè)就要用到我之前已經(jīng)提到的求模,通過rear求數(shù)組空間大小的模就可以把rear大小控制在0 - SIZE-1 的范圍內(nèi),而C語(yǔ)言的數(shù)組下標(biāo)正好是從0開始到 SIZE - 1,ok解決了讓空間循環(huán)回去的問題,我們就會(huì)遇到另一個(gè)問題這也就是

    問題二:那么我們之前的判斷隊(duì)滿的條件已經(jīng)不在適用,有人就說既然都循環(huán)了,不會(huì)存在隊(duì)滿,個(gè)人覺得呢!不不不,判斷隊(duì)滿是非常有必要的,雖然循環(huán)了但是隊(duì)可以容納的有效數(shù)據(jù)是一定的,當(dāng)隊(duì)滿時(shí)如果繼續(xù)插入,就會(huì)將之前的數(shù)據(jù)覆蓋掉這是不允許的!所以判斷隊(duì)滿是非常有必要的!并且修改成循環(huán)以后還會(huì)遇到之前判斷隊(duì)空的條件的也不好用了,因?yàn)楫?dāng)采用循環(huán)以后rear == front,有可能是隊(duì)空,也有可能是隊(duì)滿,對(duì)吧?這個(gè)大家認(rèn)同吧?ok解決這個(gè)問題有兩種方法:

    方法一:在結(jié)構(gòu)中再引入一個(gè)標(biāo)記變量,隊(duì)空時(shí)一個(gè)狀態(tài)值,堆滿時(shí)是一個(gè)狀態(tài)值。

    方法二:既然存滿時(shí)rear循環(huán)回去會(huì)造成rear == front,判斷困難,那么就犧牲最后一個(gè)空間,讓其永遠(yuǎn)也不會(huì)相等。這樣就可以解決了判斷隊(duì)滿的條件,同時(shí)判斷隊(duì)空的問題也就相應(yīng)解決了

    ok問題解決完了,那么循環(huán)隊(duì)列也就實(shí)現(xiàn)了



//循環(huán)隊(duì)列入隊(duì),入隊(duì)成功返回TRUE,入隊(duì)失敗返回FALSE
Status EnListCycQueue(ListQueue *lq,ElemType x)
{

//注意看這個(gè)判斷隊(duì)滿的條件,這里采用剛才提到的第二種方法,犧牲隊(duì)尾的最后一個(gè)空間(注意
//不一定是數(shù)組的最后一個(gè)空間,是隊(duì)尾的最后一個(gè)空間)當(dāng)rear + 1 時(shí)等于 front就是隊(duì)滿,rear//== front  依然是判斷隊(duì)空時(shí)的條件
	if(((lq->rear + 1) % MAX_SIZE) == lq->front)
	{
		printf("隊(duì)已滿\n");
		return FALSE;
	}
	lq->base[lq->rear] = x;
	lq->rear = (lq->rear + 1) % MAX_SIZE;
	return TRUE;
}

//出隊(duì),出對(duì)成功,返回TRUE,出隊(duì)失敗返回FALSE
Status DeListCycQueue(ListQueue *lq)
{

	if(lq->front == lq->rear)
	{
		printf("隊(duì)已空\(chéng)n");
		return FALSE;
	}
	lq->front = (lq->front + 1) % MAX_SIZE;
	return TRUE;
}


循環(huán)隊(duì)列獲取隊(duì)中元素個(gè)數(shù)



//獲取長(zhǎng)度
int GetLentg(ListQueue *lq)
{
	return (lq->rear + MAX_SIZE - lq->front) % MAX_SIZE;
}


循環(huán)隊(duì)列獲取隊(duì)頭元素


    雖然采用了循環(huán)結(jié)構(gòu)但是我們可以發(fā)現(xiàn)front依然是表述隊(duì)頭元素的下標(biāo),所以與順序隊(duì)的操作是沒有區(qū)別的。


//獲取隊(duì)頭
Status GetHead(ListQueue *lq,ElemType *val)
{
	if(lq->front == lq->rear)
	{
		printf("隊(duì)已空\(chéng)n");
		return FALSE;
	}

	*val = lq->base[lq->front];
	return TRUE;
}


循環(huán)隊(duì)列的清空


    循環(huán)隊(duì)列的清空同樣是讓隊(duì)恢復(fù)到初始狀態(tài),所以操縱與順序隊(duì)的操作一樣



//清空,清空成功返回TRUE
Status ClearListCycQueue(ListQueue *lq)
{
    lq->front = lq->rear = 0;
    return TRUE;
}



循環(huán)隊(duì)列的摧毀


    循環(huán)隊(duì)列只是再存儲(chǔ)時(shí)進(jìn)行了改變,對(duì)于摧毀,東西都不在了,與順序隊(duì)又有什么區(qū)別呢?


//摧毀,摧毀成功返回TRUE,
Status DestoryListCycQueue(ListQueue *lq)
{
free(lq->base);
lq->base = NULL;
lq->front = lq->rear = 0;
return TRUE;
}


循環(huán)隊(duì)列的打印


    關(guān)于打印輸出,需要注意一下,循環(huán)隊(duì)列中的元素已經(jīng)不能通過之前的方式訪問輸出了我們可以看下圖:

數(shù)據(jù)結(jié)構(gòu)之隊(duì)列(C語(yǔ)言版)

    當(dāng)采用順序隊(duì)的方式打印輸出時(shí),front本身就是大于rear所以不會(huì)進(jìn)入循環(huán)打印輸出數(shù)據(jù),并且那個(gè)判斷空的條件也已經(jīng)不在適用了,即使循環(huán)隊(duì)中有值它也會(huì)在某中情況下判斷為空。那么循環(huán)隊(duì)列怎樣存就怎樣訪問輸出,ok我們來看:前邊已經(jīng)說到循環(huán)隊(duì)列中判斷隊(duì)空的條件修改為是front == rear,然后,由于rear是指向隊(duì)尾的下一個(gè)空間的,所以循環(huán)條件只要i不等于 rear讓其循環(huán)就可以,此時(shí)還要注意i的增長(zhǎng)方式是循環(huán)的ok



Status ShowListCycQueue(ListQueue *lq)
{
	if(lq->rear == lq->front)
	{
		printf("隊(duì)已空\(chéng)n");
		return FALSE;
	}
	for(int i = lq->front; i != lq->rear; )
	{
		printf("%d ",lq->base[i]);
		i = (i+1) % MAX_SIZE;
	}
	printf("\n");
	return TRUE;
}


    ok關(guān)于隊(duì)的基本操作就總結(jié)的到這里,博文呢按照我個(gè)人的理解,盡我最大的努力進(jìn)行了總結(jié),但也不能不能避免一些表述錯(cuò)誤,代碼是沒有問題的。希望各位讀者發(fā)現(xiàn)了其中的錯(cuò)誤,評(píng)論指出錯(cuò)誤,讓我改正其中的錯(cuò)誤。



    后面呢按照之前說的進(jìn)行線性表,棧、隊(duì)的遺留問題進(jìn)行總結(jié)以及他們的應(yīng)用。



向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI