队列
先进先出,受限的线性表,主要是分成三种:顺序队列,循环队列,链队。
顺序队列
0.简记
顺序队列并不常用,经常使用循环队列来避免假溢出的情况
//1.初始: s->front=s->rear=-1;
//2.队空 s->front=s->rear;
//3.队满 s->rear=MAXSIZE-1;
//4.队尾入队 s->rear++; s->base[s->rear]=e;
//5.队首出队s->front++; *e=s->base[s->front];
1.结构体
//1.基本结构体
#define MAXSIZE 10
typedef struct
{
char* base;//存储基地址
int front;
int rear;//这两个是用来存储下标的
}queue;
2.初始化队列
//2.初始化,创建了一个空队列
void init(queue* s)
{ char *qq=s->base=(char*)malloc(MAXSIZE*sizeof(char));//提前创建一个指针用于释放该段空间
for(int i=0;i<MAXSIZE;i++)
{
qq[i]=97+i;
printf("%c\t",qq[i]);
printf("%c\t",*(s->base+i*sizeof(char)));//分配空间后,s->base指向的是首个元素的地址,可以通过基地址偏移来逐渐输出数据
}
s->front=s->rear=-1;//队空的条件
}
3.入队
void push(queue* s,char e)
{
//首先需要判断是不是满了
if(s->rear==MAXSIZE-1)
return exit(0);
s->rear++;
s->base[s->rear]=e;
}
4.出队
void pop(queue* s,char* e)//出队
{
if(s->rear==s->front)
exit(0);
s->front++;
*e=s->base[s->front];
}
5.完整代码如下
#include <stdio.h>
#include <stdlib.h>
//顺序队列,存在假溢的现象
//1.基本结构体
#define MAXSIZE 10
typedef struct
{
char* base;//存储基地址
int front;
int rear;//这两个是用来存储下标的
}queue;
//2.初始化,创建了一个空队列
void init(queue* s)
{ char *qq=s->base=(char*)malloc(MAXSIZE*sizeof(char));//提前创建一个指针用于释放该段空间
for(int i=0;i<MAXSIZE;i++)
{
qq[i]=97+i;
printf("%c\t",qq[i]);
printf("%c\t",*(s->base+i*sizeof(char)));//分配空间后,s->base指向的是首个元素的地址,可以通过基地址偏移来逐渐输出数据
}
s->front=s->rear=-1;//队空的条件
}
int isfull(queue*s)//用于判断队列是不是满了
{
if (s->rear==MAXSIZE-1)
return 1;
else
return 0;
}
void push(queue* s,char e)
{
//首先需要判断是不是满了
if(s->rear==MAXSIZE-1)
return exit(0);
s->rear++;
s->base[s->rear]=e;
}
void pop(queue* s,char* e)//出队
{
if(s->rear==s->front)
exit(0);
s->front++;
*e=s->base[s->front];
}
void showqueue(queue* s)//队列的显示
{
for(int i=0;i<MAXSIZE;i++)
{
printf("%c",*(s->base+i));
}
}
int main()
{
queue q;
queue* q1=&q;
init(q1);//初始化,创建了一个空队列
printf("%d\n",isfull(&q));
printf("%c\n",*(q1->base+1));
char g=65;
push(q1,g);//入队
showqueue(q1);
char* q2=(char*)malloc(sizeof(char));//出队
pop(q1,q2);
printf("取出的的数据是%c",*q2);
return 0;
}
6.运行结果
a a b b c c d d e e f f g g h h i i j j 0
b
Abcdefghij取出的的数据是A
循环队列
是为解决假溢出,什么是假溢出?
如图所示:
主要区别
队满和队空的概念,因为是循环队列 ,所以空和满的概念有些不同
MAXSIZE=4,但是此时rear已经不能加1,然后入队元素了,此时就称之为队满
//1.初始: s->front=s->rear=-1;
//2.队空 s->front=s->rear;
//3.队满 (s->rear+1)%MAXSIZE=s->front;
//4.队尾入队 s->rear=(s->rear+1)%MAXSIZE; s->data[s->rear]=e;
//5.队首出队s->front=(s->front+1)%MAXSIZE; *e=s->data[s->front];
链队
0.简记
(等数据结构更完,手写的笔记上传一下)
//队空 s->front==NULL&&s->rear==NULL
// 只有一个元素 s->front->next==NULL)
1.结构体
//结构点
//值节点(多个)
typedef struct
{
int data;
struct dnote* next;//这里只有循环的时候在多加一个struct
}dnode;
//头节点(首尾指针,只有一个,用于表示整个链队的指针)
typedef struct
{
dnode* front;
dnode* rear;
}hnode;
2.初始化
//初始化
hnode* init()
{
hnode* s=(hnode*)malloc(sizeof(hnode));//创建一个头节点的指针来储存头节点数据
s->front=NULL;//头节点和尾节点都指向空
s->rear=NULL;
return s;
}
3.入队
hnode* push(hnode*s,int e)
{
//错误示范:dnode* q 创建一个指针一般需要将它指向一个固有的地址,为其分配空间,才能正常使用。
dnode* q=(dnode*)malloc(sizeof(dnode));
q->data=e;
q->next=NULL;//第一步,需要先创建一个值节点来储存要插入的值,然后指针指向空
if(s->front!=NULL||s->rear!=NULL)
{
s->rear->next=q;//尾指针指向的节点指针指向q,尾指针也指向q
s->rear=q;
}
else
{ s->front=q;
s->rear=q;
}
return s;
}
4.出队
void pop(hnode* s, int* e)
{
if(s->front==NULL&&s->rear==NULL)//判断是不是空
exit(0);
else
{ dnode *t;//创建临时指针,方便释放节点
t=s->front;
*e=t->data;
if(s->front->next==NULL)//只有一个元素
{
s->front=NULL;
s->rear=NULL;
}
else //有多个元素
{
s->front=t->next;
}
free(t);
}
}
5.显示
//基本和链表一致,输入元素是头结构体
void showlist(hnode* l)
{
dnode* p=l->front;
while(p!=NULL)
{
printf("%d",p->data);
p=p->next;
}
printf("数据已经输出完毕\n");
}
6.完整代码
#include <stdio.h>
#include <stdlib.h>
//结构点
//值节点(多个)
typedef struct
{
int data;
struct dnote* next;//这里只有循环的时候在多加一个struct
}dnode;
//头节点(首尾指针,只有一个,用于表示整个链队的指针)
typedef struct
{
dnode* front;
dnode* rear;
}hnode;
//初始化
hnode* init()
{
hnode* s=(hnode*)malloc(sizeof(hnode));//创建一个头节点的指针来储存头节点数据
s->front=NULL;//头节点和尾节点都指向空
s->rear=NULL;
return s;
}
hnode* push(hnode*s,int e)
{
//错误示范:dnode* q 创建一个指针一般需要将它指向一个固有的地址,为其分配空间,才能正常使用。
dnode* q=(dnode*)malloc(sizeof(dnode));
q->data=e;
q->next=NULL;//第一步,需要先创建一个值节点来储存要插入的值,然后指针指向空
if(s->front!=NULL||s->rear!=NULL)
{
s->rear->next=q;//尾指针指向的节点指针指向q,尾指针也指向q
s->rear=q;
}
else
{ s->front=q;
s->rear=q;
}
return s;
}
void pop(hnode* s, int* e)
{
if(s->front==NULL&&s->rear==NULL)//判断是不是空
exit(0);
else
{ dnode *t;//创建临时指针,方便释放节点
t=s->front;
*e=t->data;
if(s->front->next==NULL)//只有一个元素
{
s->front=NULL;
s->rear=NULL;
}
else //有多个元素
{
s->front=t->next;
}
free(t);
}
}
void showlist(hnode* l)
{
dnode* p=l->front;
while(p!=NULL)
{
printf("%d",p->data);
p=p->next;
}
printf("数据已经输出完毕\n");
}
int main()
{
hnode* s1=init();//init
hnode* s2=push(s1,1);//push
hnode* s3=push(s2,3);
hnode* s4=push(s3,5);
showlist(s4);
int* e=(int*)malloc(sizeof(int));//pop
pop(s4,e);
showlist(s4);
printf("%d\n",*e);
pop(s4,e);
showlist(s4);
printf("%d\n",*e);
return 0;
}
7.运行结果
//135数据已经输出完毕
//35数据已经输出完毕
//1
//5数据已经输出完毕
//3