一.队列介绍
1.什么是队列
队列是限制在两端进行插入操作和删除操作的线性表
允许进行存入操作的一端称为"队尾"
允许进行删除操作的一端称为"队头"
当线性表中没有元素时,称为"空队"
特点 :先进先出(FIFO)
队列有一下两种

2.顺序队列
typedef int data_t ; /*定义队列中数据元素的数据类型*/
#define N 64 /*定义队列的容量*/
typedef struct {
data_t data[N] ; /*用数组作为队列的储存空间*/
int front, rear ; /*指示队头位置和队尾下一个位置的指针*/
} sequeue_t ; /*顺序队列类型定义*/
顺序队列我们常用循环队列,循环队列有个特点就是为了区别空队和满队,满队元素个数比数组元素个数少一个

代码框架
sequeue.h
typedef int datatype ;
#define N 128
typedef struct
{
data_t data[N];
int front,rear;
}sequeue;
sequeue *queue_create();
int enqueue(sequeue *sq,datatype x);
datatype dequeue(sequeue *sq);//出队
int queue_empty(sequeue *sq);
int queue_full(sequeue *sq);
int queue_clear(sequeue *q);
sequeue * queue_free(sequeue *sq);
sequeue.c
#include <stdio.h>
#include <stdlib.h>
#include "sequeue.h"
#include <string.h>
sequeue *queue_create(){
sequeue *sq;
if((sq=(sequeue *)malloc(sizeof(sequeue)))==NULL){
printf("malloc failed\n");
return NULL;
}
memset(sq->data,0,sizeof(data));
sq->front=sq->rear=0;
return sq;
}
int enqueue(sequeue *sq,datatype x){
if(sq==NULL){
printt("sq is NULL\n");
return -1;
}
}
test.c
#include<stdio.h>
#include "sequeue.h"
int main()
{
sequeue *sq;
sq=queue_create();
if(sq==NULL){
return -1;
}
enqueue(sq,10);
enqueue(sq,100);
enqueue(sq,1000);
while(!queue_empty(sq)){
printf("dequeue:%d\n",dequeue(sq));
}
return 0;
}
具体代码编写
创建队列
创建一个结构体指针,分配内存,判断是否分配成功,成功之后给成员data初始化,让队尾和队头都为0;
sequeue *queue_create(){
sequeue *sq;
if((sq=(sequeue *)malloc(sizeof(sequeue)))==NULL){
printf("malloc failed\n");
return NULL;
}
memset(sq->data,0,sizeof(data));
sq->front=sq->rear=0;
return sq;
}
入队
判断rear向后移动一位,rear与front是否相等,相等说明队满了,不等进行入队操作
int enqueue(sequeue *sq,datatype x){
if(sq==NULL){
printf("sq is NULL\n");
return -1;
}
if((sq->rear+1%N)==sq->front){//循环队列是不能超过队列的最大值的
printf("sequeue is full\n");
return -1;
}
sq->data[sq->rear]=x;
sq->rear=(sq->rear+1)%N;
return 0;
}
出队
datatype dequeue(sequeue *sq){//出队
datatype ret;
if(sq==NULL){
printf("sq is NULL\n");
return -1;
}
ret=sq->data[sq->front];
sq->front=(sq->front+1)%N;
return ret;
}
判断队列情况
int queue_empty(sequeue *sq){
if(sq==NULL){
printf("sq is NULL\n");
return -1;
}
return (sq->front==sq->rear?1:0);
}
int queue_full(sequeue *sq){
if(sq==NULL){
printf("sq is NULL\n");
return -1;
}
if((sq->rear+1%N)==sq->front){
printf("sequeue is full\n");
return -1;
}
else
return 0;
}
清空队列元素
int queue_clear(sequeue *sq){
if(sq==NULL){
printf("sq is NULL\n");
return -1;
}
sq->front=sq->rear=0;
return 0;
}
释放队列内存
sequeue * queue_free(sequeue *sq){
if(sq==NULL){
printf("sq is NULL\n");
return NULL;
}
free(sq);
sq=NULL;
return NULL;
}
3.链式队列


linkqueue.h
typedef struct node
{
data_t data;
struct node *next;
}listnode,*linklist;
typedef struct{
linklist front;
linklist rear;
}linkqueue;
linkqueue *queue_crearte();
int enqueue(linkqueue *lq,datatype x);
datatype dequeue(lingkqueue *lq);
int queue_empty(linkqueue *le);
int queue_clear(linkqueue *lq);
int queue_free(linkqueue *lq);
linkqueue.c
#include "linkqueue.h"
int main()
{
linkqueue *lq;
lq=queue_create();
if(lq==NULL){
return -1;
}
enqueue(lq,10);
enqueue(lq,100);
enqueue(lq,1000);
enqueue(lq,200);
while(!queue_empty(lq)){
printf("dequeue:%d\n",dequeue(lq));
}
queue_free(lq);
return 0;
}
创建队列
单链表是有头指针的,如果为空front与rear也是要指向一个头节点,并且两个都需要申请内存,其次front和rear都是一个结构体,结构体里面的data,next需要初始化

linkqueue *queue_create(){
linkqueue *lq;
if((lq=(linkqueue *)malloc(sizeof(linkqueue)))==NULL){
printf("malloc linkqueue failed\n");
return NULL;
}
lq->front=lq->rear=(linklist)malloc(sizeof(listnode));//同一个内存空间
if(lq->front==NULL){
printf("malloc is failed\n");
return NULL;
}
lq->front->data=0;
lq->front->next=NULL;//或则lq->rear->next=NULL,只需对一个就行,因为指向同一个内存空间
return lq;
}
入队
需要封装一个节点p去指向入队的元素,封装节点需要创建,申请内存,之后去指向入队元素。
之后rear->next指向p,再移动rear到p
int enqueue(linkqueue *lq,data_t x){
linklist p;
if(lq==NULL){
printf("lq is NULL");
return -1;
}
//申请内存空间
if((p=(linklist)malloc(sizeof(listnode)))==NULL){
printf("malloc node failed\n");
return -1;
}
//指向新元素
p->data=x;
p->next=NULL;
//插入操作
lq->rear->next=p;
lq->rear=p;
return 0;
}
出队
出队就是把front往后移动,frear->data初值是没有数据的,往后移动一位就是队的第一个数据,此时返回front->data就是把第一个入队的出队了;front的移动需要一个指针p来协助,以及用p释放出队的元素的内存
data_t dequeue(linkqueue *lq){
linklist p;
if(lq==NULL){
printf("lq is NULL");
return -1;
}
p=lq->front;
lq->front=p->next;
free(p);
p=NULL;
return (lq->front->data);
}
是否为空
查看front与rear是否相同就行,相同就是空
int queue_empty(linkqueue *lq){
if(lq==NULL){
printf("lq is NULL");
return -1;
}
return (lq->front==lq->rear ? 1:0);
}
清空队列
清空队列需要留一个,节点,所以while的判断调节是ql->front->next是否为空
nt queue_clear(linkqueue *lq){
linklist p;
if(lq==NULL){
printf("lq is NULL");
return -1;
}
while(lq->front->next){
p=lq->front;
lq->front=p->next;
printf("free:%d\n",p->data);
free(p);
p=NULL;
}
return 0;
}
释放内存
先while循环释放内层,再释放外层
linkqueue * queue_free(linkqueue *lq){
linklist p;
if(lq==NULL){
printf("lq is NULL");
return NULL;
}
while(lq->front){
p=lq->front;
lq->front=p->next;
printf("free:%d\n",p->data);
free(p);
p=NULL;
}
free(lq);
lq=NULL;
return NULL;
}
96,9 98%