一 队列
队列(Queue)是一种数据结构,它遵循先进先出(First-In-First-Out,FIFO)的原则。队列中的数据
项只能在一端插入,而在另一端删除。插入操作称为入队(enqueue),删除操作称为出队(dequeue)。
二 顺序队列
1、定义
顺序队列(Sequential Queue)是一种使用数组实现的队列。在顺序队列中,数据项按照插入的顺序排列,并且在队头进行删除操作,在队尾进行插入操作。实现顺序队列时,需要定义一个固定大小的数组,使用两个指针(front指针和rear指针)来分别表示队头和队尾的位置。
2、代码示例
头文件
/*===============================================
* 文件名称:seqqueue.h
* 创 建 者:
* 创建日期:2023年08月09日
* 描 述:
================================================*/
#ifndef _SEQQUEUE_H
#define _SEQQUEUE_H
#define N 1024
typedef int queue_data;
typedef struct seq_squeue
{
queue_data data[N];
int f; //首
int r; // 尾
}squeue, *psqueue;
//创建
psqueue init_seqqueue();
//入队
int input_seqqueue(psqueue Q , queue_data value);
//出队
int out_seqqueue(psqueue Q);
//判空
int empty_seqqueue(psqueue Q);
//判满
int full_seqqueue(psqueue Q );
#endif
功能代码
/*===============================================
* 文件名称:seqqueue.c
* 创 建 者:
* 创建日期:2023年08月09日
* 描 述:
================================================*/
#include <stdio.h>
#include "seqqueue.h"
#include <stdlib.h>
//创建
psqueue init_seqqueue()
{
psqueue Q = (psqueue ) malloc(sizeof(squeue));
if( NULL == Q )
return NULL;
Q->r = 0; //队尾
Q->f = 0;//队首
return Q;
}
//入队
int input_seqqueue(psqueue Q , queue_data value)
{
if( NULL == Q )
return -1;
if( 0 == full_seqqueue(Q))
return -2;
Q->data[Q->r] = value ;// 从队尾插入
Q->r = (Q->r+1)%N; //队尾移动一位
return 0;
}
//出队
queue_data out_seqqueue(psqueue Q)
{
//
if( NULL == Q )
return -1;
if( 0 == empty_seqqueue(Q))
return -2;
queue_data t = Q->data[Q->f];//从队头出队
Q->f = (Q->f+1)%N; //队头移动一位
return t;
}
//判空
int empty_seqqueue(psqueue Q)
{
if( NULL == Q )
return -1;
if( Q->r == Q->f ) // 如果出队与入队标识重合,则为空队列
return 0 ;
else
return 1;
}
//判满
int full_seqqueue(psqueue Q )
{
if( NULL == Q )
return -1;
if( Q->f == (Q->r+1)%N ) // 人为定义,在队尾离队头有一个位置时为满队列,用一个数组元素空间来判断队列是否满
return 0;
else
return 1;
}
测试代码
/*===============================================
* 文件名称:main.c
* 创 建 者:
* 创建日期:2023年08月09日
* 描 述:
================================================*/
#include <stdio.h>
#include "chstack.h"
int main(int argc, char *argv[])
{
//创建
pchstack H = init_chstack();
if( NULL == H )
{
puts("init err");
return -1;
}
//入栈
puts("入栈");
for( int i = 0 ; i < 10 ; i++ )
{
printf("%d " , i+1);
if( 0 != input_chstack(H , i+1))
{
puts("input err");
return -1;
}
}
puts("");
//出栈
puts("出栈");
int ret = 0 ;
while( 0 != empty_chstack(H))
{
if( 0 > (ret = out_chstack( H )))
{
puts("out err");
return -1;
}
printf("%d ",ret);
}
puts("");
return 0;
}
3、运行结果
三 链队列
1、定义
链队列(Linked Queue)是一种使用链表实现的队列。链队列中,每个数据项保存一个指向下一个数据项的指针,通过这些指针将数据项连接在一起。链队列可以动态地增加或删除数据项,因此没有固定的大小限制。在链队列中,只需要一个指向队头和队尾的指针即可。
2、代码示例
头文件
/*===============================================
* 文件名称:chqueue.h
* 创 建 者:
* 创建日期:2023年08月09日
* 描 述:
================================================*/
#ifndef _CHQUEUE_H
#define _CHQUEUE_H
typedef int chqueue_data;
//定义节点类型
typedef struct ch_queue
{
chqueue_data data;
struct ch_queue * next;
}chqueue , *pchqueue;
//定义指向头和尾的指针的类型
typedef struct node
{
pchqueue f; //头
pchqueue r; //尾
}nod,*pnod;
//创建链队列
pnod init_chqueue();
//入队链队列
int input_chqueue(pnod S , chqueue_data value );
//出队链队列
int out_chqueue(pnod S);
//判空
int empty_chqueue(pnod S);
#endif
功能代码
/*===============================================
* 文件名称:chqueue.c
* 创 建 者:
* 创建日期:2023年08月09日
* 描 述:
================================================*/
#include <stdio.h>
#include "chqueue.h"
#include <stdlib.h>
//创建链队列
pnod init_chqueue()
{
//创建链队列头节点
pchqueue H = (pchqueue) malloc(sizeof(chqueue));
if( NULL == H)
return NULL;
//创建一个有两个节点类型指针的结构体空间
pnod S = (pnod) malloc(sizeof(nod));
if( NULL == S )
return NULL;
S->r = S->f = H;//两个指针都指向头节点,其中,r指向尾,f指向头
return S;
}
//入队链队列
int input_chqueue(pnod S , chqueue_data value )
{
if( NULL == S )
return -1;
//开辟一个新节点
pchqueue H = (pchqueue)malloc(sizeof(chqueue));
if( NULL == H)
return -1;
//通过尾插的方式插入链队列
S->r->next = H;//尾节点指向新节点
S->r = H ; // 指针r指向新节点(也是新的尾节点)
H->next = NULL ; // 新节点的next为空
H->data = value ; // 将插入值给新节点
return 0;
}
//出队链队列
int out_chqueue(pnod S)
{
if( NULL == S )
return -1;
// 如果除了头节点外只有一个节点的情况
if( S->f->next == S->r )
{
pchqueue t = S->r;
chqueue_data m = t->data ;
S->r = S->f; // 头指针和尾指针都指向头节点,此时链队列为空
free(t);
t == NULL;
return m ;
}
else // 有超过一个节点的情况
{
pchqueue q = S->f->next; //临时保存需要删除的节点地址
S->f->next = q->next; // 头节点断开被删除的节点,指向删除节点的下一个节点
chqueue_data t = q->data ; //临时保存需要删除的节点数据
free(q); // 释放节点
q =NULL;
return t; //返回节点数据
}
}
//判空
int empty_chqueue(pnod S)
{
if( NULL == S )
return -1;
if( S->r == S->f ) // 如果尾指针和头指针指向一个地方,则链队列为空
return 0;
else
return 1;
}
测试代码
/*===============================================
* 文件名称:main.c
* 创 建 者:
* 创建日期:2023年08月09日
* 描 述:
================================================*/
#include <stdio.h>
#include "chqueue.h"
int main(int argc, char *argv[])
{
//创建链队列
pnod S = init_chqueue();
if( NULL == S )
{
puts("init err");
return -1;
}
//入队
puts("入队");
for( int i = 0 ; i < 10 ; i++ )
{
printf("%d ",i+1);
if( 0 != input_chqueue(S,i+1))
{
puts("input err");
return -1;
}
}
puts("");
//出队
puts("出队");
chqueue_data ret;
while( 0 != empty_chqueue(S))
{
if( 0 > (ret = out_chqueue(S)))
{
puts("out err");
return -1;
}
printf("%d ",ret);
}
puts("");
return 0;
}
总结来说,顺序队列适合于固定大小的队列,插入和删除操作的时间复杂度为O(1);链队列适用于动态大小的队列,插入和删除操作的时间复杂度也为O(1)。