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。队空和队满的情况如图:
循环队列改为顺序队列 限制数组长度值即可
相关代码不懂的自行百度研究!