队列及顺序列

一、特性

1、概念

队列是只允许在两端进行插入和删除操作的线性表,在队尾插入,在队头删除,插入的一端被称为“队尾”,删除的一端被称为“队头”。 队列包括顺序队列(循环队列)、链式队列。

结构:先进先出FIFO

操作:创建、入列、出列、判空和满、清空

注意:为了避免假溢出问题,即队列前面还有空闲,但是队尾已经出现越界,所以在实际使用队列时,为了使队列空间能重复使用,往往对队列的使用方法稍加改进,需要引入循环队列

循环队列是把顺序队列首尾相连,把存储队列元素的表从逻辑上看成一个环,成为循环队列。

  1. 循环队列

逻辑结构:线性结构

存储结构:顺序存储

操作:创建、入列、出列、判空和判满、清空

循环队列操作

队列结构体:

代码实现:

创建空队列:

入列:

循环队列判满需要浪费一个空间来实现

出列:

循环队列结构体

#include<stdio.h>
#include<stdlib.h>
#define N 6
typedef int datatype;
typedef struct sequeue
{
    datatype data[N];//循环队列存放数据的数组。
    int front;//队头,出数据的一端。
    int rear;//队尾,存数据的一端。
}sequeue_t,* sequeue_list_t;

1)创建一个空队列

//创建一个空队列
sequeue_t CreatSequeue()
{
    sequeue_list_t p=(sequeue_list_t)malloc(sizeof(sequeue_t));
    if(NULL==p)
    {
        perror("空间开辟失败\n");
        return NULL;
    }
    //初始化
    p->front=0;//使用的时候是数组的下标,表示队头,用来出队得那一端
    p->rear=0;//使用的时候是数组的下标, 表示队尾,用来入队的那一端
    return p;
}

2)判空

//判空
int IsFellSequeue(sequeue_list_t p)
{
    return p->front==(p->rear+1)%N;
}

3)判满

//判断队列是否为满
int isFullSequeue(sequeue_t *p)
{
    //思想上,舍去数组上的一个存储位置,用于判断队列是否为满
    //先判断rear的下一个位置是否等于front
    return p->front == (p->rear + 1) % N;
}

4)入列

//入列
int InSequeue(sequeue_list_t p,datatype data)
{
    if(IsFellSequeue(p)) //1.容错判断,入列前判断是否为满
    {
        printf("队列已满\n");
        return -1;
    }
    p->data[p->rear]=data;//2.将数据如列,存到rear表示的那个空间。
    p->rear=(p->rear+1)%N;//3.将rear移动到下一个位置,这里不能单纯的+1了,而是通过取于让下标循环起来。
    return 0;
}

5)出列

//出列
int OutSequeue(sequeue_list_t p)
{
    if(IsVoidSequeue(p))
    {
        printf("顺序列为空\n");
    }
    datatype out=p->data[p->front];
    p->front=(p->front+1)%N;
    printf("%d\n",out);
    printf("头的位置:%d,尾的位置:%d\n",p->front,p->rear);
    return out;
}

6)遍历输出

//遍历输出 
void Show(sequeue_list_t p)
{
    if(IsVoidSequeue(p))
    {
        printf("顺序列为空\n");
    }
    int i=p->front;
    while(i!=p->rear)
    {
        printf("%d ",p->data[i]);
        i=(i+1)%N;
    }
    puts(" ");
}

7)求顺序队列长度

//求顺序队列长度
int LengthSequeue(sequeue_list_t p)
{
    if(IsVoidSequeue(p))
    {
        printf("顺序列为空\n");
    }
    if(p->front<=p->rear)
    {
        printf("%d\n",(p->rear)-(p->front));
        return (p->rear)-(p->front);
    }
    else
    {   
        printf("%d\n",(p->rear)-(p->front)+N);
        return p->rear-p->front+N;
    }
}

8)清空

//清空
int ClearSequeue(sequeue_list_t p)
{
    if(IsVoidSequeue(p))
    {
        printf("顺序列为空\n");
    }
    while(p->data[p->front]!=0)
    {
        OutSequeue(p);
    }
    // p->front=p->rear;
    return 0;
}

综合代码

#include<stdio.h>
#include<stdlib.h>
#define N 6
typedef int datatype;
typedef struct sequeue
{
    datatype data[N];//循环队列存放数据的数组。
    int front;//队头,出数据的一端。
    int rear;//队尾,存数据的一端。
}sequeue_t,* sequeue_list_t;
//创建一个空队列
sequeue_list_t CreatSequeue()
{
    sequeue_list_t p=(sequeue_list_t)malloc(sizeof(sequeue_t));
    if(NULL==p)
    {
        perror("空间开辟失败\n");
        return NULL;
    }
    //初始化
    p->front=0;
    p->rear=0;
    return p;
}
//判满
int IsFellSequeue(sequeue_list_t p)
{
    return p->front==(p->rear+1)%N;
}
//入列
int InSequeue(sequeue_list_t p,datatype data)
{
    if(IsFellSequeue(p)) //1.容错判断,入列前判断是否为满
    {
        printf("队列已满\n");
        return -1;
    }
    p->data[p->rear]=data;//2.将数据如列,存到rear表示的那个空间。
    p->rear=(p->rear+1)%N;//3.将rear移动到下一个位置,这里不能单纯的+1了,而是通过取于让下标循环起来。
    return 0;
}
//判空
int IsVoidSequeue(sequeue_list_t p)
{
    return p->front==p->rear;
}
//出列
int OutSequeue(sequeue_list_t p)
{
    if(IsVoidSequeue(p))
    {
        printf("顺序列为空\n");
    }
    datatype out=p->data[p->front];
    p->front=(p->front+1)%N;
    printf("%d\n",out);
    printf("头的位置:%d,尾的位置:%d\n",p->front,p->rear);
    return out;
}
//遍历输出 
void Show(sequeue_list_t p)
{
    if(IsVoidSequeue(p))
    {
        printf("顺序列为空\n");
    }
    int i=p->front;
    while(i!=p->rear)
    {
        printf("%d ",p->data[i]);
        i=(i+1)%N;
    }
    puts(" ");
}
//求顺序队列长度
int LengthSequeue(sequeue_list_t p)
{
    if(IsVoidSequeue(p))
    {
        printf("顺序列为空\n");
    }
    if(p->front<=p->rear)
    {
        printf("%d\n",(p->rear)-(p->front));
        return (p->rear)-(p->front);
    }
    else
    {   
        printf("%d\n",(p->rear)-(p->front)+N);
        return p->rear-p->front+N;
    }
}
//清空
int ClearSequeue(sequeue_list_t p)
{
    if(IsVoidSequeue(p))
    {
        printf("顺序列为空\n");
    }
    while(p->data[p->front]!=0)
    {
        OutSequeue(p);
    }
    // p->front=p->rear;
    return 0;
}
int main(int argc, char const *argv[])
{
    sequeue_list_t p=CreatSequeue();
    int num;
    int push[32];
    char in;
    while(1)
    {
        printf("请输入命令=");
        scanf("%c",&in);//回收一个垃圾字符
        getchar();
        switch(in)
        {
            case 'A':
                printf("请输入要插入的元素个数:");
                scanf("%d",&num);
                getchar();
                printf("请输入要插入的元素内容:");
                for(int i=0;i<num;i++)
                {
                    scanf("%d",&push[i]);
                    getchar();
                }
                for(int i=0;i<num;i++)
                {
                    InSequeue(p,push[i]);
                }break;
            case 'a':
                printf("请输入要插入的元素内容:");
                scanf("%d",&num);
                getchar();
                InSequeue(p,num);break;
            case 'b':
                Show(p);break;
            case 'c'://清空栈
                ClearSequeue(p);break;
            case 'd':
                LengthSequeue(p);break;
            case 'e':
                //出栈
                OutSequeue(p);break;
            // case 'f':
            //     ShowForlinkstack(p);break;
            // case 'q':
            // break;break;
        }
    }
    return 0;
}

循环队列,如果数组的元素个数为N,那么队列中最多能够存储的数据数的多少?N-1

为什么呢?

答:rear 后面 队尾,在插入的时候,插入之前需要先判断 rear+1,也就是他的下一个为位置是否 等于 front 来判断队列是否为满,会造成浪费一个存储位置。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

满山的猴子我的腚最红

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值