文章目录

  • 1.队列的定义
  • 2.顺序队列及其操作
    • 2.1 队列的顺序存储结构
    • 2.2 顺序队列上的操作
      • (1)创建队列
      • (2)插入
      • (3)删除
  • 3.循环队列及其操作
    • 3.1 循环队列的存储结构
    • 3.2 循环队列上的操作
      • (1)创建循环队列
      • (2)插入
      • (3)删除
  • 4.链队列及其操作
    • 4.1 队列的链存储结构
    • 4.2 链队列上的操作
      • (1)创建链队列
      • (2)插入
      • (3)删除

#队列的定义及其基本操作

  • 队列的定义
  • 顺序队列及其操作
  • 循环队列及其操作
  • 链队列及其操作

1.队列的定义

队列是限制结点插入操作固定在一端进行,而结点的删除操作固定在另一端进行的线性表.

队列犹如一个两端开口的管道.允许插入的一端称为队头,允许删除的一端称为队尾.队头和队尾各用一个"指针"指示,称为队头指针和队尾指针.不含任何结点的队列称为"空队列".队列的特点是结点在队列中的排队次序和出队次序按进队时间先后确定,即先进队者先出队.因此,队列又称先进先出表.简称FIFO(first in first out)表.

2.顺序队列及其操作

2.1 队列的顺序存储结构

顺序存储结构存储的队列称为顺序队列.和顺序表一样,用一个一维数组存.对头在数组的低下标端,队尾设在高下表端.队头,队尾指针值是数组元素的下标.对头指针始终指向对头结点的前一个结点位置,初始值为0.队尾指针是指向队尾结点位置,初始值也为0.

队列初始条件:队头指针=队尾指针=0

队列满条件:队尾指针=m(设队列当前容量为m)

队列空条件:队头指针=队尾指针

在QueueCs.c文件中定义了结构

#define DT char
#define M 100
typedef struct {DT data[M];int front,rear;
}SEQUEUE;

data[M]也为数组为队列,front为队头指针,rear为队尾指针.(注意:front和rear是整数类型,不是指针类型),当front=rear=0时,为初始队列.因为C语言中数组的第一个元素下标为0,而不是1;所以这里约定数组元素data[0]闲置不用.

2.2 顺序队列上的操作

(1)创建队列

初始化队列,队头指针和队尾指针=0.

在QueueControl.h写出方法声明


/*创建队列*/
SEQUEUE initQueue();

在QueueControl.c中实现此方法

#include "QueueControl.h"
/*创建队列*/
SEQUEUE initQueue(){SEQUEUE Q;//1.初始化队列,队头指针=队尾指针=0Q.front=Q.rear=0;return Q;
}

(2)插入

在QueueControl.h写出方法声明


/*插入*/
SEQUEUE inQueue(SEQUEUE Q,DT x);

在QueueControl.c中实现此方法

#include "QueueControl.h"SEQUEUE inQueue(SEQUEUE Q,DT x){//1.判断队列是上溢,就是队尾指针是否等于最大申请的空间if(Q.rear==M){printf("Up Overflow\n");}else{//2.从队尾插入结点Q.rear++;Q.data[Q.rear]=x;printf("in  success\n");}return Q;
}

(3)删除

在QueueControl.h写出方法声明

/*删除*/
SEQUEUE outQueue(SEQUEUE Q);/*打印队列元素*/
void printQueue(SEQUEUE Q);

在QueueControl.c中实现此方法

#include "QueueControl.h"SEQUEUE outQueue(SEQUEUE Q){//1.首先判断是否是空队列if(Q.front==Q.rear){printf("queue is empty\n");}else{//2.删除结点是从队头删除Q.front++;printf("out success\n");}return Q;
}/*打印队列元素*/
void printQueue(SEQUEUE Q){//1.从队头开始打印数据SEQUEUE  temp=Q;printf("queue={");while (temp.front<temp.rear) {temp.front++;if(temp.front==Q.front+1){printf("%c",temp.data[temp.front]);}else{printf(",%c",temp.data[temp.front]);}}printf("}\n");
}

在main.c中的main方法(int main(int argc, const char * argv[]) {})调用此方法,并且进行判断

#include "QueueControl.h"
int main(int argc, const char * argv[]) {//初始化顺序队列SEQUEUE queue=initQueue();printQueue(queue);//插入queue=inQueue(queue, 'a');queue=inQueue(queue, 'b');queue=inQueue(queue, 'c');queue=inQueue(queue, 'd');printQueue(queue);//删除queue=outQueue(queue);printQueue(queue);return 0;}

打印结果:

queue={}
in  success
in  success
in  success
in  success
queue={a,b,c,d}
out success
queue={b,c,d}
Program ended with exit code: 0

从插入队列和删除队列操作的打印结果来看,队列的特点确实是:先进先出.

3.循环队列及其操作

3.1 循环队列的存储结构

根据顺序队列的操作和叙述可以看出,队尾指针=m表示队满,不能再插入结点了,当队头指针等于队尾指针表示对空.但是当队尾指针和队尾指针都等于m的时候,那么此时表示对空,那么也不能插入了其他的结点,但是此时0-m之间的结点已经空闲,这样许多空闲的结点不能被利用,浪费存储空间.

循环队列是把顺序队列的头尾相接形成一个圆环.逻辑上吧1号结点作为m号结点的后继结点处理.

循环队列初始条件:队头指针=队尾指针=0

循环队列队满条件:MOD(队尾指针+1,m)=队头指针

循环队列空条件:队头指针=队尾指针

队头指针推进计算:队头指针=MOD(队头指针+1,m)

队尾指针推进计算:队尾指针=MOD(队尾指针+1,m)

在QueueCycleCs.c文件中定义了结构


#define CDT char
#define CM 5
typedef struct {CDT data[CM];int front,rear;
}SECYCLEQUEUE;

3.2 循环队列上的操作

(1)创建循环队列

初始化队列,队头指针和队尾指针=0.

在QueueCycyleControl.h写出方法声明

#include "QueueCycleCs.c"/*创建循环队列*/
SECYCLEQUEUE initCycleQueue();

在QueueCycyleControl.c中实现此方法

#include "QueueCycleControl.h"
/*创建循环队列*/
SECYCLEQUEUE initCycleQueue(){SECYCLEQUEUE  Q;//队头指针=队尾指针=0;Q.front=Q.rear=0;return Q;
}

(2)插入

在QueueCycyleControl.h写出方法声明

#include "QueueCycleCs.c"/*循环队列插入*/
SECYCLEQUEUE inCycleQueue(SECYCLEQUEUE  Q,char x);

在QueueCycyleControl.c中实现此方法

#include "QueueCycleControl.h"
SECYCLEQUEUE inCycleQueue(SECYCLEQUEUE  Q,CDT x){//1.判断循环队列是否已经满了,MOD(队尾指针+1,m)=队头指针if((Q.rear+1)%CM==Q.front){printf("queue is full!\n");}else{//2.在队尾插入,计算队尾指针的Q.rear=(Q.rear+1)%CM;//3.设置插入结点的值数值Q.data[Q.rear]=x;printf("in Cycle queue Success!\n");}return Q;
}

(3)删除

在QueueCycyleControl.h写出方法声明

#include "QueueCycleCs.c"
/*循环队列删除*/
SECYCLEQUEUE outCycleQueue(SECYCLEQUEUE Q);
/*打印循环队列*/
void printCycleQueue(SECYCLEQUEUE Q);

在QueueCycyleControl.c中实现此方法

#include "QueueCycleControl.h"
SECYCLEQUEUE outCycleQueue(SECYCLEQUEUE Q){//1.判断循环队列是否是空if(Q.front==Q.rear){printf("Cycle queue is Empty!\n");}else{//2.删除结点从队头删除,计算队头指针:队头指针=MOD(队头指针+1,m)Q.front=(Q.front+1)%CM;printf("out cycle queue success!\n");}return Q;
}/*打印循环队列*/
void printCycleQueue(SECYCLEQUEUE Q){//M=5;//1.从队头开始打印数据SECYCLEQUEUE  temp=Q;printf("queue={");//2.判断的条件是,队头指针!=队尾指针while (temp.front!=temp.rear) {temp.front=(temp.front+1)%CM;if(temp.front==((Q.front+1)%CM)){printf("%c",temp.data[temp.front]);}else{printf(",%c",temp.data[temp.front]);}}printf("}\n");
}

在main.c中的main方法(int main(int argc, const char * argv[]) {})调用此方法,并且进行判断

#include "QueueCycleControl.h"
int main(int argc, const char * argv[]) {//创建循环队列SECYCLEQUEUE CQ=initCycleQueue();//插入数据5个结点,但是最大是5,一个空闲,最后一个添加不进去,CQ=inCycleQueue(CQ, 'a');CQ=inCycleQueue(CQ, 'b');CQ=inCycleQueue(CQ, 'c');CQ=inCycleQueue(CQ, 'd');CQ=inCycleQueue(CQ, 'e');printCycleQueue(CQ);//删除节点-三个结点CQ=outCycleQueue(CQ);CQ=outCycleQueue(CQ);CQ=outCycleQueue(CQ);printCycleQueue(CQ);//插入-两个结点CQ=inCycleQueue(CQ, 'e');CQ=inCycleQueue(CQ, 'f');printCycleQueue(CQ);//删除节点--删除四个结点,现在此时是三个结点,最后一个删除不了CQ=outCycleQueue(CQ);CQ=outCycleQueue(CQ);CQ=outCycleQueue(CQ);CQ=outCycleQueue(CQ);printCycleQueue(CQ);return 0;
}

打印结果:

in Cycle queue Success!
in Cycle queue Success!
in Cycle queue Success!
in Cycle queue Success!
queue is full!
queue={a,b,c,d}
out cycle queue success!
out cycle queue success!
out cycle queue success!
queue={d}
in Cycle queue Success!
in Cycle queue Success!
queue={d,e,f}
out cycle queue success!
out cycle queue success!
out cycle queue success!
Cycle queue is Empty!
queue={}
Program ended with exit code: 0

4.链队列及其操作

4.1 队列的链存储结构

链存储结构存储的队列称为链队列.队头指针指向链队列的头结点,头结点的指针域若为空,则为空队列;若不为空,则为指向队首结点的指针.

链队列设有一个队头指针,其值指向队列的头结点.也是唯一地标示一个链队.设置一个队尾指针方便插入结点.队头指针和队尾指针都是指针型变量.

链队列没有容量的限制,所以在可用的存储空间范围内,一般不会出现上溢问题,也不存在如顺序队列的假溢出问题.

在QueueLinkCs.c中定义了结构

#define LDT char
//结点类型
typedef struct llnode{LDT data;struct llnode *next;
}LINKNODE;//链队列结构
typedef struct{LINKNODE *front,*rear;
}LINKQUEUE;

4.2 链队列上的操作

(1)创建链队列

在QueueLinkControl.h写出方法声明


#include <stdio.h>
#include "QueueLinkCs.c"/*创建链队*/
LINKQUEUE * initLinkQueue(LINKQUEUE *LQ);

在QueueLinkControl.c中实现此方法

#include "QueueLinkControl.h"
#include <stdlib.h>
/*创建链队*/
LINKQUEUE *initLinkQueue(LINKQUEUE *LQ){//设置队头指针LQ->front=(LINKNODE *)malloc(sizeof(LINKNODE));LQ->front->data='#';//设置队头指针,也是头结点的指针域LQ->front->next=NULL;//初始条件:队头指针和队尾指针一致LQ->rear=LQ->front;return LQ;
}

(2)插入

在QueueLinkControl.h写出方法声明

/*链队插入:队尾*/
LINKQUEUE * inLinkQueue(LINKQUEUE *LQ,LDT x);

在QueueLinkControl.c中实现此方法

#include "QueueLinkControl.h"
#include <stdlib.h>
LINKQUEUE * inLinkQueue(LINKQUEUE *LQ,LDT x){if(LQ==NULL){LQ=initLinkQueue(LQ);}//1.初始化插入的结点LINKNODE  *q;q=(LINKNODE *)malloc(sizeof(LINKNODE));q->data=x;q->next=NULL;//2.插入式从队尾插入,将插入的结点插入队尾LQ->rear->next=q;//把队尾指针后移LQ->rear=q;printf("in link queue success!\n");return LQ;
}

(3)删除

在QueueLinkControl.h写出方法声明

/*链队删除:队头*/
LINKQUEUE *outLinkQueue(LINKQUEUE *LQ);/*打印链表结点*/
void printLinkQueue(LINKQUEUE *LQ);

在QueueLinkControl.c中实现此方法

#include "QueueLinkControl.h"
#include <stdlib.h>
LINKQUEUE *outLinkQueue(LINKQUEUE *LQ){if(LQ==NULL || LQ->rear==LQ->front){printf("LQ is  empty!\n");return LQ;}//1.获取首结点LINKNODE *frontNextNode;frontNextNode=LQ->front->next;//2.将首节点的next指针域的值存储头结点的next域LQ->front->next=frontNextNode->next;//3.如果队尾结点等于首节点的next指针域的值,那么表示是空栈,根据空链队列的结构,还需修改队尾指针,使指向头结点.if(LQ->rear==frontNextNode){LQ->rear=LQ->front;}//4.释放删除的结点free(frontNextNode);printf("out link queue success!\n");return LQ;
}/*打印链表结点*/
void printLinkQueue(LINKQUEUE *Q){//实例化一个LQ,为了不改变原来链队QLINKQUEUE *LQ;LQ=(LINKQUEUE *)malloc(sizeof(LINKQUEUE));LQ->front=Q->front;LQ->rear=Q->rear;printf("queue={");//1.判断不是空链表if(LQ!=NULL && LQ->rear!=LQ->front){int flag=0;do{//2.输出数据if(flag==0){printf("%c",LQ->front->data);flag=1;}else{printf(",%c",LQ->front->data);}//3.链头指针向后移动LQ->front=LQ->front->next;}while (LQ->front!=LQ->rear) ;printf(",%c",LQ->front->data);}printf("}\n");
}

在main.c中的main方法(int main(int argc, const char * argv[]) {})调用此方法,并且进行判断

#include "QueueLinkControl.h"
int main(int argc, const char * argv[]) {//创建链队列LINKQUEUE  *LQ=(LINKQUEUE *)malloc(sizeof(LINKQUEUE));LQ=initLinkQueue(LQ);//向链队插入结点LQ=inLinkQueue(LQ,'a');LQ=inLinkQueue(LQ,'b');LQ=inLinkQueue(LQ,'c');LQ=inLinkQueue(LQ,'d');printLinkQueue(LQ);//删除结点--从队头LQ=outLinkQueue(LQ);LQ=outLinkQueue(LQ);printLinkQueue(LQ);return 0;
}

打印结果:

in link queue success!
in link queue success!
in link queue success!
in link queue success!
queue={#,a,b,c,d}
out link queue success!
out link queue success!
queue={#,c,d}
Program ended with exit code: 0

这是队列定义和基本操作,请大家指点,有好的建议请大家指出,有好的书籍,还往大家推荐!

源码下载

队列的定义及其基本操作相关推荐

  1. 数据结构入门(五)-队列的定义与实现

    队列的定义 队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表. 队列是一种先进先出(First In First Out)的线性表,简称FIFO.允许插入的一端称为队尾,允 ...

  2. 栈和队列(详细版,一看就懂。包含栈和队列的定义、意义、区别,实现)

    栈和队列 一.栈和队列的定义.区别,存在的意义 1.栈的定义 (1)栈:栈实际上是一种线性表,它只允许在固定的一段进行插入或者删除元素,在进行数据插入或者删除的一段称之为栈顶,剩下的一端称之为栈顶.其 ...

  3. 循环队列,定义循环队列长度为10,编写初始化队列、入队、出队、求队长,实现10,20,30,40,50,60,70,80入队,10,20,30出队,56,67入队的算法功能。

    循环队列,定义循环队列长度为10,编写初始化队列.入队.出队.求队长,实现10,20,30,40,50,60,70,80入队,10,20,30出队,56,67入队的算法功能. #include< ...

  4. java循环的概念_Java数据结构之循环队列简单定义与用法示例

    本文实例讲述了Java数据结构之循环队列简单定义与用法.分享给大家供大家参考,具体如下: 一.概述: 1.原理: 与普通队列的区别在于循环队列添加数据时,如果其有效数据end == maxSize - ...

  5. 循环队列的进队算法c语言,循环队列的定义,入队算法,出队算法,遍历算法,及其代码实现-Go语言中文社区...

    队列 的定义: 一种可以是实现"先进先出"的存储结构.数据的进出类似于排队购票.队只允许队尾一端(rear)添加,在另一端队头(front)删除.队有队头(front)和队尾(re ...

  6. 数据结构之队列的定义与简单实现

    队列的定义与简单实现 和栈相反,队列是一种先进先出(FIFO)的线性表,队列仅在线性表的两端进行操作: 1.队头(Front):取出数据元素的一端: 2.队尾(Rear):插入数据元素的一端. 现实中 ...

  7. 数据结构-栈(Stack)-定义与基本操作

    数据结构-栈(Stack)-定义与基本操作 一. 顺序栈(Sequential Stack) 1. 定义 2. 基本操作 2.1 初始化 2.2 进栈 2.3 出栈 2.4 取栈顶元素 2.5 判空 ...

  8. 数据结构(C语言)——线性表(定义,基本操作)

    数据结构(C语言)--线性表(定义,基本操作) 一. 线性表的定义 二.线性表的基本操作 什么时候要传入引用"==&=="----对参数的修改结果需要"==带回来 ...

  9. 队列的定义、循环队列的顺序存储结构及链式存储结构

    文章目录 1 队列的定义 1.1 文字定义 1.2 代码定义 2 循环队列 2.1 循环队列的定义 2.2 循环队列的顺序存储结构 3 队列的链式存储结构 3.1 链队列的入队操作 3.2 链队列的出 ...

最新文章

  1. shell中定义变量用双引号和单引号以及不用引号的区别
  2. Oracle优化07-分析及动态采样-动态采样
  3. python字符串连接的三种方法及其效率、适用场景详解
  4. abstract类中不可以有private的成员_C++类成员的三种访问权限:public/protected/private...
  5. angular dom_Angular 8 DOM查询:ViewChild和ViewChildren示例
  6. mysql的学习要点_MySQL中的联合索引的学习要点总结
  7. scikit-learn中随机森林使用详解
  8. kafka控制台模拟消费_Flink初试——对接Kafka
  9. matlab吧结果存数组,求助:如何将带有符号变量的运算结果储存到数组中
  10. Hive与RDBMS的区别
  11. Quartz教程五:SimpleTrigger
  12. BUUCTF--相册
  13. Visio2010绘制用例图
  14. 前端,自定义印章效果
  15. OpenG数组讲解之Remove Duplicates from 1D Array.vi
  16. 你必须认识的五名网络女红人
  17. java tiff 压缩_java – 多页Tiff压缩
  18. 入围T00ls 2018风云人物
  19. 如何使用虚拟机运行“小HomeKit”智汀家庭云
  20. python 战棋游戏代码实现(2):六边形地图寻路和显示

热门文章

  1. 工具类 - 生成6位短信验证码
  2. Office 365小型企业版同时安装 Office Project 2016 教程
  3. mysql统计每半小时内的数据(查寻某段时间内的数据)
  4. 什么是网页设计中的滚动设计?如何进行滚动设计?
  5. 02.集线器,网桥,交换机
  6. 港中文旷视提出PanopticFCN:用于全景分割的全卷积网络
  7. 毕业论文图片、公式自动编号和交叉索引教程——真的超好用
  8. 京东商城API 京东商品评论列表
  9. cmd执行调用打开文件
  10. sqlmap中的tamper 脚本分析