順序隊列與鏈式隊列

隊列

首先介紹一下什麼是隊列:

隊列是一種特殊的線性表,特殊之處在於它只允許在表的前端(front)進行刪除操作,而在表的後端(rear)進行插入操作,和棧一樣,隊列是一種操作受限制的線性表。進行插入操作的端稱爲隊尾,進行刪除操作的端稱爲隊頭。隊列中沒有元素時,稱爲空隊列。
隊列的數據元素又稱爲隊列元素。在隊列中插入一個隊列元素稱爲入隊,從隊列中刪除一個隊列元素稱爲出隊。因爲隊列只允許在一端插入,在另一端刪除,所以只有最早進入隊列的元素才能最先從隊列中刪除,故隊列又稱爲先進先出(FIFO—first in first out)線性表。
這裏寫圖片描述

下面分別實現順序隊列與鏈式隊列:
1.順序隊列

.h文件

#pragma once
#include<stddef.h>

typedef char SeqQueueType;

#define SeqQueueMaxSize 1000

typedef struct SeqQueue
{
    SeqQueueType data[SeqQueueMaxSize];
    size_t head;
    size_t tail;
    size_t size;
}SeqQueue;
void SeqQueueInit(SeqQueue* q);//初始化
void SeqQueueDestroy(SeqQueue* q);//銷燬隊列
void SeqQueuePush(SeqQueue* q,SeqQueueType value);//入隊列
void SeqQueuePop(SeqQueue* q);//出隊列
int SeqQueueFront(SeqQueue* q,SeqQueueType* value);//取隊首元素

.c文件

void SeqQueueInit(SeqQueue* q)
{
    if(q == NULL)
    {
        //非法輸入
        return;
    }
    q->size = 0;
    q->head = 0;
    q->tail = 0;
    return;
}
void SeqQueueDestroy(SeqQueue* q)
{
    if(q == NULL)
    {
        //非法輸入
        return;
    }
    q->size = 0;
    q->head = 0;
    q->tail = 0;
    return;
}
void SeqQueuePush(SeqQueue* q,SeqQueueType value)
{
    if(q == NULL)
    {
        //非法輸入
        return;
    }
    if(q->size > SeqQueueMaxSize)//如果隊列的尺寸大於隊列最大尺寸,說明隊列已經滿了
    {
        //隊列已經滿了
        return;
    }
    q->data[q->tail++] = value;//把value賦給數組的最後一個元素,並把數組元素下標+1
    if(q->tail > SeqQueueMaxSize)//如果尾元素的下標已經超過了最大容量,就讓下一個元素從0號下標開始入隊列
    {
        q->tail = 0;
    }
    ++q->size;//隊列size+1
    return;
}
void SeqQueuePop(SeqQueue* q)
{
    if(q == NULL)
    {
        //非法輸入
        return;
    }
    if(q->size == 0)
    {
        //空隊列沒法出隊列
        return;
    }
    ++q->head;//將頭元素的下標+1
    if(q->head >= SeqQueueMaxSize)//如果頭元素的下標已經超過了最大容量,就讓下一個元素從0號下標開始出隊列
    {
        q->head = 0;
    }
    --q->size;//隊列size-1
    return;
}
int SeqQueueFront(SeqQueue* q,SeqQueueType* value)
{
    if(q == NULL || value == NULL)
    {
        //非法輸入
        return 0;
    }
    if(q->size == 0)
    {
        return 0;
    }
    *value = q->data[q->head];//將隊列頭元素的值賦給value
    return 1;
}
下面爲測試代碼:
#if 1
#include<stdio.h>
#define TEST_HEADER printf("\n==========================%s===========================\n",__FUNCTION__);
void TestSeqQueue()
{
    TEST_HEADER;
    SeqQueue queue;
    SeqQueueInit(&queue);
    //首先入隊列4個元素
    SeqQueuePush(&queue,'a');
    SeqQueuePush(&queue,'b');
    SeqQueuePush(&queue,'c');
    SeqQueuePush(&queue,'d');

    SeqQueueType value;
    int ret = SeqQueueFront(&queue,&value);
    //因爲隊列遵循先進先出原則,所以第一個元素的值爲a
    printf("ret expected 1,actual %d\n",ret);
    printf("value expected a,actual %c\n",value);
    //出隊列一個元素後,第一個元素值爲b
    SeqQueuePop(&queue);
    ret = SeqQueueFront(&queue,&value);
    printf("ret expected 1,actual %d\n",ret);
    printf("value expected b,actual %c\n",value);
    SeqQueuePop(&queue);
    ret = SeqQueueFront(&queue,&value);
    printf("ret expected 1,actual %d\n",ret);
    printf("value expected c,actual %c\n",value);
    SeqQueuePop(&queue);
    ret = SeqQueueFront(&queue,&value);
    printf("ret expected 1,actual %d\n",ret);
    printf("value expected d,actual %c\n",value);
}
int main()
{
    TestSeqQueue();
    return 0;
}
#endif
2.鏈式隊列

.h文件

#pragma once

typedef char LinkType;

typedef struct LinkNode
{
    LinkType data;
    struct LinkNode* next;
}LinkNode;

typedef struct LinkQueue
{
    LinkNode* head;
    LinkNode* tail;
}LinkQueue;
void LinkQueueInit(LinkQueue* q);//隊列的初始化
void LinkQueueDestroy(LinkQueue* q);//銷燬隊列
void LinkQueuePush(LinkQueue* q,LinkType value);//入隊列
void LinkQueuePop(LinkQueue* q);//出隊列
int LinkQueueFront(LinkQueue* q,LinkType* value);//取隊首元素

.c文件

void LinkQueueInit(LinkQueue* q)
{
    if(q == NULL)
    {
        //非法輸入
        return;
    }
    q->head = NULL;//設置頭指針爲空
    q->tail = NULL;//設置爲指針爲空
    return;
}
void LinkQueueDestroy(LinkQueue* q)//銷燬隊列
{
    if(q == NULL)
    {
        //非法輸入
        return;
    }
    LinkNode* cur = q->head;
    LinkNode* pre = cur;
    while(cur != NULL)
    {
        pre = cur;
        cur = cur->next;
        free(pre);
    }
    q->head = q->tail = NULL;
    return;
}
void DestroyLinkNode(LinkNode* to_delete)
{
    if(to_delete == NULL)
    {
        return;
    }
    free(to_delete);//釋放節點
    to_delete = NULL;
    return;
}
LinkNode* CreateLinkNode(LinkType value)
{
    LinkNode* tmp = (LinkNode*)malloc(sizeof(LinkNode));
    if(!tmp)//創建節點失敗
    {
        printf("CreateLinkNode error!\n");
        return NULL;
    }
    tmp->data = value;
    tmp->next = NULL;
    return tmp;
}
void LinkQueuePush(LinkQueue* q,LinkType value)
{
    if(q == NULL)
    {
        //非法輸入
        return;
    }
    LinkNode* temp = CreateLinkNode(value);//創建一個新的節點temp
    if(q->head == NULL)//如果隊列中沒有元素
    {
        q->head  = temp;
        q->tail = temp;
        return;
    }
    //如果隊列中有元素
    q->tail->next = temp;//在原隊列的尾部插入一個節點
    q->tail = temp;//把尾指針後移
    return;
}
void LinkQueuePop(LinkQueue* q)
{
    if(q == NULL)
    {
        //非法輸入
        return;
    }
    LinkNode* to_delete = q->head;//to_delete指向隊首節點
    q->head = q->head->next;//更新頭指針
    DestroyLinkNode(to_delete);//銷燬頭結點
    return;
}
int LinkQueueFront(LinkQueue* q,LinkType* value)
{
    if(q == NULL )
    {
        //非法輸入
        return 0;
    }
    *value = q->head->data;//把隊首元素的值賦給value
    return 1;
}
下面爲測試代碼:
#if 1
#define TEST_HEADER printf("\n======================%s========================\n",__FUNCTION__);
void LinkQueuePrintChar(LinkQueue* q,const char* msg)
{
    printf("[%s]\n",msg);
    LinkNode* cur = q->head;
    for(;cur!= NULL;cur=cur->next)
    {
        printf("[%c][%p]<- ",cur->data,cur);
    }
    printf("NULL\n");
    printf("\n");

}
void TestQueue()
{
    TEST_HEADER;
    LinkQueue queue;
    LinkQueueInit(&queue);
    LinkQueuePush(&queue,'a');
    LinkQueuePush(&queue,'b');
    LinkQueuePush(&queue,'c');
    LinkQueuePush(&queue,'d');
    LinkQueuePrintChar(&queue,"打印隊列");

    LinkType value;
    int ret = LinkQueueFront(&queue,&value);
    printf("ret expected 1,actual %d\n",ret);
    printf("value expected a,actual %c\n",value);

    LinkQueuePop(&queue);
    ret = LinkQueueFront(&queue,&value);
    printf("ret expected 1,actual %d\n",ret);
    printf("value expected b,actual %c\n",value);

    LinkQueuePop(&queue);
    ret = LinkQueueFront(&queue,&value);
    printf("ret expected 1,actual %d\n",ret);
    printf("value expected c,actual %c\n",value);

    LinkQueuePop(&queue);
    ret = LinkQueueFront(&queue,&value);
    printf("ret expected 1,actual %d\n",ret);
    printf("value expected d,actual %c\n",value);

    LinkQueue queue1;
    LinkQueueInit(&queue1);
    LinkQueuePush(&queue1,'a');
    LinkQueuePush(&queue1,'b');
    LinkQueuePush(&queue1,'c');
    LinkQueuePush(&queue1,'d');
    LinkQueuePrintChar(&queue1,"打印隊列");

    LinkQueueDestroy(&queue1);
    LinkQueuePrintChar(&queue1,"打印隊列");
}
int main()
{
    TestQueue();
    return 0;
}
#endif
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章