数据结构— —队列(顺序表实现)

简介: 数据结构— —队列(顺序表实现)

队列及其企业级应用

队列的故事导入


Jack 在一个著名软件外包公司上班,公司每年要接很多的外包项目给各个开发团队开发,现在刚 刚接到一个项目,要实现银行排队叫号系统, 基本需求是:


取号:

1. 银行用户进入银行大厅办理业务

2. 用户从自动排号机上取号

3. 自动取号机生成号码以及当前等待人数信息给用户


叫号:

1. 当银行业务员(1 位或多位)处理完业务以后,会指示叫号系统呼叫下一位(按排队次序)正在等待的用 户,用户达到窗口以后,银行业务员会将用户的号码从叫号系统中删除。


49983cdeb4ae4883a171b8b652a18f73.png


如果你是 Jack ,你该如何设计这个功能?

队列的原理精讲

队列是一种受限的线性表,(Queue)它是一种运算受限的线性表,先进先出(FIFO First In First Out)


image.png

  • 队列是一种受限的线性结构
  • 它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。

生活中队列场景随处可见: 比如在电影院, 商场, 或者厕所排队。。。。。。

03777de1c97147b0a24389ca50f2e830.png

队列的算法实现

顺序存储

采用数组来保存队列的元素,设立一个队首指针 front ,一个队尾指针 rear,分别指向队首和队尾元素。则 rear-front 即为存储的元素个数!


91ff824594a546dea80b6901218b5e41.png

#define MaxSize 5 //队列的最大容量 
typedef int DataType; //队列中元素类型
typedef struct Queue
{
    DataType queue[MaxSize];
    int front; //队头指针 
    int rear; //队尾指针
}SeqQueue;

队列初始化

//队列初始化,将队列初始化为空队列
void InitQueue(SeqQueue *SQ)
{ 
    if(!SQ) return ;
    SQ->front = SQ->rear = 0; //把对头和队尾指针同时置0
}


队列为空

//判断队列为空
int IsEmpty(SeqQueue *SQ)
{ 
    if(!SQ) return 0;
    if (SQ->front == SQ->rear)
    { return 1;
    } 
    return 0;
}


队列为满

//判断队列是否为满
int IsFull(SeqQueue *SQ)
{ 
    if(!SQ) return 0;
    if (SQ->rear == MaxSize)
    { return 1;
    }
    return 0;
}


入队:将新元素插入 rear 所指的位置,然后 rear 加 1。

//入队,将元素data插入到队列SQ中
int EnterQueue( SeqQueue *SQ,DataType data)
{ 
    if(!SQ) return 0;
    if(IsFull(SQ))
    {
        cout<<"无法插入元素 "<<data<<", 队列已满!"<<endl; return 0;
    }
    SQ->queue[SQ->rear] = data; 
    //在队尾插入元素data 
    SQ->rear++; //队尾指针后移一位
    return 1;
}

打印队列中的元素

//打印队列中的各元素
void PrintQueue(SeqQueue* SQ)
{
    if(!SQ) return ;
    int i = SQ->front; 
    while(i<SQ->rear)
    { 
        cout<<setw(4)<<SQ->queue[i]; 
        i++;
    }
    cout<<endl;
}

1.删除 front 所指的元素, 后面所有元素前移 1 并返回被删除元素

//出队,将队列中队头的元素data出队,后面的元素向前移动
int DeleteQueue(SeqQueue* SQ, DataType *data)
{
    if(!SQ || IsEmpty(SQ))
    { 
        cout<<"队列为空!"<<endl;
        return 0;
    } 
    if(!data) return 0;
    *data = SQ->queue[SQ->front];
    for(int i=SQ->front+1; i<SQ->rear; i++)
    {//移动后面的元素 
        SQ->queue[i-1]=SQ->queue[i];
    }
    SQ->rear--;//队尾指针前移一位 return 1;
}



3a80ab617cbc4a0d8ab05c5c1f665943.png


2.删除 front 所指的元素,然后加 1 并返回被删元素

//出队,将队列中队头的元素data出队,出队后队头指针front后移一位
int DeleteQueue2(SeqQueue* SQ,DataType* data)
{ 
    if (!SQ || IsEmpty(SQ))
    { 
        cout<<"队列为空!"<<endl;
        return 0; 
    }
    if(SQ->front>=MaxSize)
    {
        cout<<"队列已到尽头!"<<endl;
        return 0;
    }
    *data = SQ->queue[SQ->front]; //出队元素值 
    SQ->front = (SQ->front)+1;  //队首指针后移一位 
    return 1;
}


bf33a23d472643ccb4342f0f7011662b.png

#include <stdio.h>
#include <assert.h>
#include <Windows.h>
#include <iostream> 
#include <iomanip> 
using namespace std;
#define MaxSize 5 //队列的最大容量 
typedef int DataType; //队列中元素类型
typedef struct Queue
{
    DataType queue[MaxSize];
    int front; //队头指针 
    int rear; //队尾指针
}SeqQueue;

取队首元素:返回 front 指向的元素值

//获取队首元素
int GetHead(SeqQueue* SQ,DataType* data)
{ 
    if (!SQ || IsEmpty(SQ))
    {
         cout<<"队列为空!"<<endl;
    }
    return *data = SQ->queue[SQ->front]; 
}

清空队列

//清空队列
void ClearQueue(SeqQueue* SQ)
{
    SQ->front = SQ->rear = 0;
}


完整代码实现

//队列初始化,将队列初始化为空队列
void InitQueue(SeqQueue *SQ)
{ 
    if(!SQ) return ;
    SQ->front = SQ->rear = 0; //把对头和队尾指针同时置0
}
//判断队列为空
int IsEmpty(SeqQueue *SQ)
{ 
    if(!SQ) return 0;
    if (SQ->front == SQ->rear)
    { 
        return 1;
    } 
    return 0;
}
//判断队列是否为满
int IsFull(SeqQueue *SQ)
{ 
    if(!SQ) return 0;
    if (SQ->rear == MaxSize)
    { 
        return 1;
    } 
    return 0;
}
//入队,将元素data插入到队列SQ中
int EnterQueue( SeqQueue *SQ,DataType data)
{     
    if(!SQ) return 0;
    if(IsFull(SQ))
    {
        cout<<"无法插入元素 "<<data<<", 队列已满!"<<endl; 
        return 0;
    }
    SQ->queue[SQ->rear] = data; //在队尾插入元素data 
    SQ->rear++; //队尾指针后移一位
    return 1;
}
//出队,将队列中队头的元素data出队,后面的元素向前移动
int DeleteQueue(SeqQueue* SQ, DataType *data)
{
    if(!SQ || IsEmpty(SQ))
    {
        cout<<"队列为空!"<<endl;
        return 0;
    } 
    if(!data) return 0;
    *data = SQ->queue[SQ->front];
    for(int i=SQ->front+1; i<SQ->rear; i++)
    {//移动后面的元素 
        SQ->queue[i-1]=SQ->queue[i];
    }
    SQ->rear--;//队尾指针前移一位 
    return 1;
}
//出队,将队列中队头的元素data出队,出队后队头指针front后移一位
int DeleteQueue2(SeqQueue* SQ,DataType* data)
{     
    if (!SQ || IsEmpty(SQ))
    { 
        cout<<"队列为空!"<<endl;
        return 0; 
    }
    if(SQ->front>=MaxSize)
    {
        cout<<"队列已到尽头!"<<endl;
        return 0;
    }
    *data = SQ->queue[SQ->front]; //出队元素值 
    SQ->front = (SQ->front)+1;  //队首指针后移一位
    return 1;
}
//打印队列中的各元素
void PrintQueue(SeqQueue* SQ)
{ 
    if(!SQ) return ;
    int i = SQ->front; 
    while(i<SQ->rear)
    {
         cout<<setw(4)<<SQ->queue[i]; 
         i++;
    }
    cout<<endl;
}
//获取队首元素,不出队
int GetHead(SeqQueue* SQ,DataType* data)
{ 
    if (!SQ || IsEmpty(SQ))
    { 
        cout<<"队列为空!"<<endl;
    }
    return *data = SQ->queue[SQ->front];
}
//清空队列
void ClearQueue(SeqQueue* SQ)
{ 
    if(!SQ) return ;
    SQ->front = SQ->rear = 0;
}
//获取队列中元素的个数
int getLength(SeqQueue* SQ)
{ 
    if(!SQ) return 0;
    return SQ->rear-SQ->front;
}
int main()
{
    SeqQueue *SQ = new SeqQueue;
    DataType data = -1;
    //初始化队列
    InitQueue(SQ);
    //入队
    for(int i=0; i<7; i++)
    {
         EnterQueue(SQ, i);
    }
    //打印队列中的元素
    printf("队列中的元素(总共%d 个):", getLength(SQ));
    PrintQueue(SQ);
    cout<<endl;
    //出队
    //for(int i=0; i<10; i++)
     { 
        if(DeleteQueue2(SQ, &data))
        { 
            cout<<"出队的元素是:"<<data<<endl;
        }
        else 
        { 
            cout<<"出队失败!"<<endl;
        }
    //}
    //打印队列中的元素 
      printf("出队一个元素后,队列中剩下的元素:");
      PrintQueue(SQ); cout<<endl;
      system("pause"); 
      return 0;
}


下一小节将介绍队列的链式存储

相关文章
|
2月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
265 9
|
5天前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
116 75
|
5天前
|
存储 C++ 索引
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
【数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】初始化队列、销毁队列、判断队列是否为空、进队列、出队列等。本关任务:编写一个程序实现环形队列的基本运算。(6)出队列序列:yzopq2*(5)依次进队列元素:opq2*(6)出队列序列:bcdef。(2)依次进队列元素:abc。(5)依次进队列元素:def。(2)依次进队列元素:xyz。开始你的任务吧,祝你成功!(4)出队一个元素a。(4)出队一个元素x。
27 13
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
|
5天前
|
存储 C语言 C++
【C++数据结构——栈与队列】链栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现链栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储整数,最大
31 9
|
5天前
|
C++
【C++数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】
【数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】(1)遇到左括号:进栈Push()(2)遇到右括号:若栈顶元素为左括号,则出栈Pop();否则返回false。(3)当遍历表达式结束,且栈为空时,则返回true,否则返回false。本关任务:编写一个程序利用栈判断左、右圆括号是否配对。为了完成本关任务,你需要掌握:栈对括号的处理。(1)遇到左括号:进栈Push()开始你的任务吧,祝你成功!测试输入:(()))
25 7
|
5天前
|
机器学习/深度学习 存储 C++
【C++数据结构——线性表】顺序表的基本运算(头歌实践教学平台习题)【合集】
本文档介绍了线性表的基本运算任务,涵盖顺序表和链表的初始化、销毁、判定是否为空、求长度、输出、查找元素、插入和删除元素等内容。通过C++代码示例详细展示了每一步骤的具体实现方法,并提供了测试说明和通关代码。 主要内容包括: - **任务描述**:实现顺序表的基本运算。 - **相关知识**:介绍线性表的基本概念及操作,如初始化、销毁、判定是否为空表等。 - **具体操作**:详述顺序表和链表的初始化、求长度、输出、查找、插入和删除元素的方法,并附有代码示例。 - **测试说明**:提供测试输入和预期输出,确保代码正确性。 - **通关代码**:给出完整的C++代码实现,帮助完成任务。 文档
20 5
|
19天前
|
数据库
数据结构中二叉树,哈希表,顺序表,链表的比较补充
二叉搜索树,哈希表,顺序表,链表的特点的比较
数据结构中二叉树,哈希表,顺序表,链表的比较补充
|
2月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
80 5
|
2月前
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习之顺序表【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找等具体详解步骤以及举例说明
|
2月前
|
存储 C语言
【数据结构】顺序表(c语言实现)(附源码)
本文介绍了线性表和顺序表的基本概念及其实现。线性表是一种有限序列,常见的线性表有顺序表、链表、栈、队列等。顺序表是一种基于连续内存地址存储数据的数据结构,其底层逻辑是数组。文章详细讲解了静态顺序表和动态顺序表的区别,并重点介绍了动态顺序表的实现,包括初始化、销毁、打印、增删查改等操作。最后,文章总结了顺序表的时间复杂度和局限性,并预告了后续关于链表的内容。
95 3