• 5、队列的顺序存储结构:循环队列、两种方法


    队列的ADT:

     1 package ren.laughing.datastructure.base;
     2 
     3 import ren.laughing.datastructure.exception.QueueEmptyException;
     4 
     5 /**
     6  * 队列Queue的ADT:先进先出
     7  * 在队列中把插入数据元素的一端称为 队尾(rear), 删除数据元素
     8  * 的一端称为 队首(front)。向队尾插入元素称为 进队或入队,
     9  * 新元素入队后成为新的队尾元素;从队列中删除元素称为 离队或出队,
    10  * 元素出队后,其后续元素成为新的队首元素。
    11  * @author Laughing_Lz
    12  * @time 2016年4月7日
    13  */
    14 public interface Queue {
    15     //返回队列的大小
    16     public int getSize();
    17     //判断队列是否为空
    18     public boolean isEmpty();
    19     //数据元素 e 入队
    20     public void enqueue(Object e);
    21     //队首元素出队
    22     public Object dequeue() throws QueueEmptyException;
    23     //取队首元素
    24     public Object peek() throws QueueEmptyException;
    25     }

    循环队列的顺序存储实现,采用少一存储空间的方法:

     1 package ren.laughing.datastructure.baseImpl;
     2 
     3 import ren.laughing.datastructure.base.Queue;
     4 import ren.laughing.datastructure.exception.QueueEmptyException;
     5 /**
     6  * 队列Queue的顺序存储,此处使用循环队列,逆时针,方法一
     7  * ★循环队列:难点在于如何判断队空和队满
     8  * 方法一:★少使用一个存储空间,即:当队尾指针的下一指针指向队首指针时,就停止入队。
     9  * 判决:队空:rear=front,队满:(rear+1)%capacity = float
    10  * 方法二:★增设一个标志size,以size?=MAX区别队满队空
    11  * 判决:队空:size = 0,队满:size = capacity
    12  * @author Laughing_Lz
    13  * @time 2016年4月7日
    14  */
    15 public class QueueArray implements Queue{
    16     private static final int CAP=7;//队列默认容量大小
    17     private Object[] elements;
    18     private int capacity;//数组的实际大小 elements.length
    19     private int front;
    20     private int rear;
    21     
    22     public QueueArray() {
    23         this(CAP);
    24     }
    25     public QueueArray(int cap) {
    26         this.elements = new Object[capacity];
    27         this.capacity = cap+1;//这里数组实际大小capacity比队列容量cap大1
    28         this.front = 0;
    29         this.rear = 0;
    30     }
    31     //获取队列的容量
    32     @Override
    33     public int getSize() {
    34         return (rear-front+capacity)%capacity;//返回队列的实际容量,小于等于capacity-1
    35     }
    36     //判断是否队空
    37     @Override
    38     public boolean isEmpty() {
    39         if(rear == front){
    40             return true;
    41         }else{
    42             return false;
    43         }
    44     }
    45     //入队:相当于在insertAfter队尾
    46     @Override
    47     public void enqueue(Object e) {
    48 //        if(getSize()==capacity-1){//同下,判断队列容量是否已满
    49         if((rear+1)%capacity == front){//判断是否队满
    50             expandSpace();//扩充队列的容量
    51         }
    52         elements[rear] = e;
    53         rear = (rear+1)%capacity;//rear有可能从capacity-1移动到0
    54     }
    55     //出队:相当于在remove队首
    56     @Override
    57     public Object dequeue() throws QueueEmptyException {
    58         if(rear == front){//判断是否队空
    59             throw new QueueEmptyException("错误:队列已空");
    60         }
    61         Object obj = elements[front];
    62         elements[front] = null;//置空
    63         front = (front+1)%capacity;//front有可能从capacity-1移动到0
    64         return obj;
    65     }
    66     //获取队首数据元素
    67     @Override
    68     public Object peek() throws QueueEmptyException {
    69         if(rear == front){//判断是否队空
    70             throw new QueueEmptyException("错误:队列已空");
    71         }
    72         return elements[front];
    73     }
    74     /**
    75      * ★扩充数组长度
    76      */
    77     private void expandSpace() {
    78         Object[] a = new Object[elements.length * 2];
    79         int i = front;
    80         int j = 0;
    81         while(i!=rear){//将从 front 开始到 rear 前一个存储单元的元素复制到新数组
    82             a[j++] = elements[i];
    83             i = (i+1)%capacity;
    84         }
    85         elements = a;
    86         capacity = elements.length;
    87         front  = 0;
    88         rear = j;//重新设置新的队首队尾指针
    89     }
    90 }

    循环队列的顺序存储实现,采用加标志size的方法:

     1 package ren.laughing.datastructure.baseImpl;
     2 
     3 import ren.laughing.datastructure.base.Queue;
     4 import ren.laughing.datastructure.exception.QueueEmptyException;
     5 /**
     6  * 队列Queue的顺序存储,此处使用循环队列,逆时针,方法二
     7  * ★循环队列:难点在于如何判断队空和队满
     8  * 方法一:★少使用一个存储空间,即:当队尾指针的下一指针指向队首指针时,就停止入队。
     9  * 判决:队空:rear=front,队满:(rear+1)%capacity = float
    10  * 方法二:★增设一个标志size,以size?=MAX区别队满队空
    11  * 判决:队空:size = 0,队满:size = capacity
    12  * @author Laughing_Lz
    13  * @time 2016年4月7日
    14  */
    15 public class QueueArray2 implements Queue{
    16     private static final int CAP=8;//队列默认容量大小
    17     private Object[] elements;
    18     private int capacity;//数组的实际大小 elements.length
    19     private int size;//队列容量(空/满判断标志)
    20     private int front;
    21     private int rear;
    22     
    23     public QueueArray2() {
    24         this(CAP);
    25     }
    26     
    27     public QueueArray2(int cap) {
    28         this.elements = new Object[capacity];
    29         this.capacity = cap;//此处cap = capacity
    30         this.size = 0;//队列初始为空
    31         this.front = 0;
    32         this.rear = 0;
    33     }
    34     //获取队列的容量
    35     @Override
    36     public int getSize() {
    37         if(size == capacity){
    38             return capacity;
    39         }else{
    40             return (rear-front+capacity)%capacity;
    41         }
    42     }
    43     //判断是否队空
    44     @Override
    45     public boolean isEmpty() {
    46         if(rear == front&&size !=capacity){
    47             return true;
    48         }else{
    49             return false;
    50         }
    51     }
    52     //入队:相当于在insertAfter队尾
    53     @Override
    54     public void enqueue(Object e) {
    55         if(size  == capacity){//判断是否队满
    56             expandSpace();//扩充队列的容量
    57         }
    58         elements[rear] = e;
    59         rear = (rear+1)%capacity;//rear有可能从capacity-1移动到0
    60         size++;
    61     }
    62     //出队:相当于在remove队首
    63     @Override
    64     public Object dequeue() throws QueueEmptyException {
    65         if(rear == front&&size != capacity){//判断是否队空 (此时size为0)
    66             throw new QueueEmptyException("错误:队列已空");
    67         }
    68         Object obj = elements[front];
    69         elements[front] = null;//置空
    70         front = (front+1)%capacity;//front有可能从capacity-1移动到0
    71         size--;
    72         return obj;
    73     }
    74     //获取队首数据元素
    75     @Override
    76     public Object peek() throws QueueEmptyException {
    77         if(rear == front&&size != capacity){//判断是否队空 (此时size为0)
    78             throw new QueueEmptyException("错误:队列已空");
    79         }
    80         return elements[front];
    81     }
    82     /**
    83      * ★扩充数组长度
    84      */
    85     private void expandSpace() {
    86         Object[] a = new Object[elements.length * 2];
    87         int i = front;
    88         int j = 0;
    89         do{//将从 front 开始到 rear 前一个存储单元的元素复制到新数组
    90             a[j++] = elements[i];
    91             i = (i+1)%capacity;
    92         }while(i!=rear);//
    93         elements = a;
    94         capacity = elements.length;
    95         front  = 0;
    96         rear = j;//重新设置新的队首队尾指针
    97     }
    98 }
    —————————————————————————————————————行走在人猿的并行线——Laughing_Lz
  • 相关阅读:
    用OpenGL简单编写的一个最简单贪吃蛇游戏
    Python lambda map filter reduce
    Hadoop Python MapReduce
    Python faker生成数据
    Pandas数据清洗
    PySpark与jupyer notebook
    虚拟机与宿主机网络共享
    集合覆盖问题与贪婪算法
    最快路径与狄克斯特拉
    最短路径问题与广度优先搜索
  • 原文地址:https://www.cnblogs.com/Laughing-Lz/p/5364396.html
Copyright © 2020-2023  润新知