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 }

 

posted @ 2016-04-07 17:08  回看欧洲  阅读(708)  评论(0编辑  收藏  举报