C语言数据结构(队列、循环队列)

简介: C语言数据结构(队列、循环队列)

一、队列


1、queue.c内容


#include "02queue.h"
//队列的初始化函数
void queue_init(queue *p_queue/*指向调用函数提供的代表队列的结构体存储区*/) {
    //初始化要保证队列里没有数字,也就是
    //head和tail成员变量必须相等
    p_queue->head = 0;
    p_queue->tail = 0;
}
//队列的清理函数
void queue_deinit(queue *p_queue) {
    //清理函数需要把队列里的数字都删除
    p_queue->head = 0;
    p_queue->tail = 0;
}
//获得队列里数字个数的函数
int /*表示得到的数字个数*/queue_size(const queue *p_queue) {
    return p_queue->tail - p_queue->head;
}
//判断队列是否空的函数
int /*返回值为真表示队列空,否则不空*/queue_empty(const queue *p_queue) {
    return p_queue->head == p_queue->tail;
}
//判断队列是否满的函数
int /*返回值为真表示队列满,否则不满*/queue_full(const queue *p_queue) {
    //只要最后一个存储区被使用过
    //就表示队列满了
    return p_queue->tail >= SIZE;
}
//向队列里加入数字的函数
int /*返回值为真表示成功加入,否则加入不成功*/queue_push(queue *p_queue, int val/*要加入的数字*/) {
    if (p_queue->tail >= SIZE) {
        //如果队列已经满了就不能在加入数字了
        return 0;
    }
    p_queue->buf[p_queue->tail] = val;   //把新数字放在数组里以tail做下标的存储区里
    p_queue->tail++;    //tail向后移动一步
    return 1;
}
//从队列里获得数字的函数(同时删除数字)
int /*返回值为真表示获得数字成功,否则失败*/queue_pop(queue *p_queue, int *p_val/*用来向调用函数传递数字*/) {
    if (p_queue->head == p_queue->tail) {
        //队列是空的
        return 0;
    }
    *p_val = p_queue->buf[p_queue->head];   //以head做下标的存储区里面就是最前面的数字,把它赋值给整数指针形式参数指向的存储区
    p_queue->head++;   //把head向后移动一步,这样下次获得的就是后面的数字(相当于把当前数字删除了)
    return 1;
}
//从队列里获得数字的函数(不会删除数字)
int queue_front(const queue *p_queue, int *p_val) {
    if (p_queue->head == p_queue->tail) {
        //队列空的情况
        return 0;
    }
    *p_val = p_queue->buf[p_queue->head];
    return 1;
}


2、queue.h内容


#ifndef           __QUEUE_H__
#define           __QUEUE_H__
typedef struct {
    int buf[SIZE];    //用来存放队列里的数字.前面的数字记录到小下标的存储区里,后面的数字记录到大下标的存储区里.只要最后一个存储区被使用过就认为队列已经被充满了,即使前面有空着的存储区也不可以使用
    int head;         //代表最前面的数字所在的下标.如果队列里没有数字则head应该等于tail
    int tail;         //代表下一个数字应该放置的位置下标
} queue;   //代表队列的结构体类型
//队列的初始化函数
void queue_init(queue */*指向调用函数提供的代表队列的结构体存储区*/);
//队列的清理函数
void queue_deinit(queue *);
//获得队列里数字个数的函数
int /*表示得到的数字个数*/queue_size(const queue *);
//判断队列是否空的函数
int /*返回值为真表示队列空,否则不空*/queue_empty(const queue *);
//判断队列是否满的函数
int /*返回值为真表示队列满,否则不满*/queue_full(const queue *);
//向队列里加入数字的函数
int /*返回值为真表示成功加入,否则加入不成功*/queue_push(queue *, int /*要加入的数字*/);
//从队列里获得数字的函数(同时删除数字)
int /*返回值为真表示获得数字成功,否则失败*/queue_pop(queue *, int * /*用来向调用函数传递数字*/);
//从队列里获得数字的函数(不会删除数字)
int queue_front(const queue *, int *);
#endif      //__QUEUE_H__


3、主函数


#include <stdio.h>
#include "queue.h"
int main() {
    int val = 0;
    queue que = {0};
    queue_init(&que);
    printf("数字个数是%d\n", queue_size(&que)/*获得队列里的数字个数*/);
    printf("判断空的结果是%d\n", queue_empty(&que)/*判断队列是否空*/);
    printf("判断满的结果是%d\n", queue_full(&que));/*判断队列是否满*/
    queue_push(&que, 10);
    queue_push(&que, 20);
    queue_push(&que, 30);
    printf("数字个数是%d\n", queue_size(&que)/*获得队列里的数字个数*/);
    printf("判断空的结果是%d\n", queue_empty(&que)/*判断队列是否空*/);
    printf("判断满的结果是%d\n", queue_full(&que));/*判断队列是否满*/
    queue_front(&que, &val);
    printf("最前面的数字是%d\n", val);
    queue_pop(&que, &val);
    printf("%d ", val);
    queue_pop(&que, &val);
    printf("%d\n", val);
    printf("数字个数是%d\n", queue_size(&que)/*获得队列里的数字个数*/);
    printf("判断空的结果是%d\n", queue_empty(&que)/*判断队列是否空*/);
    printf("判断满的结果是%d\n", queue_full(&que));/*判断队列是否满*/
    queue_push(&que, 40);
    queue_push(&que, 50);
    printf("数字个数是%d\n", queue_size(&que)/*获得队列里的数字个数*/);
    printf("判断空的结果是%d\n", queue_empty(&que)/*判断队列是否空*/);
    printf("判断满的结果是%d\n", queue_full(&que));/*判断队列是否满*/
    while (1) {
        if (!queue_pop(&que, &val)) {
            //不能从队列里获得数字了
            break;
        }
        printf("%d ", val);
    }
    printf("\n");
    printf("数字个数是%d\n", queue_size(&que)/*获得队列里的数字个数*/);
    printf("判断空的结果是%d\n", queue_empty(&que)/*判断队列是否空*/);
    printf("判断满的结果是%d\n", queue_full(&que));/*判断队列是否满*/
    queue_deinit(&que);
    return 0;
}
运行结果:
数字个数是0
判断空的结果是1
判断满的结果是0
数字个数是3
判断空的结果是0
判断满的结果是0
最前面的数字是10
10 20
数字个数是1
判断空的结果是0
判断满的结果是0
数字个数是3
判断空的结果是0
判断满的结果是0
30 40 50
数字个数是0
判断空的结果是1
判断满的结果是0

二、循环队列


1、loop_queue.c文件内容


#include "loop_queue.h"
//队列的初始化函数
void queue_init(queue *p_queue) {
    p_queue->tail = 0;    //下一个数字应该放在下标为0的存储区里
    p_queue->qty = 0;     //队列里还没有数字
}
//队列的清理函数
void queue_deinit(queue *p_queue) {
    p_queue->tail = 0;
    p_queue->qty = 0;
}
//计算第一个数字所在下标的函数
int /*得到的下标*/get_head(const queue *p_queue) {
    //如果tail是6,qty是3
    //使用tail - qty可以得到第一个数字
    //的下标
    //如果tail是3,qty是6
    //使用tail - qty + SIZE可以得到第一个
    //数字的下标
    int ret = p_queue->tail - p_queue->qty;
    if (ret < 0) {
        //最前面的数字在最后面数字的后面
        ret += SIZE;
    }
    return ret;
}
//获得队列里数字个数的函数
int queue_size(const queue *p_queue) {
    return p_queue->qty;
}
//判断队列空的函数
int queue_empty(const queue *p_queue) {
    return !p_queue->qty;
}
//判断队列满的函数
int queue_full(const queue *p_queue) {
    return p_queue->qty >= SIZE;
}
//向队列里加入数字的函数
int queue_push(queue *p_queue, int val) {
    if (p_queue->qty >= SIZE) {
        //队列已经满了
        return 0;
    }
    p_queue->buf[p_queue->tail] = val;
    p_queue->tail++;
    if (p_queue->tail >= SIZE) {
        //当最后一个存储区里已经放好数字后
        //应该把tail设置成0,表示后面的
        //数字应该从下标为0的存储区
        //开始继续存放
        p_queue->tail = 0;
    }
    p_queue->qty++;    //数字个数加一
    return 1;
}
//从队列里获得数字的函数(同时删除数字)
int queue_pop(queue *p_queue, int *p_val) {
    if (!p_queue->qty) {
        //队列是空的
        return 0;
    }
    *p_val = p_queue->buf[get_head(p_queue)];   //首先计算第一个数字所在存储区的下标,然后把这个存储区里的数字传递给调用函数
    p_queue->qty--;     //把数字个数减一,这导致最前面数字所在的下标向后移动一步(相当于删除最前面的数字)
    return 1;
}
//从队列里获得数字的函数(不会删除数字)
int queue_front(const queue *p_queue, int *p_val) {
    if (!p_queue->qty) {
        //队列是空的
        return 0;
    }
    *p_val = p_queue->buf[get_head(p_queue)];
    return 1;
}

2、loop_queue.h文件内容


#ifndef          __LOOP_QUEUE_H__
#define          __LOOP_QUEUE_H__
typedef struct {
    int buf[SIZE];    //用来存放队列里的数字.前面的数字存放在小下标的存储区里,后面的数字存放在大下标的存储区里.当最后一个存储区被使用过以后可以把后面的数字存放在下标为0的存储区里(前提条件是下标为0的存储区里没有有效数字)
    int qty;          //记录队列里的数字个数
    int tail;         //记录下一个数字应该放置的存储区下标
} queue;    //代表循环队列的结构体
//队列的初始化函数
void queue_init(queue *);
//队列的清理函数
void queue_deinit(queue *);
//获得队列里数字个数的函数
int queue_size(const queue *);
//判断队列空的函数
int queue_empty(const queue *);
//判断队列满的函数
int queue_full(const queue *);
//向队列里加入数字的函数
int queue_push(queue *, int );
//从队列里获得数字的函数(同时删除数字)
int queue_pop(queue *, int *);
//从队列里获得数字的函数(不会删除数字)
int queue_front(const queue *, int *);
#endif         //__03LOOP_QUEUE_H__


3、主函数内容


#include <stdio.h>
#include "loop_queue.h"
int main() {
    int val = 0;
    queue que = {0};
    queue_init(&que);
    printf("数字个数是%d\n", queue_size(&que)/*获得队列里的数字个数*/);
    printf("判断空的结果是%d\n", queue_empty(&que)/*判断队列是否空*/);
    printf("判断满的结果是%d\n", queue_full(&que));/*判断队列是否满*/
    queue_push(&que, 10);
    queue_push(&que, 20);
    queue_push(&que, 30);
    printf("数字个数是%d\n", queue_size(&que)/*获得队列里的数字个数*/);
    printf("判断空的结果是%d\n", queue_empty(&que)/*判断队列是否空*/);
    printf("判断满的结果是%d\n", queue_full(&que));/*判断队列是否满*/
    queue_front(&que, &val);
    printf("最前面的数字是%d\n", val);
    queue_pop(&que, &val);
    printf("%d ", val);
    queue_pop(&que, &val);
    printf("%d\n", val);
    printf("数字个数是%d\n", queue_size(&que)/*获得队列里的数字个数*/);
    printf("判断空的结果是%d\n", queue_empty(&que)/*判断队列是否空*/);
    printf("判断满的结果是%d\n", queue_full(&que));/*判断队列是否满*/
    queue_push(&que, 40);
    queue_push(&que, 50);
    printf("数字个数是%d\n", queue_size(&que)/*获得队列里的数字个数*/);
    printf("判断空的结果是%d\n", queue_empty(&que)/*判断队列是否空*/);
    printf("判断满的结果是%d\n", queue_full(&que));/*判断队列是否满*/
    while (1) {
        if (!queue_pop(&que, &val)) {
            //不能从队列里获得数字了
            break;
        }
        printf("%d ", val);
    }
    printf("\n");
    printf("数字个数是%d\n", queue_size(&que)/*获得队列里的数字个数*/);
    printf("判断空的结果是%d\n", queue_empty(&que)/*判断队列是否空*/);
    printf("判断满的结果是%d\n", queue_full(&que));/*判断队列是否满*/
    queue_deinit(&que);
    return 0;
}
运行结果:
数字个数是0
判断空的结果是1
判断满的结果是0
数字个数是3
判断空的结果是0
判断满的结果是0
最前面的数字是10
10 20
数字个数是1
判断空的结果是0
判断满的结果是0
数字个数是3
判断空的结果是0
判断满的结果是0
30 40 50
数字个数是0
判断空的结果是1
判断满的结果是0


目录
打赏
0
1
0
0
116
分享
相关文章
C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合
本文深入解析了C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合,旨在帮助读者掌握这一高效的数据处理方法。
149 1
|
3月前
|
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
183 77
|
2月前
|
STL——栈和队列和优先队列
通过以上对栈、队列和优先队列的详细解释和示例,希望能帮助读者更好地理解和应用这些重要的数据结构。
32 11
☀☀☀☀☀☀☀有关栈和队列应用的oj题讲解☼☼☼☼☼☼☼
### 简介 本文介绍了三种数据结构的实现方法:用两个队列实现栈、用两个栈实现队列以及设计循环队列。具体思路如下: 1. **用两个队列实现栈**: - 插入元素时,选择非空队列进行插入。 - 移除栈顶元素时,将非空队列中的元素依次转移到另一个队列,直到只剩下一个元素,然后弹出该元素。 - 判空条件为两个队列均为空。 2. **用两个栈实现队列**: - 插入元素时,选择非空栈进行插入。 - 移除队首元素时,将非空栈中的元素依次转移到另一个栈,再将这些元素重新放回原栈以保持顺序。 - 判空条件为两个栈均为空。
c语言及数据结构实现简单贪吃蛇小游戏
c语言及数据结构实现简单贪吃蛇小游戏
|
3月前
|
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
【数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】初始化队列、销毁队列、判断队列是否为空、进队列、出队列等。本关任务:编写一个程序实现环形队列的基本运算。(6)出队列序列:yzopq2*(5)依次进队列元素:opq2*(6)出队列序列:bcdef。(2)依次进队列元素:abc。(5)依次进队列元素:def。(2)依次进队列元素:xyz。开始你的任务吧,祝你成功!(4)出队一个元素a。(4)出队一个元素x。
99 13
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
数据结构(C语言)之对归并排序的介绍与理解
归并排序是一种基于分治策略的排序算法,通过递归将数组不断分割为子数组,直到每个子数组仅剩一个元素,再逐步合并这些有序的子数组以得到最终的有序数组。递归版本中,每次分割区间为[left, mid]和[mid+1, right],确保每两个区间内数据有序后进行合并。非递归版本则通过逐步增加gap值(初始为1),先对单个元素排序,再逐步扩大到更大的区间进行合并,直至整个数组有序。归并排序的时间复杂度为O(n*logn),空间复杂度为O(n),且具有稳定性,适用于普通排序及大文件排序场景。
|
3月前
|
【C++数据结构——栈与队列】链栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现链栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储整数,最大
66 9
|
3月前
|
C++
【C++数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】
【数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】(1)遇到左括号:进栈Push()(2)遇到右括号:若栈顶元素为左括号,则出栈Pop();否则返回false。(3)当遍历表达式结束,且栈为空时,则返回true,否则返回false。本关任务:编写一个程序利用栈判断左、右圆括号是否配对。为了完成本关任务,你需要掌握:栈对括号的处理。(1)遇到左括号:进栈Push()开始你的任务吧,祝你成功!测试输入:(()))
67 7
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
117 1
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等