赞
踩
队列是一种先进先出的数据结构,FIFO(first in first out)
逻辑结构:线性结构
顺序队列是基于顺序表和两个下标来实现的,一个是队列头front,一个是队列尾rear
入队时,在队列尾入,出队列时,在队列头出。
顺序队列本质就是对顺序表操作的一个约束:只能在一端插入,另一端删除。
一般这种队列我们不直接使用,因为入队时 rear++ 出队列时 front++
每块内存空间只使用了一次,相当于一个一次性的队列了。
循环队列只是对顺序队列的一个小优化,目的是让空间能复用起来。
这种结构就可以让空间复用起来了。
入队列时,不要直接执行rear++,而是改成 rear = (rear+1)%N
出队列时,不要直接执行front++,而是改成 front = (front+1)%N
判断队列空 rear == front
判断队列满 (rear+1)%N == front (浪费了一个存储空间用来区分队列满和队列空 方便写代码)
循环队列的操作:
创建队列
清空队列
销毁队列
入队列 push
判断队列满
出队列 pop
判断队列空
打印队列中所有元素----实际不需要
循环队列代码实现:
loop_queue.h
- #ifndef __LOOP_QUEUE_H__
- #define __LOOP_QUEUE_H__
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- #define N 5
-
- //循环队列的结构体
- typedef struct _Queue{
- int s[N];
- int front;
- int rear;
- }queue_t;
-
- int create_queue(queue_t **my_queue);
- int is_full(queue_t *my_queue);
- int push_queue(queue_t *my_queue, int data);
- int print_queue(queue_t *my_queue);
- int is_empty(queue_t *my_queue);
- int pop_queue(queue_t *my_queue, int *num);
- int clean_queue(queue_t *my_queue);
- int destroy_queue(queue_t **my_queue);
-
- #endif

loop_queue.c
- #include "loop_queue.h"
-
- //创建队列
- int create_queue(queue_t **my_queue){
- if(NULL == my_queue){
- printf("入参为NULL\n");
- return -1;
- }
- *my_queue = (queue_t *)malloc(sizeof(queue_t));
- if(NULL == *my_queue){
- printf("内存分配失败\n");
- return -1;
- }
- memset(*my_queue, 0, sizeof(queue_t));
- return 0;
- }
-
- //判断队列满
- int is_full(queue_t *my_queue){
- if(NULL == my_queue){
- printf("入参为NULL\n");
- return -1;
- }
- return (my_queue->rear+1) % N == my_queue->front ? 1 : 0;
- }
-
- //数据入队列
- int push_queue(queue_t *my_queue, int data){
- if(NULL == my_queue){
- printf("入参为NULL\n");
- return -1;
- }
- if(is_full(my_queue)){
- printf("队列满 入队列失败\n");
- return -1;
- }
- my_queue->s[my_queue->rear] = data;
- my_queue->rear = (my_queue->rear+1)%N;
- return 0;
- }
-
- //遍历打印队列中所有元素
- int print_queue(queue_t *my_queue){
- if(NULL == my_queue){
- printf("入参为NULL\n");
- return -1;
- }
- int i = 0;
- #if 1
- for(i = my_queue->front; i != my_queue->rear; i = (i+1)%N){
- printf("%d ", my_queue->s[i]);
- }
- #else
- for(i = my_queue->front; (i%N) != my_queue->rear; i++){
- printf("%d ", my_queue->s[i%N]);
- }
- #endif
- printf("\n");
- return 0;
- }
-
- //判断队列空
- int is_empty(queue_t *my_queue){
- if(NULL == my_queue){
- printf("入参为NULL\n");
- return -1;
- }
- return my_queue->rear == my_queue->front ? 1 : 0;
- }
-
- //数据出队列
- int pop_queue(queue_t *my_queue, int *num){
- if(NULL == my_queue || NULL == num){
- printf("入参为NULL\n");
- return -1;
- }
- if(is_empty(my_queue)){
- printf("队列空 出队列失败\n");
- return -1;
- }
- *num = my_queue->s[my_queue->front];
- my_queue->front = (my_queue->front+1)%N;
- return 0;
- }
-
- //清空队列
- int clean_queue(queue_t *my_queue){
- if(NULL == my_queue){
- printf("入参为NULL\n");
- return -1;
- }
- //让rear==front即可
- my_queue->rear = my_queue->front = 0;
- return 0;
- }
-
- //销毁队列
- int destroy_queue(queue_t **my_queue){
- if(NULL == my_queue || NULL == *my_queue){
- printf("入参为NULL\n");
- return -1;
- }
- free(*my_queue);
- *my_queue = NULL;
- return 0;
- }

main.c
- #include "loop_queue.h"
-
- int main(int argc, const char *argv[])
- {
- queue_t *my_queue = NULL;
- create_queue(&my_queue);
- printf("my_queue = %p\n", my_queue);//非NULL
-
- //测试入队列
- push_queue(my_queue, 10);
- push_queue(my_queue, 20);
- push_queue(my_queue, 30);
- push_queue(my_queue, 40);
- push_queue(my_queue, 50);//满了 失败
- print_queue(my_queue); // 10 20 30 40
-
- //出队列
- int num = 0;
- pop_queue(my_queue, &num);
- printf("num = %d\n", num);//10
- pop_queue(my_queue, &num);
- printf("num = %d\n", num);//20
- print_queue(my_queue); // 30 40
-
- //入队列
- push_queue(my_queue, 50);
- push_queue(my_queue, 60);
- push_queue(my_queue, 70);//满了 失败
- print_queue(my_queue); // 30 40 50 60
-
- //清空
- clean_queue(my_queue);
- if(-1 == pop_queue(my_queue, &num)){
- printf("没有出队列成功\n");
- }
- //销毁
- destroy_queue(&my_queue);
- printf("my_queue = %p\n", my_queue);//NULL
-
- return 0;
- }

链式队列是基于链表配合两个指针实现的 一个是队列头 front 一个是队列尾 rear
链式队列的本质就是对链表操作的一个约束:只能在一端插入,另一端删除。
一般采用尾插头删的方式
一般采用尾插头删的方式实现队列 操作的时间复杂度都是 O(1)
链式队列的操作:
创建队列
清空队列
销毁队列
入队列 push
出队列 pop
判断队列空
打印队列中所有元素----实际不需要
链式队列的代码实现:
link_queue.h
- #ifndef __LINK_QUEUE_H__
- #define __LINK_QUEUE_H__
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- //链表节点结构体
- typedef struct _Node{
- int data;
- struct _Node *next;
- }node_t;
-
- //循环队列的结构体
- typedef struct _Queue{
- node_t *rear;
- node_t *front;
- }queue_t;
-
- int create_queue(queue_t **my_queue);
- int push_queue(queue_t *my_queue, int data);
- int print_queue(queue_t *my_queue);
- int is_empty(queue_t *my_queue);
- int pop_queue(queue_t *my_queue, int *num);
- int clean_queue(queue_t *my_queue);
- int destroy_queue(queue_t **my_queue);
-
- #endif

link_queue.c
- #include "link_queue.h"
-
- //创建队列
- int create_queue(queue_t **my_queue){
- if(NULL == my_queue){
- printf("入参为NULL\n");
- return -1;
- }
- *my_queue = (queue_t *)malloc(sizeof(queue_t));
- if(NULL == *my_queue){
- printf("内存分配失败\n");
- return -1;
- }
- memset(*my_queue, 0, sizeof(queue_t));
- return 0;
- }
-
- //数据入队列
- int push_queue(queue_t *my_queue, int data){
- if(NULL == my_queue){
- printf("入参为NULL\n");
- return -1;
- }
- //创建新节点
- node_t *pnew = (node_t *)malloc(sizeof(node_t));
- if(NULL == pnew){
- printf("内存分配失败\n");
- return -1;
- }
- pnew->data = data;
- pnew->next = NULL;
- //将新节点插入队列
- if(NULL == my_queue->front && NULL == my_queue->rear){//说明是第一个节点
- my_queue->rear = pnew;
- my_queue->front = pnew;
- }else{
- my_queue->rear->next = pnew;
- my_queue->rear = pnew;
- }
- return 0;
- }
-
- //遍历所有元素
- int print_queue(queue_t *my_queue){
- if(NULL == my_queue){
- printf("入参为NULL\n");
- return -1;
- }
- node_t *ptemp = my_queue->front;
- while(NULL != ptemp){
- printf("%d ", ptemp->data);
- ptemp = ptemp->next;
- }
- printf("\n");
- return 0;
- }
-
- //判断队列空
- int is_empty(queue_t *my_queue){
- if(NULL == my_queue){
- printf("入参为NULL\n");
- return -1;
- }
- return NULL == my_queue->front && NULL == my_queue->rear ? 1 : 0;
- }
-
- //数据出队列
- int pop_queue(queue_t *my_queue, int *num){
- if(NULL == my_queue || NULL == num){
- printf("入参为NULL\n");
- return -1;
- }
- if(is_empty(my_queue)){
- printf("队列空 出队列失败\n");
- return -1;
- }
- *num = my_queue->front->data;
- node_t *pdel = my_queue->front;
- my_queue->front = pdel->next;
- free(pdel);
- pdel = NULL;
- //如果是最后一个节点 记得把 rear 也置成NULL
- if(NULL == my_queue->front){
- my_queue->rear = NULL;
- }
- return 0;
- }
-
- //清空队列
- int clean_queue(queue_t *my_queue){
- if(NULL == my_queue ){
- printf("入参为NULL\n");
- return -1;
- }
- node_t *pdel = NULL;
- while(NULL != my_queue->front){
- pdel = my_queue->front;
- my_queue->front = pdel->next;
- free(pdel);
- }
- pdel = NULL;
- my_queue->rear = NULL;
- return 0;
- }
-
- //销毁队列
- int destroy_queue(queue_t **my_queue){
- if(NULL == my_queue || NULL == *my_queue){
- printf("入参为NULL\n");
- return -1;
- }
- //先清空再销毁
- clean_queue(*my_queue);
- free(*my_queue);
- *my_queue = NULL;
- return 0;
- }

main.c
- #include "link_queue.h"
-
- int main(int argc, const char *argv[])
- {
- queue_t *my_queue = NULL;
- create_queue(&my_queue);
- printf("my_queue = %p\n", my_queue);//非NULL
-
- //测试入队列
- push_queue(my_queue, 10);
- push_queue(my_queue, 20);
- push_queue(my_queue, 30);
- push_queue(my_queue, 40);
- print_queue(my_queue); // 10 20 30 40
-
- //出队列
- int num = 0;
- pop_queue(my_queue, &num);
- printf("num = %d\n", num);//10
- pop_queue(my_queue, &num);
- printf("num = %d\n", num);//20
- print_queue(my_queue); // 30 40
-
- //入队列
- push_queue(my_queue, 50);
- push_queue(my_queue, 60);
- print_queue(my_queue); // 30 40 50 60
-
- //清空
- clean_queue(my_queue);
- if(-1 == pop_queue(my_queue, &num)){
- printf("没有出队列成功\n");
- }
-
- //销毁
- destroy_queue(&my_queue);
- printf("my_queue = %p\n", my_queue);//NULL
-
- return 0;
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。