服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - 在编程语言中怎样定义队列及其使用(C++)

在编程语言中怎样定义队列及其使用(C++)

2021-07-24 16:14156279375 C/C++

这篇文章主要介绍了在编程语言中怎样定义队列,本文主要根据c++来介绍,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

队列在编程语言中是如何定义的呢?小编与大家分享自己的经验。

在编程语言中怎样定义队列及其使用(C++)

队列的定义

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

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

步骤

队列是用来存储暂未处理但需要按一定顺序处理的元素的一种数据结构。

在编程语言中怎样定义队列及其使用(C++)

队列是一种先进先出(First In First Out,FIFO)的线性表,特点是先进队的元素先出队。

在编程语言中怎样定义队列及其使用(C++)

队列只允许在表的一端进行插入,而在另一端删除元素。

在编程语言中怎样定义队列及其使用(C++)

队尾是队列中允许插入的一端;队首是队列中允许删除的一端。

在编程语言中怎样定义队列及其使用(C++)

一般用顺序表q[m]存储队列中的元素,m是队列能存储元素的最大数量。

在编程语言中怎样定义队列及其使用(C++)

front队首指针指向队首元素存储的位置;rear队尾指针指向队尾元素的下一个位置。

在编程语言中怎样定义队列及其使用(C++)

顺序队列及其操作

队列的顺序存储结构

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

在编程语言中怎样定义队列及其使用(C++)

队列初始条件:队头指针=队尾指针=0
队列满条件:队尾指针=m(设队列当前容量为m)
队列空条件:队头指针=队尾指针

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

?
1
2
3
4
5
6
7
#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]闲置不用.

顺序队列上的操作

(1)创建队列

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

在QueueControl.h写出方法声明

?
1
2
3
4
/*
 创建队列
 */
SEQUEUE initQueue();

在QueueControl.c中实现此方法

?
1
2
3
4
5
6
7
8
9
10
#include "QueueControl.h"
/*
 创建队列
 */
SEQUEUE initQueue(){
  SEQUEUE Q;
  //1.初始化队列,队头指针=队尾指针=0
  Q.front=Q.rear=0;
  return Q;
}

(2)插入

在QueueControl.h写出方法声明

?
1
2
3
4
/*
 插入
 */
SEQUEUE inQueue(SEQUEUE Q,DT x);

在QueueControl.c中实现此方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#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写出方法声明

?
1
2
3
4
5
6
7
8
9
/*
 删除
 */
SEQUEUE outQueue(SEQUEUE Q);
 
/*
 打印队列元素
 */
void printQueue(SEQUEUE Q);

在QueueControl.c中实现此方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#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[]) {})调用此方法,并且进行判断

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#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

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

循环队列及其操作

循环队列的存储结构

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

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

在编程语言中怎样定义队列及其使用(C++)

在编程语言中怎样定义队列及其使用(C++)

循环队列初始条件:队头指针=队尾指针=0
循环队列队满条件:MOD(队尾指针+1,m)=队头指针
循环队列空条件:队头指针=队尾指针
队头指针推进计算:队头指针=MOD(队头指针+1,m)
队尾指针推进计算:队尾指针=MOD(队尾指针+1,m)

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

?
1
2
3
4
5
6
7
#define CDT char
#define CM 5
typedef struct {
 
  CDT data[CM];
  int front,rear;
}SECYCLEQUEUE;

循环队列上的操作

(1)创建循环队列

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

在QueueCycyleControl.h写出方法声明

?
1
2
3
4
5
6
#include "QueueCycleCs.c"
 
/*
 创建循环队列
 */
SECYCLEQUEUE initCycleQueue();

在QueueCycyleControl.c中实现此方法

?
1
2
3
4
5
6
7
8
9
10
#include "QueueCycleControl.h"
/*
 创建循环队列
 */
SECYCLEQUEUE initCycleQueue(){
  SECYCLEQUEUE Q;
  //队头指针=队尾指针=0;
  Q.front=Q.rear=0;
  return Q;
}

(2)插入

在QueueCycyleControl.h写出方法声明

?
1
2
3
4
5
6
#include "QueueCycleCs.c"
 
/*
 循环队列插入
 */
SECYCLEQUEUE inCycleQueue(SECYCLEQUEUE Q,char x);

在QueueCycyleControl.c中实现此方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#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写出方法声明

?
1
2
3
4
5
6
7
8
9
#include "QueueCycleCs.c"
/*
 循环队列删除
 */
SECYCLEQUEUE outCycleQueue(SECYCLEQUEUE Q);
/*
 打印循环队列
 */
void printCycleQueue(SECYCLEQUEUE Q);

在QueueCycyleControl.c中实现此方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#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[]) {})调用此方法,并且进行判断

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#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

链队列及其操作

队列的链存储结构

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

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

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

在编程语言中怎样定义队列及其使用(C++)

在QueueLinkCs.c中定义了结构

?
1
2
3
4
5
6
7
8
9
10
11
#define LDT char
//结点类型
typedef struct llnode{
  LDT data;
  struct llnode *next;
}LINKNODE;
 
//链队列结构
typedef struct{
  LINKNODE *front,*rear;
}LINKQUEUE;

链队列上的操作

(1)创建链队列

在QueueLinkControl.h写出方法声明

?
1
2
3
4
5
6
7
8
#include <stdio.h>
#include "QueueLinkCs.c"
 
 
/*
 创建链队
 */
LINKQUEUE * initLinkQueue(LINKQUEUE *LQ);

在QueueLinkControl.c中实现此方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#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写出方法声明

?
1
2
3
4
/*
 链队插入:队尾
 */
LINKQUEUE * inLinkQueue(LINKQUEUE *LQ,LDT x);

在QueueLinkControl.c中实现此方法

(3)删除

在QueueLinkControl.h写出方法声明

?
1
2
3
4
5
6
7
8
9
/*
 链队删除:队头
 */
LINKQUEUE *outLinkQueue(LINKQUEUE *LQ);
 
/*
 打印链表结点
 */
void printLinkQueue(LINKQUEUE *LQ);

在QueueLinkControl.c中实现此方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#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,为了不改变原来链队Q
  LINKQUEUE *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[]) {})调用此方法,并且进行判断

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://jingyan.baidu.com/article/6d704a136524a628db51caf5.html

延伸 · 阅读

精彩推荐
  • C/C++关于C语言中E-R图的详解

    关于C语言中E-R图的详解

    今天小编就为大家分享一篇关于关于C语言中E-R图的详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看...

    Struggler095962021-07-12
  • C/C++c/c++实现获取域名的IP地址

    c/c++实现获取域名的IP地址

    本文给大家汇总介绍了使用c/c++实现获取域名的IP地址的几种方法以及这些方法的核心函数gethostbyname的详细用法,非常的实用,有需要的小伙伴可以参考下...

    C++教程网10262021-03-16
  • C/C++C语言main函数的三种形式实例详解

    C语言main函数的三种形式实例详解

    这篇文章主要介绍了 C语言main函数的三种形式实例详解的相关资料,需要的朋友可以参考下...

    ieearth6912021-05-16
  • C/C++使用C++制作简单的web服务器(续)

    使用C++制作简单的web服务器(续)

    本文承接上文《使用C++制作简单的web服务器》,把web服务器做的功能稍微强大些,主要增加的功能是从文件中读取网页并返回给客户端,而不是把网页代码...

    C++教程网5492021-02-22
  • C/C++深入C++拷贝构造函数的总结详解

    深入C++拷贝构造函数的总结详解

    本篇文章是对C++中拷贝构造函数进行了总结与介绍。需要的朋友参考下...

    C++教程网5182020-11-30
  • C/C++OpenCV实现拼接图像的简单方法

    OpenCV实现拼接图像的简单方法

    这篇文章主要为大家详细介绍了OpenCV实现拼接图像的简单方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    iteye_183805102021-07-29
  • C/C++C语言实现双人五子棋游戏

    C语言实现双人五子棋游戏

    这篇文章主要为大家详细介绍了C语言实现双人五子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    两片空白7312021-11-12
  • C/C++c/c++内存分配大小实例讲解

    c/c++内存分配大小实例讲解

    在本篇文章里小编给大家整理了一篇关于c/c++内存分配大小实例讲解内容,有需要的朋友们可以跟着学习参考下。...

    jihite5172022-02-22