数据结构之简单队列的实现
来源:互联网 发布:linux ant 安装 编辑:程序博客网 时间:2024/06/15 05:27
数据结构中有一种存储数据的形式,我们把它叫做队列(Queue).主要探讨
一.队列的特点以及表现形式
二.写一个环形队列
三.编写过程中遇到的坑及设计模式
一.队列的特点以及表现形式
1.首先,队列存储数据的方式和栈(stack是有区别的)。栈对于数据的管理是先入后出的(FILO),而队列
对于数据的管理则是先入先出的(FIFO).
2.队列分为普通队列和环形队列
1)普通队列
这样子的队列管理数据的方式有两种,当head的数据被删除时,要么后面的位置往前移动变成头元素,要么队列管理者将head后一位的元素当做head来处理,但是这么做都是有问题的。
如果是head数据被删除后,队列管理者把head+1当做头索引的话,那么此时那个head索引处的位置就会被废弃掉,对应到计算机中就是内存被浪费掉了
如果是head数据被删除后,队列自动全部往前补一位的话, 那么内存是不会被浪费掉,但是所有的位置都要进行前移,浪费了时间。
因此上述两者处理数据的方式都有缺陷,因此,就产生了环形队列。
2)环形队列
可以完美的解决上述两个问题,即当head被删除时,head索引就像前移动一位,但此时head的位置没有不能用,就被空下来,可以重新插入。
二.队列的实现
首先要明确实现一个队列需要什么方法,以及每个方法的注意点
1.需要的方法
1)初始化队列
2)清空队列
3)销毁队列
4)插入元素
5)删除元素
6)判空
7)判满
8)迭代
9)队列长度
据此可以得到代码如下:
IQueueOp.java
/** * 队列行为的接口,主要负责进行下面的事情 * @author szxgg * 0.初始化队列----由队列自身来实现,也可以它来实现 * 1.插入一个元素 * 2.删除一个元素 * 3.销毁队列 * 4.清空队列 * 5.判空 * 6.判满 * 7.队列长度 * 8.循环遍历队列 * */public interface IQueueOp<T> {/** * 初始化队列 * @param capacity 容量值,有几个元素值 */public void initQueue(int capacity);/** * 插入一个元素,每次都是插入到队尾的索引处 * @param t 元素值 * @return */public boolean addElement(T t);/** * 删除一个元素 * 删除的都是队列头部的元素 * @return */public boolean removeElement();/** * 销毁一个队列 * 初始化队列的逆向,并且释放内存 * @return */public void destroyQueue();/** * 清空一个队列信息 * 但是不用释放内存 * @return */public void clearQueue();/** * 队列是否为空的判断 * @return */public boolean isEmpty();/** * 队列是否为满的判断 * @return */public boolean isFull();/** * 队列长度 * @return */public int getQueueLength();/** * 对队列中的元素进行迭代 */public void iteartorQueue();}我们使用接口来封装这些操作,让具体的队列类实现这些接口,或者持有这些接口的引用(策略模式),来完成队列的数据操作。
设计一个抽象的队列基类,这里是实现了这个接口,其实可以尝试持有接口的引用的。
这个基类有以下几个属性
1)队列的容量,初始化时设置的。
2)队列的长度
3)队列尾的索引值,插入元素时插入到这个索引处
4)队列头的索引值,删除时删除这个索引处的值
5)数组,用来维护队列内部的元素数据
MyAbsQueue.java
/** * 队列的抽象基类 * * @author szxgg * * @param */public abstract class MyAbsQueue<T> implements IQueueOp<T>{/** * 头元素的索引 */protected int headIndex;/** * 尾元素的索引 */protected int tailIndex;/** * 当前队列的长度 */protected int currentLength;/** * 队列的容量 */protected int capacity;/** * 数组,维护队列内部的元素排列 */protected T[] arrays;public void initQueue(int capacity) {this.capacity = capacity;arrays =initQueueElements(this.capacity);}protected abstract T[] initQueueElements(int capacity);public boolean addElement(T t) {if(isFull()){return false;}//在末尾的索引处插入元素arrays[tailIndex] = t;//末尾的索引加1tailIndex++;//防止越界tailIndex = tailIndex%capacity;//长度加1currentLength++;return true;}public boolean removeElement() {//判空if(isEmpty()){return false;}//删除头指针指向的元素arrays[headIndex] = null;//头指针元素+1headIndex++;//防止越界headIndex = headIndex%capacity;//长度减1currentLength--;return true;}public void destroyQueue() {clearQueue();arrays=null;capacity=0;}public void clearQueue() {headIndex=0;tailIndex=0;currentLength=0;}public boolean isEmpty() {return currentLength==0;}public boolean isFull() {return currentLength==capacity;}public int getQueueLength() {return currentLength;}}
下面是队列的实现类,主要负责实现初始化的操作以及迭代的具体操作(因为在泛型中没法执行)
/** * @author lenovo *队列,存放的是整型数组的 */public class IntegerQueue extends MyAbsQueue<Integer>{public IntegerQueue(int capacity) {initQueue(capacity);}@Overrideprotected Integer[] initQueueElements(int capacity) {return new Integer[capacity];}public void iteartorQueue() {for(int i=headIndex;i<headIndex+currentLength;i++){System.out.println(arrays[i%capacity]);}}}基本上这个队列就好了,下面可以用测试代码进行测试分析
TestActivity.java
import java.util.List;public class TestActivity {public static void main(String[] args){MyAbsQueue<Integer> queue = new IntegerQueue(4);//初始化先打印一下queue.iteartorQueue();//插入元素System.out.println("success add:"+queue.addElement(1));System.out.println("success add:"+queue.addElement(2));System.out.println("success add:"+queue.addElement(3));System.out.println("success add:"+queue.addElement(4));System.out.println("success add:"+queue.addElement(5));queue.iteartorQueue();//删除元素System.out.println("success delete:"+queue.removeElement());queue.iteartorQueue();System.out.println("success delete:"+queue.removeElement());queue.iteartorQueue();System.out.println("success delete:"+queue.removeElement());queue.iteartorQueue();System.out.println("success delete:"+queue.removeElement());queue.iteartorQueue();System.out.println("success delete:"+queue.removeElement());queue.iteartorQueue();//再插入3个System.out.println("success add:"+queue.addElement(10));System.out.println("success add:"+queue.addElement(20));System.out.println("success add:"+queue.addElement(30));queue.iteartorQueue();//清除队列queue.clearQueue();System.out.println("after clear");queue.iteartorQueue();queue.addElement(45);queue.iteartorQueue();//destroyqueue.destroyQueue();System.out.println("after destroy");queue.iteartorQueue();queue.addElement(11);queue.iteartorQueue();}}
输出如下:success add:true
success add:true
success add:true
success add:true
success add:false
1
2
3
4
success delete:true
2
3
4
success delete:true
3
4
success delete:true
4
success delete:true
success delete:false
success add:true
success add:true
success add:true
10
20
30
after clear
45
after destroy
三.下面分析下设计队列时相关方法的坑和注意点
1.插入一个元素:
1) 插入前要判断队列是否满了,如果满了就不插入---判断满了的标志是数组当前的长度==数组的capacity
2)是在tailIndex处插入一个元素,即arrays[tailIndex] = element;然后需要将tailIndex++,并且再和capacity取余,防止多次存取后的数组越界,注意环形特别需要取余操作。
3)插入完成后队列的长度也要+1;
2.删除一个元素
1)删除一个元素前需要判断这个队列是否为空队列,判断空队列状态的标准是length ==0;
2)是从startIndex处进行元素的删除,删除后startIndex++,然后为了防止数组越界再和队列的capacity取余。
3)数组的长度自减
3.迭代
for(int i = startIndex;i<startIndex+length;i++){
syso(arrays[i%capacity]);
}
首先不能是从0到length,因为有可能经过多次存取操作后首位置不是0,并且0上没有数据
其次不能是startIndex到length,因为有可能startIndex是3,但是length是4,这时应该迭代4个元素,但是只迭代了一个
所以就是startIndex到startIndex+length。这样可以保证迭代的准确
然后是打印
不能直接打印arrays[i],因为i是从startIndex到startIndex+length,非常有可能就越界了,
越界的话就直接和容量取余。
这块可以参考collection list arraylist的实现,画一个uml图进行分析学习
- 简单数据结构的实现之链队列
- 简单数据结构的实现之循环队列
- 数据结构之简单队列的实现
- (三)数据结构之线性表的简单实现:队列
- 数据结构之队列的实现
- 数据结构之队列的实现
- 数据结构之 队列的实现!
- 数据结构7:队列的简单实现
- [数据结构]队列的C语言简单实现
- 数据结构实现之队列
- 数据结构之队列的实现(c语言)
- 数据结构之 队列的操作与实现
- 经典数据结构之数组实现的队列
- 数据结构之队列的java实现
- 数据结构之循环队列的实现
- 数据结构之链队列的实现
- 数据结构学习之队列的数组实现
- 数据结构之队列的实现(JAVA)
- 运行matlab版的TLD算法
- 浅谈视图的frame、bounds和center属性
- 从问题到程序
- 选择排序
- hdu1087 Super Jumping! Jumping! Jumping! (求最大递增子序列和)
- 数据结构之简单队列的实现
- 杭电find the night
- HDU 4012Paint on a Wall
- ZOJ 2972-Hurdles of 110m(背包dp)
- 为什么工程师需要花时间积累
- fragment嵌套使用时getFragmentManager.findFragment()为空的问题
- 轻量级队列工具Httpsqs
- 数据结构之线性表(单链表)
- iOS中的ARC---内存管理的思考方式