数据结构-- 队列 循环与顺序

  java实现,控制台输入输出!

 

  1 package cn.lm.deque;
  2 /**
  3  * 链式队列
  4  */
  5 import java.io.Serializable;
  6 import java.util.Arrays;
  7 import java.util.Scanner;
  8 
  9 public class LoopQueue<T> implements Serializable{  
 10       /** 
 11        * @Fields serialVersionUID : TODO 
 12        */  
 13       private static final long serialVersionUID = -3670496550272478781L;  
 14       
 15       private int DEFAULT_SIZE = 3;  
 16       
 17       final int capacity ;//保存数组的长度  
 18       
 19       private Object[] elementData;//定义一个数组用于保存循环队列的元素  
 20       
 21       private int front = 0;//队头  
 22       
 23       private int rear = 0;//队尾  
 24       
 25       //以默认数组长度创建空循环队列  
 26       public LoopQueue() {  
 27         capacity = DEFAULT_SIZE;  
 28         elementData = new Object[capacity];  
 29       }  
 30       
 31       //以一个初始化元素来创建循环队列  
 32       public LoopQueue(T element) {  
 33         this();  
 34         elementData[0] = element;  
 35         rear++;  
 36       }  
 37       
 38       /** 
 39        * 以指定长度的数组来创建循环队列 
 40        * @param element 指定循环队列中第一个元素 
 41        * @param initSize 指定循环队列底层数组的长度 
 42        */  
 43       public LoopQueue(T element, int initSize) {  
 44         this.capacity = initSize;  
 45         elementData = new Object[capacity];  
 46         elementData[0] = element;  
 47         rear++;  
 48       }  
 49       
 50       //获取循环队列的大小  
 51       public int size() {  
 52         if (isEmpty()) {  
 53           return 0;  
 54         }  
 55         return rear > front ? rear - front : capacity - (front - rear);  
 56       }  
 57       
 58       //插入队列  
 59       public boolean add(T element) {  
 60         if (rear == front && elementData[front] != null) {  
 61          return false;
 62         }  
 63         elementData[rear++] = element;  
 64         //如果rear已经到头,那就转头  
 65         rear = rear == capacity ? 0 : rear;
 66         return true;
 67       }  
 68       
 69       //移除队列  
 70       public T remove() {  
 71         if (isEmpty()) {  
 72           T t= null;
 73             return t;
 74         }  
 75         //保留队列的rear端的元素的值  
 76         T oldValue = (T) elementData[front];  
 77         //释放队列的rear端的元素  
 78         elementData[front++] = null;  
 79         //如果front已经到头,那就转头  
 80         front = front == capacity ? 0 : front;  
 81         return oldValue;  
 82       }  
 83       
 84       //返回队列顶元素,但不删除队列顶元素  
 85       public T element() {  
 86         if (isEmpty()) {  
 87           throw new IndexOutOfBoundsException("空队列异常");  
 88         }  
 89         return (T) elementData[front];  
 90       }  
 91       
 92       //判断循环队列是否为空队列  
 93       public boolean isEmpty() {  
 94         //rear==front且rear处的元素为null  
 95         return rear == front && elementData[rear] == null;  
 96       }  
 97       
 98       //清空循环队列  
 99       public void clear() {  
100         //将底层数组所有元素赋为null  
101         Arrays.fill(elementData, null);  
102         front = 0;  
103         rear = 0;  
104       }  
105       
106       public String toString() {  
107         if (isEmpty()) {  
108           return "[]";  
109         } else {  
110           //如果front < rear,有效元素就是front到rear之间的元素  
111           if (front < rear) {  
112             StringBuilder sb = new StringBuilder("[");  
113             for (int i = front; i < rear; i++) {  
114               sb.append(elementData[i].toString() + ", ");  
115             }  
116             int len = sb.length();  
117             return sb.delete(len - 2, len).append("]").toString();  
118           }  
119           //如果front >= rear,有效元素为front->capacity之间、0->front之间的  
120           else {  
121             StringBuilder sb = new StringBuilder("[");  
122             for (int i = front; i < capacity; i++) {  
123               sb.append(elementData[i].toString() + ", ");  
124             }  
125             for (int i = 0; i < rear; i++) {  
126               sb.append(elementData[i].toString() + ", ");  
127             }  
128             int len = sb.length();  
129             return sb.delete(len - 2, len).append("]").toString();  
130           }  
131         }  
132       }  
133       
134       public void face() {
135           System.out.println("***************************************************");
136           System.out.println("1.入队");
137           System.out.println("2.出队");
138           System.out.println("3.退出");
139           System.out.println("***************************************************");
140       }
141       public static void main(String[] args) {  
142         Scanner scan = new Scanner(System.in);
143         
144         int cho = 0;
145         LoopQueue<String> queue = new LoopQueue<String>();  
146         while (true) {
147             queue.face();
148             System.out.println("请输入序号");
149             cho = scan.nextInt();
150             if(cho==1) {
151                 System.out.println("请输入入队的值:");
152                 String queuearr = scan.next();
153                 boolean l = queue.add(queuearr);
154                 if(!l) {
155                     System.out.println("添加失败!,队列已满");
156                 }
157                 System.out.println(queue);
158             }
159             if(cho==2) {
160                 Object c = queue.remove();
161                 if(c==null) {
162                     System.out.println("空队列!");
163                 }
164                 else {
165                     System.out.println("删除一个元素后的队列:" + queue);
166                 }
167             }
168             //再次添加一个元素,此时队列又满  
169             if(cho ==3) {
170                 System.out.println("程序退出!");
171                 System.exit(0);
172             }
173         }
174         
175         
176       }  
177 }

顺序队列

建立顺序队列结构必须为其静态分配或动态申请一片连续的存储空间,并设置两个指针进行管理。一个是队头指针front,它指向队头元素;另一个是队尾指针rear,它指向下一个入队元素的存储位置,如图所示
每次在队尾插入一个元素是,rear增1;每次在队头删除一个元素时,front增1。随着插入和删除操作的进行,队列元素的个数不断变化,队列所占的存储空间也在为队列结构所分配的连续空间中移动。当front=rear时,队列中没有任何元素,称为空队列。当rear增加到指向分配的连续空间之外时,队列无法再插入新元素,但这时往往还有大量可用空间未被占用,这些空间是已经出队的队列元素曾经占用过得存储单元。
顺序队列中的溢出现象:
(1) "下溢"现象:当队列为空时,做出队运算产生的溢出现象。“下溢”是正常现象,常用作程序控制转移的条件。
(2)"真上溢"现象:当队列满时,做进栈运算产生空间溢出的现象。“真上溢”是一种出错状态,应设法避免。
(3)"假上溢"现象:由于入队和出队操作中,头尾指针只增加不减小,致使被删元素的空间永远无法重新利用。当队列中实际的元素个数远远小于向量空间的规模时,也可能由于尾指针已超越向量空间的上界而不能做入队操作。该现象称为"假上溢"现象。

 

 

循环队列

在实际使用队列时,为了使队列空间能重复使用,往往对队列的使用方法稍加改进:无论插入或删除,一旦rear指针增1或front指针增1 时超出了所分配的队列空间,就让它指向这片连续空间的起始位置。自己真从MaxSize-1增1变到0,可用取余运算rear%MaxSize和front%MaxSize来实现。这实际上是把队列空间想象成一个环形空间,环形空间中的存储单元循环使用,用这种方法管理的队列也就称为循环队列。除了一些简单应用之外,真正实用的队列是循环队列。[2] 
在循环队列中,当队列为空时,有front=rear,而当所有队列空间全占满时,也有front=rear。为了区别这两种情况,规定循环队列最多只能有MaxSize-1个队列元素,当循环队列中只剩下一个空存储单元时,队列就已经满了。因此,队列判空的条件时front=rear,而队列判满的条件时front=(rear+1)%MaxSize。队空和队满的情况如图:

 

 

循环队列改为顺序队列  限制数组长度值即可

相关代码不懂的自行百度研究!

 

posted @ 2017-10-31 11:31  刘可乐  阅读(1080)  评论(0编辑  收藏  举报