【数据结构与算法(Java描述)】队列,Josephus环问题

来源于书籍《数据结构与算法(Java描述)》邓俊辉 著 机械工业出版社

队列

队列的抽象数据类型就是一个容器,其中的对象排成一个序列,我们只能访问和取出排在最前端(Front)的对象,只能在队列的尾部(Rear)插入新对象。正是按照这一规则,才能保证最先被插入的对象首先被删除(FIFO)。

使用数组实现

public interface Queue <T> {
    
    
    int getSize();
    boolean isEmpty();
    //取队首元素,但不删除
    Object front() throws QueueEmptyException;
    void enqueue(T obj) throws QueueFullException;//入队
    T dequeue() throws QueueEmptyException;//出队
    void Traversal();//遍历
}
public class QueueEmptyException extends RuntimeException{
    
    
    public QueueEmptyException(String err){
    
    
        super(err);
    }
}
public class QueueFullException extends RuntimeException{
    
    
    public QueueFullException(String err){
    
    
        super(err);
    }
}
package com.kqgeo.bigdata.study.queue;


/**
 * @Auther: bigboss
 * @Date: 2020/8/7 11:06
 * @Description:
 */
public class QueueByArray<T> implements Queue<T> {
    
    
    public static final int CAPACITY = 1000;
    protected int capacity;
    protected Object[] Q;
    protected int f;//队首元素的位置
    protected int r;//队尾元素的位置

    public QueueByArray(){
    
    
        this(CAPACITY);
    }

    public QueueByArray(int cap){
    
    
        capacity=cap;
        Q=new Object[capacity];
    }


    @Override
    public int getSize() {
    
    
        return (capacity-f+r)%capacity;
    }

    @Override
    public boolean isEmpty() {
    
    
        return (f == r);
    }

    @Override
    public Object front() throws QueueEmptyException {
    
    
        if(isEmpty()){
    
    
            throw new QueueEmptyException("Queue is empty!");
        }
        return Q[f];
    }

    @Override
    public void enqueue(T obj) throws QueueFullException {
    
    
        if(getSize() == capacity-1){
    
    
            throw new QueueFullException("队列满了");
        }
        Q[r]=obj;
        r=(r+1)%capacity;
    }

    @Override
    public T dequeue() throws QueueEmptyException {
    
    
        Object ele;
        if(isEmpty()){
    
    
            throw new QueueEmptyException("Queue is empty!");
        }
        ele=Q[f];
        Q[f]=null;
        f=(f+1)%capacity;
        return (T) ele;
    }

    @Override
    public void Traversal() {
    
    

        for (int i = f; i < r; i++) {
    
    
            System.out.print(Q[i]+" ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
    
    

        Queue<String> queue=new QueueByArray<>();
        queue.enqueue("zhangsan");
        queue.enqueue("lisi");
        queue.enqueue("wangwu");
        System.out.println(queue.getSize());
        queue.Traversal();

    }
}

Josephus 环

孩提时的你是否玩过“烫手山芋”游戏:一群小孩围成一圈,有一个刚出锅的山芋在他们之间传递。其中一个孩子负责数数,每数一次,拿着山芋的孩子就把山芋转交给右边的邻居。一旦数到某个特定的数,拿着山芋的孩子就必须退出,然后重新数数。如此不断,最后剩下的那个孩子就是幸运者。
通常,数数的规则总是从 1 开始,数到 k 时让拿着山芋的孩子出列,然后重新从 1 开始。Josephus问题可以表述为:n 个孩子玩这个游戏,最后的幸运者是谁?
为了解答这个问题,我们可以利用队列结构来表示围成一圈的n个孩子。一开始,假定对应于队列首节点的那个孩子拿着山芋。然后,按照游戏的规则,把“土豆”向后传递到第k个孩子(交替进行k次dequeue()和k次enqueue()操作),并让她出队(dequeue())。如此不断迭代,直到队长(getSize())为 1。

public class Josephus {
    
    

    //利用队列模拟Josephus环
    public static Object josephus(Queue queue,int k){
    
    
        if(queue.isEmpty()) return null;
        while (queue.getSize()>1){
    
    
            queue.Traversal();
            for (int i = 0; i < k; i++) {
    
    
                //将山芋向前传递k次
                queue.enqueue(queue.dequeue());
            }
            Object e=queue.dequeue();//拿着山芋的孩子退出
            System.out.println(e+"退出");
        }

        return queue.dequeue();//返回最后的赢家

    }

    public static Queue buildQueue(Object[] obs){
    
    
        Queue queue=new QueueByArray();
        for (int i = 0; i < obs.length; i++) {
    
    
            queue.enqueue(obs[i]);
        }
        return queue;
    }

    public static void main(String[] args) {
    
    
        String[] kid = {
    
    "Alice", "Bob", "Cindy", "Doug", "Ed",
                "Fred", "Gene", "Hope", "Irene", "Jack",
                "Kim", "Lance", "Mike", "Nancy", "Ollie"};
        System.out.println("最终的幸运者是" + josephus(buildQueue(kid), 5));
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42158942/article/details/107863352