队列

【定义】

队列和栈有异曲同工之妙,明白栈以后,对理解队列会很快,队列属于先进先出,尾部插入,前面删除,俗称队尾和对头,前删后插。


【顺序存储队列】
【难点解析】

1.假溢出现象

顺序存储结构难点在于出列,出列后数组有位置时的入列情况,引入front指针指向队头元素,rear指针指向队尾元素的下一个位置,空队列时front = rear,出队列时front往后移,入队列时rear往后移,但是会出现一个问题,本身存储队列的是一个数组,后面满了,但是前面还有空位,就导致一种“假溢出”现象,为了解决这个问题,把空间充分利用上,采取循环队列,首尾相接,把rear移动到前面空余空间去添加新成员。

2.满队与空队判断条件

假溢出导致满队和空队一样rear = front, 为了区分空队列和满队列,设置标志变量flag,flag =0 为空,1为满,还有一种办法就是留下一个空余单元,假如数组的最大尺寸为max,则满队条件为(rear+1)%max ==front

3.队列长度

当rear大于front时,长度=rear-front,
当rear小于front时,长度=rear-0+max-front,
通用的计算队列长度公式就是(rear - front +max)%max。

4.结构代码

typedef int my_data;
typedef struct my_queue
{
    my_data data[MAX];
    int front;
    int rear;
}my_queue;

【测试代码】

#include<stdio.h>
#include<stdlib.h>
#define MAX 10
typedef int my_data;
typedef struct my_queue
{
    my_data data[MAX];
    int front;
    int rear;
}my_queue;

//初始化一个空队列
int init_queue(my_queue *Q)
{
    Q->front = 0;
    Q->rear = 0;
    return 0;
}
//入队
int enqueue(my_queue *Q, my_data e)
{
    //判断队满?
    if((Q->rear+1)%MAX == Q->front)
        return 1;

    Q->data[Q->rear] = e;
    Q->rear = (Q->rear +1)%MAX;//移一位

    return 0;
}
//出队
int dequeue(my_queue *Q, my_data *e)
{
    //先判断是否为空队
    if(Q->rear == Q->front)
        return 1;

    *e = Q->data[Q->front];
    Q->front = (Q->front+1)%MAX;//移一位

    return 0;
}
//队列长度
int queue_length(my_queue *Q)
{
    return (Q->rear-Q->front+MAX)%MAX;
}

void test(my_queue *Q)
{
    int s[MAX];
    printf("请输入入队成员\n");
    for(int i= 0; i<MAX-1;i++)
    {
        scanf("%d",&s[i]);
        enqueue(Q,s[i]);
    }
    int length =queue_length(Q);
    printf("队列长度%d\n",length);


    my_data *e=(my_data *)malloc(sizeof(my_data));
    dequeue(Q,e);
    printf("谁出去了%d\n",*e);
    dequeue(Q,e);
    printf("谁出去了%d\n",*e);
}
int main()
{
    my_queue *queue = (my_queue *)malloc(sizeof(my_queue));
    init_queue(queue);
    test(queue);
    int length =queue_length(queue);
    printf("队列长度%d\n",length);
}

【输出】
这里写图片描述
这里需要注意的是移动front和rear,怎么向后移一位。


【链队列】
就是一个带头结点的单链表,队头指针指向链队列的头结点,队尾指针指向终端节点,空队列时,front,rear都指向头结点。


【测试代码】

#include<stdio.h>
#include<stdlib.h>

typedef int my_data;
//结点结构
typedef struct QNode
{
    my_data data;
    struct QNode *next;
}QNode, *Queue_ptr;
//队列的链表结构
typedef struct 
{
    Queue_ptr front, rear; //队头、队尾指针
}LinkQueue;

int enqueue(LinkQueue *Q, my_data e)
{
    Queue_ptr pnew = (Queue_ptr)malloc(sizeof(QNode));
    if(!pnew)
    {
        printf("over flow");
        return 1;
    }

    pnew->data =e;
    pnew->next = NULL;
    Q->rear->next = pnew;
    Q->rear = pnew;

    return 0;
}

int dequeue(LinkQueue *Q, my_data *e)
{
    //判断是否为空队
    if(Q->front == Q->rear)
    {
        printf("null");
        return 1;
    }

    Queue_ptr p;
    p = Q->front->next;//将队头调出来单独操作
    *e = p->data;
    Q->front->next = p->next;//令队头指向第二个结点

    if(Q->rear == p)//如果队头就是队尾,删除了后就没有了,应将rear指向头节点
        Q->rear = Q->front;

    free(p);
    return 0;

}
void test(LinkQueue *Q)
{
    int s[3];
    printf("input:\n");
    for(int i = 0 ;i<3;i++)
    {
        scanf("%d",&s[i]);
        enqueue(Q,s[i]);
    }
    my_data *e = (my_data*)malloc(sizeof(my_data));
    dequeue(Q, e);
    printf("谁出来了%d\n",*e);
}
int main()
{
    LinkQueue *Q=(LinkQueue *)malloc(sizeof(LinkQueue));
    Queue_ptr first =(Queue_ptr)malloc(sizeof(QNode));
    first->next = NULL;
    Q->front= Q->rear = first;
    test(Q);
}

【输出】
这里写图片描述
这里还是要注意一下头结点和头指针的问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值