数据结构 队列

队列

​ 解密QQ号,A向B询问QQ号,A并没有直接给B,A给了B一串加密过的数字,同时告诉了B解密规则。规则是:先将第1个元素删除,然后将第2个元素放到最后,再将第3个元素删除,然后将第4个元素放到最后…,直到剩下最后一个数,将最后一个数也删除。

​ OK,现在开始模拟一下规则,给出数字6 3 1 7 5 8 9 2 4这样9个数字,解密后应该是6 1 5 9 4 7 2 8 3。

​ 开始模拟过程,刚开始是6 3 1 7 5 8 9 2 4,然后删除6,把3放到最后,1 7 5 8 9 2 4 3,然后删除1,7放到最后,5 8 9 2 4 3 7,依次模拟为,9 2 4 3 7 8,4 3 7 8 2, 7 8 2 3,2 3 8, 8 3,然后删除8,3放到末尾,最后删除3.因此被删除的顺序为6 1 5 9 4 7 2 8 3。

​ 现在弄清楚了规则,试一下编程,首先需要一个数组来存储这一串数字,并初始化这个数组,

int a[101] = {0, 6, 3, 1, 7, 5, 8, 9, 2, 4};

​ 在这里先引入两个整型变量head和tail。tail来记录队列的队尾的下一个位置,head用来记录队列的队首。这时就会问为什么不直接tail来记录队尾,却要记录队尾的下一个位置?这是因为队列中只剩下一个元素的时候,队首和队尾就重合了,重合会带来一些麻烦。所以,我们这里规定队首和队尾重合时,队列为空。

​ 现在有9个数全部放入队列之后head=1,tail=10,此时head和tail之间的数就是目前队列里面的有效数。如果要删除一个数的话,tail++就能办到,这样仍然可以保持tail和head之间的数为有效数。这样做虽然浪费了一个空间,但是却节省了大量的时间,这样就非常划算。新增加一个数也很简单,把需要的数放到队尾即a[tail]之后再tail++就OK了。

#include <stdio.h>

int main()
{
    int q[102]; = {0, 6, 3, 1, 7, 5, 8, 9, 2, 4}, head, tail;
    head = 1;
    tail = 10;
    while (head < tail) {
        // 打印队首元素,并让队首出队
        printf("%d ", q[head]);
        head++;
        
        // 先将新队首放到队尾
        q[tail] = q[head];
        tail++;
        // 再让队首出队
        head++;
    }
    return 0;
}

​ 队列是一种特殊的线性结构,它只允许在队列的首部head进行删除操作,这称为出队,而在尾部进行插入操作,这称为入队。当队列中没有元素时(head == tail),称为空队列。

​ 队列是将来学习广度优先算法以及队列优化的Bellmand-Ford最短路算法的核心数据结构。所以我们现在将队列的三个基本元素封装为一个结构体,如下:

struct queue
{
    int data[100];
    int head;
    int tail;
};

​ 上面定义了一个结构体类型,我们通常将其放在main函数的外面,请注意结构体的定义末尾有一个;号。struct是结构体的关键字,queue是我们为这个结构体起的名字。这个结构体有3个成员分别是:数组data,head,tail。这样我们就可以把三个数放在一起作为一个整体来对待。

​ 下面这段代码用结构体来操作:

#include <stdio.h>

struct queue
{
    int data[100];
    int head;
    int tail;
};

int main()
{
    struct queue q;
    int i;
    
    // 初始化队列
    q.head = 1;
    q.tail = 1;
    
    for (i = 1; i <= 9; i++) {
        scanf("%d", &q.data[q.tail]);
        q.tail++;
    }
    
    while (q.head < q.tail) {
        printf("%d ", q.data[q.head]);
        q.head++;
        
        q.data[q.tail] = q.data[head];
        q.tail++;
        
        q.head++;
    }
    
    return 0;
}

虽然上面的写法冗余了一点,但是可以加强对队列的理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值