C语言队列基本操作

1.顺序循环队列

顺序循环队列里base作为数组存放数据,定义front和rear的整型数值,控制队列的起始位置。当rear超过数组长度时,若数组的第一个位置还有空间,就将数据压入的base里的第一个位置,并且rear等于0。当base里的存储长度减去1等于定义的长度时,队列为满队。

代码:  

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
// 循环队列,先进先出

#define MAXSIZE 5

typedef struct queue
{
    int *base;
    int front;
    int rear;
    //  rear = front队列为空, (rear+1)%MAXSIZE = front队列为满队(如果不留一个位置,当队列满时,rear = front)
} Queue;

void InitQueue(Queue *Q)
{
    Q->base = (int *)malloc(MAXSIZE * sizeof(int));
    Q->front = 0;
    Q->rear = 0;
}
// 入队: rear = rear + 1, 当rear指向最后一个位置时, rear = MAXSIZE - 1, rear+1后重新从0开始计数。
void EnQueue(Queue *Q, int data)
{
    if ((Q->rear + 1) % MAXSIZE == Q->front)
    {
        puts("队列已满");
    }
    else
    {
        Q->base[Q->rear] = data;
        printf("%d入队\n", data);
        Q->rear = (Q->rear + 1) % MAXSIZE;
    }
}

void DeQueue(Queue *Q, int *data)
{
    if (Q->front == Q->rear)
    {
        puts("队列为空");
    }
    else
    {
        *data = Q->base[Q->front];
        Q->front = (Q->front + 1) % MAXSIZE;
        printf("%d出队\n", *data);
    }
};

void printQueue(Queue *Q)
{
    if (Q->front == Q->rear)
    {
        puts("队列为空");
        return;
    }
    int start = Q->front;
    int end = Q->rear > Q->front ? Q->rear : (Q->rear + MAXSIZE);
    puts("---打印队列---");
    for (int k = start; k < end; k++)
    {
        int location = k % MAXSIZE;
        printf("地址为%d的数据为%d\n", location, Q->base[location]);
    }
}

void GetQueueHead(Queue *Q, int *data)
{
    *data = Q->base[Q->front];
}

int main()
{
    struct queue Q;
    InitQueue(&Q);
    EnQueue(&Q, 11);
    EnQueue(&Q, 12);
    EnQueue(&Q, 13);
    EnQueue(&Q, 14);
    printQueue(&Q);
    int data = -1;
    DeQueue(&Q, &data);
    DeQueue(&Q, &data);
    EnQueue(&Q, 15);
    EnQueue(&Q, 16);
    EnQueue(&Q, 17);
    printQueue(&Q);
    int head;
    GetQueueHead(&Q, &head);
    printf("循环队列的头指针的数据是:%d\n", head);
}

循环队列的长度为5,最多存储4个数据,避免头指针front和尾指针指向同一个地址,和队列为空加以区别,先删除两个数,在加三个数,第三个数17不能入队:

2. 链式队列

 代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
// 链式队列

#define MAXSIZE 5

typedef struct QNode
{
    int data;
    struct QNode *next;
} QNode, *QueuePointer;

typedef struct {
    QueuePointer front; // 队头指针
    QueuePointer rear; // 队尾指针
} LinkQueue;

void InitQueue(LinkQueue *Q) {
    QueuePointer node = (struct QNode *)malloc(sizeof(struct QNode));
    node->data = 0;
    node->next = NULL;
    Q->front = node;
    Q->rear = node;
    // 空队列
}

// 入队
void EnQueue(LinkQueue *Q, int data) {
    struct QNode *node = (struct QNode *)malloc(sizeof(struct QNode));
    node->data = data;
    node->next = NULL;
    Q->rear->next = node; // 第一次设置rear,front的next指针也会指向新的节点
    Q->rear = node; // rear指向新的节点,在队尾
    // Q->front的next指向第一个有数据的节点。Q->front->data为空或者默认为0,不计入队列。
}

// 出队
void DeQueue(LinkQueue *Q, int *data) {
    LinkQueue *p;
    p = Q;
    struct QNode *temp;
    if (p->front == p->rear) {
        puts("队列为空");
        return;
    }
    if (p->front->next == p->rear) {
        *data = p->rear->data;
        p->rear = p->front; // 只有一个节点,删除后队尾指针指向队头指针
        temp = p->front->next;
        delete temp; // 释放删除节点的内存
    } else {
        *data = p->front->next->data;
        temp = p->front->next;
        p->front->next = temp->next; // 跨过要删除的节点,指向下下个节点
        delete temp;
    }
}

int GetQueueHead(LinkQueue *Q) {
    if (Q->front != Q->rear) {
        return Q->front->next->data;
    }
}

void PrintQueue(LinkQueue *Q) {
    LinkQueue *p;
    p = Q;
    struct QNode *head = p->front->next;
    if (p->front == p->rear) {
        puts("队列为空");
        return;
    }
    puts("---打印队列---");
    while(head) {
        printf("队列的数据为%d\n", head->data);
        head = head->next;
    }
}

int EmptyQueue(LinkQueue *Q) {
    if (Q->front == Q->rear) {
        return 1;
    } else return 0;
}

void conversion(LinkQueue *Q, int n) {
    InitQueue(Q);
    int number = n;
    while(number) {
        EnQueue(Q, number % 2);
        number = number / 2;
    }
    PrintQueue(Q);
    printf("---将10进制数据%d转化2进制---\n", n);
    while(!EmptyQueue(Q)) {
        int data;
        DeQueue(Q, &data);
        printf("%d", data);
    }
    printf("\n");
    puts("---end---");
}

int main()
{
    LinkQueue *linkQueue;
    linkQueue = (LinkQueue *)malloc(sizeof(LinkQueue));
    InitQueue(linkQueue);
    EnQueue(linkQueue, 101);
    EnQueue(linkQueue, 102);
    EnQueue(linkQueue, 103);
    EnQueue(linkQueue, 104);
    PrintQueue(linkQueue);
    int data = GetQueueHead(linkQueue);
    printf("队列头节点数据:%d\n", data);
    DeQueue(linkQueue, &data);
    DeQueue(linkQueue, &data);
    DeQueue(linkQueue, &data);
    PrintQueue(linkQueue);
    DeQueue(linkQueue, &data);
    PrintQueue(linkQueue);

    LinkQueue *queue;
    queue = (LinkQueue *)malloc(sizeof(LinkQueue));
    InitQueue(queue);
    // Segmentation fault: 11
    return 0;
}

        main函数里的linkQueue变量和queue变量都使用malloc函数分配了内存,如果去掉这两行程序报错:Segmentation fault: 11。而分配内存的操作通常放在init初始化函数里,如果在init函数里执行Q= (LinkQueue *)malloc(sizeof(LinkQueue)); ,操作非法:

void InitQueue(LinkQueue *Q) {
    QueuePointer node = (struct QNode *)malloc(sizeof(struct QNode));
    Q = (LinkQueue *)malloc(sizeof(LinkQueue));
    node->data = 0;
    node->next = NULL;
    Q->front = node;
    Q->rear = node;
}

以上会报错,所以需要像链表那样重新定义队列的结构:

typedef struct {
    QueuePointer front; // 队头指针
    QueuePointer rear; // 队尾指针
} LinkQueue, *LinkQueuePointer;

然后所有的函数都像链表那样(类比于swap(int *a, int *b)交换函数):

void InitQueue(LinkQueuePointer *Q) {
*Q = (LinkQueuePointer *)malloc(sizeof(LinkQueuePointer));
(*Q)->front = NULL;
(*Q)->rear = NULL;
}

此时Q是结构体指针的指针,*Q是结构体指针,使用(*Q)->front代替Q.front去操作变量。

当然,还有一种方法,就是队列不使用指针初始化,可以这样做:

LinkQueue linkQueue; 

InitQueue(&queue);

...

此时linkQueue = (LinkQueue *)malloc(sizeof(LinkQueue));就可以不要了。

另外,取地址符也是可以改指针的值(这个值是所指向的变量的地址,非指针自己的地址)。试想交换两个数字的函数:swap(&a, &b){a = b;}如果a是指针也是可以改的,即a本来指向一个地址,a=b以后a会指向b所指向的值的地址:

void InitQueue(LinkQueuePointer &T) {
 T = (struct LinkQueue *)malloc(sizeof(struct LinkQueue));
}

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

heine162

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值