大话数据结构(六)——队列的两种java实现方式

    记得说桟的时候用了羽毛球的例子:羽毛球盒只有一个端口,取出和放入都得从这个口进行,并且放入和取出的原则遵循“后入先出”的原则。而队列与桟的原则相反,桟的原理就好比这个羽毛球盒子是两头开的,放入的时候从一个口放入,而取出的时候从另一端取出,这样就使得先放入的先取出,后放入的后取出。这种先进先出的数据结构就是队列。

    说的官方一点,队列就是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。队列是一种FIFO(先进先出)的线性表,允许插入的一端为队尾,允许删除的一端为队头。队列的实现方式有两种:一种是顺序存储结构,一种是链式存储结构。

    首先来看顺序存储结构以及入队出队操作,如下图:

    入队列:从队尾插入


    出队列:从队头删除

下面是队列的顺序存储结构ArrayQueue

其中队列头为数组头,队列尾为数组尾,队列中包含有获取队列中元素位置、插入、删除、清空队列等操作

ArrayQueue实现:

package ArrayQueue;

import java.util.Arrays;

/**
 * Created by Administrator on 2017/5/27.
 */
public class ArrayQueue<T> {
    private final int DEFAULT_SIZE = 10;//设置默认尺寸
    private int capacity;//保存当前数组长度
    private int addCapacity;//设置当超出原数组长度时增加的长度
    private Object[] elements;//初始化队列数组
    private int size;//保存队列中元素的个数

    //创建默认长度的空队列
    public ArrayQueue(){
        capacity = DEFAULT_SIZE;
        elements = new Object[capacity];
    }

    //创建指定长度的空队列
    public ArrayQueue(int capacity){
        this.capacity = capacity;
        elements = new Object[capacity];
    }

    /**
     * 创建指定长度的空队列,并指定超出数组范围后的增量
     * @param capacity 设置指定长度
     * @param addCapacity 设置增量
     */
    public ArrayQueue(int capacity,int addCapacity){
        this.capacity = capacity;
        this.addCapacity = addCapacity;
        elements = new Object[capacity];
    }

    //获取队列的长度
    public int getSize(){
        return size;
    }

    //判断队列是否为空队列
    public boolean isEmpty(){
        return size == 0;
    }

    //确保数组长度,如果超出就进行拓展
    private void ensureCapacity(int inputCapacity){
        //如果输入的数组长度大于原有数组的长度
        if (inputCapacity > capacity) {
            //若果有设定数组增量
            if (addCapacity > 0)
                while (inputCapacity > capacity)
                    //按照增量扩容,直到大于所需的数组容量
                    capacity += inputCapacity;
                //如果未设定数组增量
            else
                while (inputCapacity > capacity)
                    //将capacity左移,使其为大于所需容量
                    capacity <<= 1;
            //扩容后,将原数组复制到新数组中
            elements = Arrays.copyOf(elements, capacity);
        }
    }

    //入队列:向队尾添加一个元素
    public void add(T element){
        //确保数组长度
        ensureCapacity(size+1);
        //元素进栈
        elements[size++] = element;
    }

    //出队列:移出队头元素
    //同时返回移出的元素
    public T remove(){
        //如果是空队列
        if (isEmpty())
            return null;
        T element = (T) elements[0];
        //释放队列头元素并将长度减一
        elements[0] = null;
        size--;
        //将队列头后的元素整体前移
        for (int i = 1;i<size;i++)
            elements[i-1] = elements[i];
        return element;
    }

    //获取队列头元素
    public T getTop(){
        return (T)elements[0];
    }

    //清空队列
    public void clear(){
        for (int i = 0;i<size;i++)
            elements[i] = null;
        size = 0;
    }

    public String toString(){
        if (isEmpty())
            return "[]";
        else {
            StringBuilder sb = new StringBuilder("[");
            for (int i = 0;i < size;i++)
                sb.append(elements[i].toString()+" ");
            sb.append("]");
            int len = sb.length();
            return sb.delete(len-2,len-1).toString();
        }
    }
}
测试代码:

package ArrayQueue;

/**
 * Created by Administrator on 2017/5/27.
 */
public class ArrayQueueTest {
    public static void main(String[] args) {
        ArrayQueue<String> as = new ArrayQueue<String>();
        System.out.println("原队列中的元素: "+as);
        System.out.println("----------入队列啦----------");
        //入队列
        as.add("haha");
        as.add("hehe");
        as.add("xixi");
        as.add("hiahia");
        as.add("heihei");
        System.out.println("入队列后队列中所含元素: "+as);
        //获取队列头元素
        System.out.println("队列中队列头元素为: "+as.getTop());
        //获取栈中元素个数
        System.out.println("当队列中元素个数为: "+as.getSize());
        //出栈
        System.out.println("----------出队列啦----------");
        as.remove();
        System.out.println("出队列后队列中所含元素: "+as);
        //获取栈顶元素
        System.out.println("队列头元素为: "+as.getTop());
        //获取栈中元素个数
        System.out.println("当前队列中元素个数为: "+as.getSize());
        //清空线队列
        as.clear();
        System.out.println("清空队列");
        System.out.println("清空后队列是否为空: "+as.isEmpty());
    }
}
测试结果:

原队列中的元素: []
----------入队列啦----------
入队列后队列中所含元素: [haha hehe xixi hiahia heihei]
队列中队列头元素为: haha
当队列中元素个数为: 5
----------出队列啦----------
出队列后队列中所含元素: [hehe xixi hiahia hiahia]
队列头元素为: hehe
当前队列中元素个数为: 4
清空队列
清空后队列是否为空: true

Process finished with exit code 0

    

    然后来看链式存储结构以及入队出队操作,如下图:

下面是队列的链式存储结构LinkListQueue

其中队列头为链表头,队列尾为链表尾,队列中包含有获取队列中元素位置、插入、删除、清空队列等操作

LinkListQueue实现:

package LinkListQueue;

/**
 * Created by Administrator on 2017/5/27.
 */
public class LinkListQueue<T> {
    //定义一个内部类Node代表链表的节点
    private class Node{
        private T data;//保存数据
        private Node next;//指向下一个节点的引用

        //无参构造器
        public Node(){}

        //初始化全部属性的构造器
        public Node(T data,Node next){
            this.data = data;
            this.next = next;
        }
    }

    private Node header;//保存头结点
    private Node tail;//保存尾节点
    private int size;//保存已含有的结点数

    //创建空链表
    public LinkListQueue(){}

    //返回链表长度
    public int getSize(){
        return size;
    }

    //获取队列指定位置的结点
    public Node getNodeByIndex(int index){
        if (index < 0 || index > size)
            throw new IndexOutOfBoundsException("获取位置超过了链表长度范围");
        Node current = header;//从链表表头开始遍历
        for (int i = 0;i<size && current != null;i++,current = current.next)
            if (i == index)
                return current;
        return null;
    }

    //获取队列处指定索引处的元素
    public T getElement(int index){
        return this.getNodeByIndex(index).data;
    }

    //按值查找所在队列的位置
    public int getIndex(T element){
        Node current = header;

        for (int i = 0;i < size && current != null;i++,current = current.next)
            if (current.data.equals(element))
                return i;
        return -1;
    }

    //获取队列头元素
    public T getTop(){
        return (T)header.data;
    }

    //在队列中添加元素
    public void add(T element){
        //如果队列为空
        if (header == null){
            header = new Node(element, null);
            tail = header;//空链表中头尾结点指向同一个
        }
        else {
            Node newNode = new Node(element,null);//创建新结点
            tail.next = newNode;//尾结点的next指向新结点
            tail = newNode;//将新结点作为尾结点
        }
        size++;
    }

    //取出队列中的元素
    public T remove(){
        Node del = null;
        //删除的是头结点
        del = header;
        header = header.next;
        del.next = null;
        size--;
        return del.data;
    }

    //判断链表是否为空
    public boolean isEmpty(){
        return size == 0;
    }

    //清空线性表
    public void clear(){
        //将头结点和尾结点设为空
        header = null;
        tail = null;
        size = 0;
    }

    public String toString(){
        if (isEmpty())
            return "[]";
        else {
            StringBuilder sb = new StringBuilder("[");
            for (Node current = header;current != null;current = current.next)
                sb.append(current.data+"->").toString();
            int len = sb.length();
            return sb.delete(len-2,len).append("]").toString();
        }
    }
}
测试代码:

package LinkListQueue;

/**
 * Created by Administrator on 2017/5/27.
 */
public class LinkListQueueTest {
    public static void main(String[] args) {
        LinkListQueue<String> ls = new LinkListQueue<String>();
        System.out.println("原队列中的元素: "+ls);
        System.out.println("----------入队列啦----------");
        //入队列
        ls.add("haha");
        ls.add("hehe");
        ls.add("xixi");
        ls.add("hiahia");
        ls.add("heihei");
        System.out.println("入队列后队列中所含元素: "+ls);
        //获取队列头元素
        System.out.println("队列中队列头元素为: "+ls.getTop());
        //获取栈中元素个数
        System.out.println("当队列中元素个数为: "+ls.getSize());
        //出栈
        System.out.println("----------出队列啦----------");
        ls.remove();
        System.out.println("出队列后队列中所含元素: "+ls);
        //获取栈顶元素
        System.out.println("队列头元素为: "+ls.getTop());
        //获取栈中元素个数
        System.out.println("当前队列中元素个数为: "+ls.getSize());
        //清空线队列
        ls.clear();
        System.out.println("清空队列");
        System.out.println("清空后队列是否为空: "+ls.isEmpty());
    }
}
测试结果:

原队列中的元素: []
----------入队列啦----------
入队列后队列中所含元素: [haha->hehe->xixi->hiahia->heihei]
队列中队列头元素为: haha
当队列中元素个数为: 5
----------出队列啦----------
出队列后队列中所含元素: [hehe->xixi->hiahia->heihei]
队列头元素为: hehe
当前队列中元素个数为: 4
清空队列
清空后队列是否为空: true

Process finished with exit code 0

参考:《大话数据结构》
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值