数据结构02--队列

来源:互联网 发布:html与java关系 编辑:程序博客网 时间:2024/05/16 18:52

队列是一种基于先进先出(FIFO)策略的集合类型,只允许在其一端(队尾)进行插入操作,在另一端(对头)进行删除操作。

抽象数据类型

public class Queue<Item> implements Iterable<Item>
队列API 功能 void enQueue(Item item) 添加元素(入队) Item deQueue() 删除元素(出队) boolean isEmpty() 判断队列是否为空 int size() 队列的大小

队列的创建

数组实现

其存储结构如下图:
这里写图片描述
数组实现队列的过程:
这里写图片描述
假设开始时数组长度为5,如图,当f入队时,此时数组末尾元素已被占用,如果继续向后就会产生下标越界,但此时数组未满,将从头开始入队。这种逻辑上首尾相连的顺序存储结构叫循环队列。当数组满(h入队)时,将数组的长度加倍。
代码如下:

import java.util.Iterator;/** * 能动态调整数组大小的循环队列 * @author Gain */public class CycleArrayQueue<Item> implements Iterable<Item> {        private int N;//记录队列大小        //last表示尾元素后一个的索引        private int first,last;//first表示头元素的索引        private Item[] a;        public CycleArrayQueue() {            a = (Item[])new Object[1];        }        public int size() {return N;}        public boolean isEmpty(){return N==0;}        //调整数组大小        public void resizingArray(int num) {            Item[] temp = (Item[])new Object[num];            for(int i=0;i<N;i++) {                temp[i] = a[(first+i)%a.length];            }            a = temp;            first = 0;//数组调整后first,last位置            last =  N;        }        public void enQueue(Item item){            //当队列满时,数组长度加倍            if(N==a.length) resizingArray(2*N);            a[last] = item;            last = (last+1)%a.length;//【关键】            N++;        }        public Item deQueue() {            if(isEmpty()) return null;            Item item = a[first];            first = (first+1)%a.length;//【关键】            N--;            //当队列长度小于数组1/4时,数组长度减半            if(N>0 && N<a.length/4) resizingArray(2*N);            return item;        }        //实现迭代器        public Iterator<Item> iterator() {            return new ResizingArrayQueueIterator();        }        private class ResizingArrayQueueIterator implements Iterator<Item> {            private int num=N;            private int current = first;            public boolean hasNext() {                return num>0;            }            public Item next() {                Item item = a[current++];                num--;                return item;            }        }}

链表实现

存储结构如下图:
这里写图片描述
代码如下:

import java.util.Iterator;/** * 链表实现的队列 * @author Gain */public class LinkedQueue<Item> implements Iterable<Item> {    private Node first,last;//头结点,尾结点    private int N=0;//队列大小    //定义结点    private class Node {        Item item;        Node next;    }    public int size() {return N;}    public boolean isEmpty(){return N==0;}    //入队    public void enQueue(Item item) {        Node oldLast = last;        last = new Node();        last.item = item;        if(isEmpty()) {            first = last;//【要点】        }else {            oldLast.next = last;        }        N++;    }    //出队    public Item deQueue() {        Item item = first.item;        first = first.next;        N--;        if(isEmpty()) last = null;//【要点】        return item;    }    //实现迭代器    public Iterator<Item> iterator() {        return new LinkedQueueIterator();    }    private class LinkedQueueIterator implements Iterator<Item>{        private Node current = first;        public boolean hasNext() {            return current != null;        }        public Item next(){            Item item = current.item;            current = current.next;            return item;        }    }}

测试

代码如下:

    //测试    public class Test {        public static void main(String[] args) {            int[] a = {1,2,4,6,new Integer(10),5};            CycleArrayQueue<Integer> queue1 = new CycleArrayQueue<Integer>();            LinkedQueue<Integer> queue2 = new LinkedQueue<Integer>();            for(int i=0;i<a.length;i++) {                queue1.enQueue(a[i]);                queue2.enQueue(a[i]);                System.out.print(a[i]+" ");            }            System.out.println("入队");            //迭代            for (Integer s : queue1) {                System.out.print(s+" ");            }            System.out.println("出队");            for (Integer s : queue2) {                System.out.print(s+" ");            }        }    }

运行结果:
这里写图片描述

应用

Josephus问题:

问题描述:N个身陷绝境的人一致同意通过以下方式减少生存人数。他们围成一圈(位置记为0到N-1)并从第一个人开始报数,报到M的人被杀死,直到最后一人留下来。找到不会被杀死的位置。

思路: 需要一个辅助队列,将0到N-1全部依次入队,然后依次出队,再将未被杀死的人(未报到M)入队,构成循环。打印出人们被杀死的顺序,最后一个即为不会被杀死的位置。

import java.util.Scanner;import queue.LinkedQueue;/** * Josephus问题 * @author Gain * */public class Josephus {    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        LinkedQueue<Integer> q = new LinkedQueue<Integer>();        System.out.println("输入人数N:");        int N = sc.nextInt();        System.out.println("输入报数M:");        int M = sc.nextInt();        sc.close();        for(int i=0;i<N;i++) {            q.enQueue(i);        }        while(!q.isEmpty()) {            for(int i=1;i<M;i++) {                q.enQueue(q.deQueue());//【核心代码】            }            System.out.print(q.deQueue() + " ");        }    }}

运行结果:
这里写图片描述

0 0
原创粉丝点击