数据结构基础笔记(5)队列

队列:先进先出的线性表,如何实现增删查
1.队列是什么
队列是一种特殊的线性表,与线性表不同之处在于对数据的增和删操作上
队列的特点是先进先出:
先进:队列的数据新增操作只能在末端进行,不允许在队列的中间某个结点后新增数据
先出:队列的数据删除操作只能在始端进行,不允许在队列的中间某个结点后删除数据
队列存在两种存储方式,顺序队列和链式队列:
顺序队列:依赖数组来实现,其中的数据在内存中也是顺序存储
链式队列:依赖链表来实现,其中的数据依赖每个结点的指针互联,在内存中并不是顺序存储链式队列,实际上就是只能尾进头出的线性表的单链表
2.队列对于数据的增删查处理
单循环指针也会产生新的问题,当队列为空时,front指针和rear指针相等。队列是满的的时候,同样有可能出现front和rear指针相等的情况。那么怎么判断队列是空的还是满的呢?通常设置一个flag来区别队列是空的还是满的。
3.链式队列的数据操作
我们再看一下链式队列的数据操作。链式队列就是一个单链表,同时增加了 front 指针和 rear 指针。链式队列和单链表一样,通常会增加一个头结点,并另 front 指针指向头结点。头结点不存储数据,只是用来辅助标识。
链式队列进行新增数据操作时,将拥有数值 X 的新结点 s 赋值给原队尾结点的后继,即 rear.next。然后把当前的 s 设置为队尾结点,指针 rear 指向 s。
当链式队列进行删除数据操作时,实际删除的是头结点的后继结点。这是因为头结点仅仅用来标识队列,并不存储数据。因此,出队列的操作,就需要找到头结点的后继,这就是要删除的结点。接着,让头结点指向要删除结点的后继。
如果这个链表除去头结点外只剩一个元素,那么删除仅剩的一个元素后,rear 指针就变成野指针了。这时候,需要让 rear 指针指向头结点。也许你前面会对头结点存在的意义产生怀疑,似乎没有它也不影响增删的操作。那么为何队列还特被强调要有头结点呢?这主要是为了防止删除最后一个有效数据结点后, front 指针和 rear 指针变成野指针,导致队列没有意义了。有了头结点后,哪怕队列为空,头结点依然存在,能让 front 指针和 rear 指针依然有意义。对于队列的查找操作,不管是顺序还是链式,队列都没有额外的改变。跟线性表一样,它也需要遍历整个队列来完成基于某些条件的数值查找。因此时间复杂度也是 O(n)。
4.案例
约瑟夫环是一个数学的应用问题,具体为,已知 n 个人(以编号 1,2,3…n 分别表示)围坐在一张圆桌周围。从编号为 k 的人开始报数,数到 m 的那个人出列;他的下一个人又从 1 开始报数,数到 m 的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
这个问题,用队列的方法实现是个不错的选择。它的结果就是出列的顺序,恰好满足队列对处理顺序敏感的前提。因此,求解方式也是基于队列的先进先出原则。解法如下:
先把所有人都放入循环队列中。注意这个循环队列的长度要大于或者等于 n。
从第一个人开始依次出队列,出队列一次则计数变量 i 自增。如果 i 比 m 小,则还需要再入队列。
直到i等于 m 的人出队列时,就不用再让这个人进队列了。而是放入一个用来记录出队列顺序的数组中。
直到数完 n 个人为止。当队列为空时,则表示队列中的 n 个人都出队列了,这时结束队列循环,输出数组内记录的元素。

public static void main(String[] args) {

    ring(10, 5);

}

public static void ring(int n, int m) {

    LinkedList<Integer> q = new LinkedList<Integer>();

    for (int i = 1; i <= n; i++) {

        q.add(i);

    }

    int k = 2;

    int element = 0;

    int i = 0;

    for (; i<k; i++) {

        element = q.poll();

        q.add(element);

    }

    i = 1;

    while (q.size() > 0) {

        element = q.poll();

        if (i < m) {

            q.add(element);

            i++;

        } else {

            i = 1;

            System.out.println(element);

        }

    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值