!-- 顺序队列及链式队列的C语言实现 --!

队列

基本操作:入队列、出队列、取队首元素;
基本特性:先进先出;
  


1.顺序队列:
     实现顺序队列时,我们利用数组实现,定义了head,tail用来记录当前首元素和最后元素的下标。但是在删除时,因为队列要实现“先进先出”,所以进行头删。所以本来数组的下标为[0,MAXSIZE),原本的head应该为0,但头删之后就不为0。在tail等于或大于MASIZE值时,若head不为0,则可以从0再继续入队列,即只要tail没有追上head就可以继续向队列里放元素;同样地,在打印队列元素以检查操作是否正确时,也要考虑这个因素。

SeqQueue.h
#pragma once

#include <stdio.h>
#include <stddef.h>

#define SHOW_NAME printf("\n=================%s==================\n",__FUNCTION__);
#define MAX_SIZE 5

typedef char SeqQueueType;

typedef struct SeqQueue//整个队列的元素是从head到tail,
{           //由于出队是头删,所以前面可能会有空,所以当tail走到最后时,tail再指向0,只要size与MAX_SIZE不相等,就还有空间
    SeqQueueType data[MAX_SIZE];
    size_t head;//队列第一个元素下标
    size_t tail;//队列最后一个元素的下标
    size_t size;//用了多少个元素的空间
}SeqQueue;

SeqQueue.c
include "SeqQueue.h"

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 >= MAX_SIZE)//队列已满
        return;
    q->data[q->tail++] = value;
    if(q->tail >= MAX_SIZE)//tail走到最后,就再指向头(只要size<MAX_SIZE)
        q->tail = 0;
    q->size++;
    return;
}

void SeqQueuePop(SeqQueue* q)//出列队(头删)
{
    if(q == NULL)//非法操作
        return;
    if(q->size == 0)//空队
        return;
    q->head++;
    if(q->head >= MAX_SIZE)//别忘记!!!
        q->head = 0;
    q->size--;
    return;
}

int SeqQueueGetFront(SeqQueue* q,SeqQueueType* value)//取队首元素
{
    if(q == NULL)
        return 0;
    if(q->size == 0)
        return 0;
    *value = q->data[q->head];
    return 1;
}

void SeqQueuePrint(SeqQueue* q,const char* msg)//打印
{
    printf("[%s]\n",msg);
    if(q == NULL)
        return;
    if(q->size == 0)//空队列
    {
        printf("空队\n");
        return;
    }
    size_t i = q->head;
    if(q->tail <= q->head)//tail在head前
    {
        for(; i<MAX_SIZE; ++i)
            printf("[%c] ",q->data[i]);
        for(i=0; i<q->tail; ++i)//q->tail指向最后一个元素的下一个位置
            printf("[%c] ",q->data[i]);
    }
    else//tail在head后
    {
        for(i=q->head; i<q->tail; ++i)
            printf("[%c] ",q->data[i]);
    }
    printf("\n");
    return;
}

void TestInit()
{
    SHOW_NAME;
    SeqQueue q;
    SeqQueueInit(&q);
    printf("size: excpted is 0,actual is %d\n",q.size);
    printf("head: excpted is 0,actual is %d\n",q.head);
    printf("tail: excpted is 0,actual is %d\n",q.tail);
}

void TestDestroy()
{
    SHOW_NAME;
    SeqQueue q;
    SeqQueueInit(&q);
    SeqQueueDestroy(&q);
}

void TestPush()
{
    SHOW_NAME;
    SeqQueue q;
    SeqQueueInit(&q);
    SeqQueuePush(&q,'a');
    SeqQueuePush(&q,'b');
    SeqQueuePush(&q,'c');
    SeqQueuePush(&q,'d');
    SeqQueuePush(&q,'e');
    SeqQueuePrint(&q,"入队五个元素");
}

void TestPop()
{
    SHOW_NAME;
    SeqQueue q;
    SeqQueueInit(&q);
    SeqQueuePush(&q,'a');
    SeqQueuePush(&q,'b');
    SeqQueuePush(&q,'c');
    SeqQueuePush(&q,'d');
    SeqQueuePush(&q,'e');
    SeqQueuePrint(&q,"入队五个元素");
    SeqQueuePop(&q);
    SeqQueuePop(&q);
    SeqQueuePop(&q);
    SeqQueuePrint(&q,"出队三个元素");
    SeqQueuePush(&q,'f');
    SeqQueuePush(&q,'g');
    SeqQueuePush(&q,'h');
    SeqQueuePrint(&q,"入队三个元素");
    SeqQueuePop(&q);
    SeqQueuePop(&q);
    SeqQueuePop(&q);
    SeqQueuePrint(&q,"出队三个元素");
    SeqQueuePop(&q);
    SeqQueuePop(&q);
    SeqQueuePrint(&q,"出队两个元素");
}

void TestGetFront()
{
    SHOW_NAME;
    SeqQueue q;
    SeqQueueInit(&q);
    SeqQueuePush(&q,'a');
    SeqQueuePush(&q,'b');
    SeqQueuePush(&q,'c');
    SeqQueuePrint(&q,"入队三个元素");
    int ret = 0;
    SeqQueueType value;
    ret = SeqQueueGetFront(&q,&value);
    if(ret == 1)
        printf("取得队首元素为 %c\n",value);
    else
        printf("未取得队首元素\n");
    SeqQueuePop(&q);
    SeqQueuePop(&q);
    SeqQueuePop(&q);
    SeqQueuePrint(&q,"出队三个元素");
    ret = SeqQueueGetFront(&q,&value);
    if(ret == 1)
        printf("取得队首元素为 %c\n",value);
    else
        printf("未取得队首元素\n");
}

int main()
{
    TestInit();
    TestDestroy();
    TestPush();
    TestPop();
    TestGetFront();
    return 0;
}


2.链式队列:

    类似单链表实现链式队列

LinkQueue.h
#pragma once

#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>

#define SHOW_NAME printf("\n=================%s==================\n",__FUNCTION__);

typedef char LinkNodeType;

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

typedef struct LinkQueue//入队(尾插)、出队(头删)
{
    LinkNode* head;
    LinkNode* tail;
}LinkQueue;

LinkQueue.c
#include "LinkQueue.h"

void LinkQueueInit(LinkQueue* q)//初始化
{
    if(q == NULL)//非法输入
        return;
    q->head = NULL;
    q->tail =NULL;
}

void LinkQueueDestroy(LinkQueue* q)//销毁队列
{
    if(q == NULL)
        return;
    LinkNode* cur = q->head;
    while(cur != NULL)
    {   
        LinkNode* to_delete = cur;
        cur = cur->next;
        free(to_delete);
    }   
    q->head = q->tail = NULL;
    return;
}

LinkNode* CreateNode(LinkNodeType value)//新建一个结点
{
    LinkNode* new_node = (LinkNode*)malloc(sizeof(LinkNode));
    new_node->data = value;
    new_node->next = NULL;
    return new_node;
}

void LinkQueuePush(LinkQueue* q,LinkNodeType value)//入队列(尾插)
{
    if(q == NULL)//非法操作
        return;
    if(q->head==NULL)//空队列
    {
        q->head = q->tail = CreateNode(value);
        return;
    }
    LinkNode* p = CreateNode(value);
    q->tail->next = p;
    q->tail = q->tail->next;
    return;
}

void LinkQueuePop(LinkQueue* q)//出列队(头删)
{
    if(q == NULL)//非法操作
        return;
    if(q->tail == NULL)//空队
        return;
    if(q->head->next == NULL)//只剩一个元素
    {
        q->head = q->tail = NULL;
        return;
    }
    LinkNode* ret = q->head->next;
    q->head = ret;
    return;
}

int LinkQueueGetFront(LinkQueue* q,LinkNodeType* value)//取队首元素
{
    if(q == NULL)
        return 0;
    if(q->tail == NULL)
        return 0;
    *value = q->head->data;
    return 1;
}

void LinkQueuePrint(LinkQueue* q,const char* msg)//打印
{
    printf("[%s]\n",msg);
    LinkNode* cur = q->head;
    for(; cur!=NULL; cur=cur->next)
    {
        printf("[%c] ",cur->data);
    }
    printf("\n");
    return;
}

void TestInit()
{
    SHOW_NAME;
    LinkQueue q;
    LinkQueueInit(&q);
}

void TestDestroy()
{
    SHOW_NAME;
    LinkQueue q;
    LinkQueueInit(&q);
    LinkQueueDestroy(&q);
}

void TestPush()
{
    SHOW_NAME;
    LinkQueue q;
    LinkQueueInit(&q);
    LinkQueuePush(&q,'a');
    LinkQueuePush(&q,'b');
    LinkQueuePush(&q,'c');
    LinkQueuePush(&q,'d');
    LinkQueuePush(&q,'e');
    LinkQueuePrint(&q,"入队五个元素");
}

void TestPop()
{
    SHOW_NAME;
    LinkQueue q;
    LinkQueueInit(&q);
    LinkQueuePush(&q,'a');
    LinkQueuePush(&q,'b');
    LinkQueuePush(&q,'c');
    LinkQueuePush(&q,'d');
    LinkQueuePush(&q,'e');
    LinkQueuePrint(&q,"入队五个元素");
    LinkQueuePop(&q);
    LinkQueuePop(&q);
    LinkQueuePop(&q);
    LinkQueuePrint(&q,"出队三个元素");
    LinkQueuePush(&q,'f');
    LinkQueuePush(&q,'g');
    LinkQueuePush(&q,'h');
    LinkQueuePrint(&q,"入队三个元素");
    LinkQueuePop(&q);
    LinkQueuePop(&q);
    LinkQueuePop(&q);
    LinkQueuePrint(&q,"出队三个元素");
    LinkQueuePop(&q);
    LinkQueuePop(&q);
    LinkQueuePrint(&q,"出队两个元素");
}

void TestGetFront()
{
    SHOW_NAME;
    LinkQueue q;
    LinkQueueInit(&q);
    LinkQueuePush(&q,'a');
    LinkQueuePush(&q,'b');
    LinkQueuePush(&q,'c');
    LinkQueuePrint(&q,"入队三个元素");
    int ret;
    LinkNodeType value;
    ret = LinkQueueGetFront(&q,&value);
    if(ret == 1)
        printf("取得队首元素为 %c\n",value);
    else
        printf("未取得队首元素\n");
    LinkQueuePop(&q);
    LinkQueuePop(&q);
    LinkQueuePop(&q);
    LinkQueuePrint(&q,"出队三个元素");
    ret = LinkQueueGetFront(&q,&value);
    if(ret == 1)
        printf("取得队首元素为 %c\n",value);
    else
        printf("未取得队首元素\n");
}

int main()
{
    TestInit();
    TestDestroy();
    TestPush();
    TestPop();
    TestGetFront();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lycorisradiata__/article/details/79937803