【数据结构】-循环队列1(顺序存储)

缺乏、安全感 2023-02-28 12:45 14阅读 0赞

顺序存储-循环队列1

  • 1.头文件及类型定义
  • 2.循环队列类型定义
  • 3.函数声明
  • 4.基本操作
    • 4.1 初始化队列
    • 4.2 判空
    • 4.3 入队
    • 4.4 出队
    • 4.5 获取队头元素
    • 4.6 main函数
  • 5.小结

1.头文件及类型定义

  1. #include<stdio.h>
  2. #define MaxSize 10 //定义队列中元素的最大个数
  3. #define ElemType int

2.循环队列类型定义

  1. typedef struct {
  2. //顺序队列类型定义
  3. ElemType data[MaxSize]; //静态数组存放队列元素
  4. int front, rear; //队头指针和队尾指针
  5. }SqQueue;

3.函数声明

  1. /*函数声明*/
  2. void InitQueue(SqQueue& Q); //1.初始化队列
  3. bool QueueEmpty(SqQueue Q); //2.判空
  4. bool EnQueue(SqQueue& Q, ElemType x); //3.入队
  5. bool ExQueue(SqQueue& Q, ElemType& x); //4.出队
  6. bool GetHead(SqQueue Q, ElemType& x); //5.获取队头元素

4.基本操作

4.1 初始化队列

  1. //1.初始化队列
  2. void InitQueue(SqQueue& Q) {
  3. /*初始时队头队尾指针都指向0*/
  4. Q.front = 0; //队头指针指向队头元素
  5. Q.rear = 0; //队尾指针指向队尾元素的后一个位置,即下一个要插入的位置
  6. }

4.2 判空

  1. //2.判空
  2. bool QueueEmpty(SqQueue Q) {
  3. return Q.front == Q.rear;
  4. }

4.3 入队

  1. //3.入队操作:在队尾进行插入操作
  2. bool EnQueue(SqQueue& Q, ElemType x) {
  3. if ((Q.rear + 1) % MaxSize == Q.front) //队满,报错
  4. return false;
  5. Q.data[Q.rear] = x; //新元素插入队尾
  6. Q.rear = (Q.rear + 1) % MaxSize; //队尾指针加1取模,用模运算j将存储空间在逻辑上变成了“环状”,这也是叫循环队列的原因
  7. return true;
  8. }

4.4 出队

  1. //4.出队操作:在队头进行删除操作
  2. bool ExQueue(SqQueue& Q, ElemType& x) {
  3. if (Q.front == Q.rear) //队空,报错
  4. return false;
  5. x = Q.data[Q.front]; //返回出队元素的值
  6. Q.front = (Q.front + 1) % MaxSize; //队头指针+1取模,指向下一个元素
  7. return true;
  8. }

4.5 获取队头元素

  1. //5.获得队头元素的值,用x返回
  2. bool GetHead(SqQueue Q, ElemType& x) {
  3. if (Q.front == Q.rear) //队空,报错
  4. return false;
  5. x = Q.data[Q.front];
  6. return true;
  7. }

4.6 main函数

  1. int main() {
  2. SqQueue Q; //声明一个循环队列(分配内存空间)
  3. /*1、初始化队列*/
  4. InitQueue(Q);
  5. /*2、判空*/
  6. if (QueueEmpty(Q))
  7. printf("当前队列为空!\n");
  8. else
  9. printf("当前队列非空!\n");
  10. /*3、入队操作*/
  11. ElemType e1;
  12. printf("请输入入队元素的值:");
  13. scanf("%d", &e1);
  14. if (EnQueue(Q, e1))
  15. printf("新元素入队成功!\n");
  16. else
  17. printf("队列已满,新元素入队失败!\n");
  18. /*4、读取队头元素*/
  19. ElemType e2 = -1;
  20. if (GetHead(Q, e2))
  21. printf("读取队头元素成功,当前队头元素值为:%d\n", e2);
  22. else
  23. printf("队列已空,读取队头元素失败!\n");
  24. /*5、出队操作*/
  25. ElemType e3 = -1;
  26. if (ExQueue(Q, e3))
  27. printf("队头元素出队成功,出队元素值为:%d\n", e3);
  28. else
  29. printf("队列已空,队头元素出队失败!\n");
  30. /*6、读取队头元素*/
  31. ElemType e4 = -1;
  32. if (GetHead(Q, e4))
  33. printf("读取队头元素成功,当前队头元素值为:%d\n", e4);
  34. else
  35. printf("队列已空,读取队头元素失败!\n");
  36. return 0;
  37. }

5.小结

  1. 队列的定义及操作特性
    (1)和栈类似,队列的本质仍然为线性表,也是一种操作受限的线性表,但是它只允许在表得到一端进行插入,而在表的另一端进行删除。同线性表类似,它也有两种存储方式:顺序存储和链式存储,将在接下来的文章中继续讨论。
    (2)队列的操作特性为先进先出(FIFO,First In First Out)
    (关于栈和队列的区别,网上有一种比喻生动且形象:吃多了吐就是栈,而吃多了拉就是队列。hhhhhhhh)
  2. 队列的基本操作
    队列和栈一样,因为操作受限,故与栈的操作基本相同,如下:
    (1)初始化
    (2)判空
    (3)入队
    (4)出队
    (5)获取队头元素
  3. 本文队列中元素个数为:(Q.rear-Q.front+MaxSize)% MaxSize
  4. 说明
    (1)因为队列允许在一端进行插入(即入队),在另一端进行删除(即出队),所以存在入队和出队快慢的问题。在队列的顺序存储中,由于分配的空间是有限的,在队列满了以后,如果队头有人出队,则这个空间就又有了空缺,可在原来队头的位置继续入队。这样,将顺序队列从逻辑上视为一个环,称为循环队列,具体由取余运算来实现。
    (2)在循环队列的代码的具体实现上有如下情况
    在设置队尾指针时,有两种情况:
    a 可以指向队尾元素的后一个元素 (在本文中使用此种方式)
    b 可以指向队尾元素。
    在区分队空队满时,也有三种处理方式:
    牺牲一个单元来区分队空队满(在本文中使用此种方式)
    引入辅助变量size来判断队满队空
    引入辅助变量tag来判断队满队空
    因此,总共有2*3=6种代码实现(本文采用a+①的方式),在接下来的文章中会再实现两种,其余三种方式不再阐述。

发表评论

表情:
评论列表 (有 0 条评论,14人围观)

还没有评论,来说两句吧...

相关阅读

    相关 顺序存储

    Queue基本概念 队列是一种特殊的线性表  队列仅在线性表的两端进行操作  队头(Front):取出数据元素的一端  队尾(Rear):插入数据元素的一端