博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
日常学习随笔-数组、单链表、双链表三种形式实现队列结构的基本操作(源码注释)...
阅读量:6576 次
发布时间:2019-06-24

本文共 15961 字,大约阅读时间需要 53 分钟。

一、队列结构(本文侧重于源码实现,基础理论不多赘述)

  和栈一样,队列(queue)也是表,然而使用队列是在一端插入数据,在另一端删除数据。这里插入就是入队(enqueue),删除就是(dequeue).

       队列的核心思想是:“先进先出”

  队列的实现方式有很多中,常见的有

  (1)数组方式

  (2)单链表方式

  (3)双链表方式

  (4)其他

二、数组方式实现队列结构(详细注释说明)

   我学习的时候,发现网上有很多数组实现队列,用得最多的是循环结构的方式,提供一下:(数组循环结构实现队列结构)

我这里并没有使用这种方式,下面的案例使用的是,在队列内部维护了2个数组,一个是执行数组(固定长度-不可扩展容量),一个等待数组(初始长度+System复制扩展容量),这个队列是永远支持入队操作的,当执行队列未满的时候,优先入队执行队列,当执行队列满了的时候,

会将数据继续入队到等待队列中。当执行队列出队数据的时候,也会检查等待队列中是否有数据,有的话会调取等待的数据到执行队列中。

提供一下类的结构图:

 源码如下:

MyQueueDefin3.java

1 package com.xfwl.algorithmAnalysis.heap;  2 import java.util.Arrays;  3 /**  4  * 自定义栈结构(基于数组的形式)  5  * 队列的核心思想:先进先出  6  * @function  日常学习测试  7  * @author 小风微凉  8  * @time  2018-5-20 上午8:41:27  9  */ 10 public class MyQueueDefin3
{ 11 /** 12 * 定义一个默认扩展容量:100 13 * 特别说明: 14 * 这个案例就不做数组容量扩展了,默认设置一个定量的数组。如果入队列达到上限则需要等待! 15 * 所以又需要创建一个等待数组(这个可以扩容) 16 * 17 */ 18 private static final int DEFAULT_CAPACITY=10; 19 private static final int DEFAULT_WAIT_CAPACITY=10; 20 /** 21 * 数组队列容器:(执行队列-不支持扩展) 22 */ 23 private T[] arrQueue; 24 /** 25 * 等待队列数组(等待队列-支持扩展) 26 */ 27 private T[] waitQueue; 28 /** 29 * 计数器(执行队列中的数据条数) 30 */ 31 private int nodeCount=0; 32 /** 33 * 计数器(等待队列中的数据条数) 34 */ 35 private int nodeWaitCount=0; 36 /** 37 * 栈构造器 38 */ 39 public MyQueueDefin3(){ 40 //重置队列结构 41 this.arrQueue=(T[]) new Object[this.DEFAULT_CAPACITY]; 42 this.waitQueue=(T[]) new Object[this.DEFAULT_WAIT_CAPACITY]; 43 this.nodeCount=0; 44 this.nodeWaitCount=0; 45 } 46 /** 47 * 扩展数组容器(仅供waitQueue使用) 48 * @param newCapacity 新容量大小 49 * 说明:这里参考ArrayList源码中的一套扩展规则">>" 50 */ 51 public void ensureCapacity(int newCapacity){ 52 //大小范围检查 53 if(newCapacity<=this.size()){
//不超过了当前容器的容量大小 54 return;//则不需要扩展容器容量 55 } 56 //数组初始值判断 57 if(this.waitQueue==null){ 58 waitQueue=(T[]) new Object[newCapacity]; 59 return;//第一次初始化进来 60 } 61 //需要扩展容器容量 62 T[] newItems=(T[]) Arrays.copyOf(this.waitQueue, newCapacity,this.waitQueue.getClass()); 63 this.waitQueue=newItems; 64 } 65 /** 66 * 执行队列容量 67 * @return 68 */ 69 public int size(){ 70 return this.nodeCount; 71 } 72 /** 73 * 等待队列容量 74 * @return 75 */ 76 public int waitSize(){ 77 return this.nodeWaitCount; 78 } 79 /** 80 * 数据入队列 81 * @param data 数据 82 * @return 83 */ 84 public boolean enqueue(T data){ 85 boolean bool=false; 86 try{ 87 //判断当前执行队列是否达到上限 88 if(this.size()==this.DEFAULT_CAPACITY){
//执行队列已经上限,数据压入等待队列中 89 //判断等待队列是否达到上限,是否需要扩容 90 if(this.nodeWaitCount==this.waitQueue.length){
//等待队列达到上限,需要扩容 91 int newCapacity=this.waitSize()+this.waitSize()>>1;//扩展量:取当前容量的一半,且向下取整 92 ensureCapacity(newCapacity); 93 } 94 //数据压入等待队列 95 this.waitQueue[this.nodeWaitCount]=data; 96 this.nodeWaitCount++; 97 bool=false; 98 System.out.println("执行队列已满容量:"+DEFAULT_CAPACITY+",数据进入等待队列!等待队列容量:"+this.waitSize()); 99 }else{
//执行队列未满,可继续压入 100 this.arrQueue[this.nodeCount]=data;101 this.nodeCount++;102 bool=true; 103 System.out.println("数据进入执行队列!当前容量:"+this.size()+",剩余容量:"+(this.DEFAULT_CAPACITY-this.size()));104 }105 }catch(Exception e){106 e.printStackTrace();107 throw e;108 }109 return bool; 110 }111 /**112 * 数据出队列113 * @return114 */115 public T dequeue(){116 T data=null;117 if(this.size()==0){118 System.out.println("执行队列中无数据,请先插入数据!");119 return data;120 } 121 if(this.size()==this.DEFAULT_CAPACITY){
//执行队列已经上限,出队的同时,调取等待队列的第一条数据到执行队列中122 //出执行队列123 data=this.arrQueue[0];124 //数组数据前移一位125 System.arraycopy(this.arrQueue, 1, this.arrQueue, 0, this.size()-1);126 this.arrQueue[this.size()-1]=null;127 this.nodeCount--;128 System.out.println("执行队列【已满】,出队数据:"+data+",当前容量:"+this.nodeCount+",剩余熔炼"+(this.DEFAULT_CAPACITY-this.nodeCount));129 //调取判断130 if(this.waitSize()>0){131 //调取等待队列的第一条数据到执行队列的最后一条132 T tmpData=this.waitQueue[0];133 this.arrQueue[this.DEFAULT_CAPACITY-1]=tmpData;134 //等待队列数据变化:要移除的位置之后的数据前移一位135 System.arraycopy(this.waitQueue, 1, this.waitQueue, 0, this.waitSize()-1);136 //末尾的数据需要置空137 this.waitQueue[this.waitSize()-1]=null;138 //计数-1139 this.nodeWaitCount--;140 this.nodeCount++;141 System.out.println("tips:等待队列调取一位数据补充执行队列,调取数据:"+tmpData+",当前执行队列当前容量:"+this.nodeCount+",剩余熔炼"+(this.DEFAULT_CAPACITY-this.nodeCount));142 }else{143 System.out.println("tips:等待队列中无数据,当前执行队列当前容量:"+this.nodeCount+",剩余熔炼"+(this.DEFAULT_CAPACITY-this.nodeCount));144 } 145 }else{
//仅仅执行队列中数据出列146 //出执行队列147 data=this.arrQueue[0];148 //数组数据前移一位149 System.arraycopy(this.arrQueue, 1, this.arrQueue, 0, this.size()-1);150 this.arrQueue[this.size()-1]=null;151 this.nodeCount--;152 System.out.println("执行队列【不满】,出队数据:"+data+",当前容量:"+this.nodeCount+",剩余熔炼"+(this.DEFAULT_CAPACITY-this.nodeCount));153 }154 return data; 155 } 156 /**157 * 打印队列数据158 */159 public void printList(){160 System.out.println("----1·【执行队列】开始打印---------------------");161 for(int i=0;i

 测试类:Test3.java

1 package com.xfwl.algorithmAnalysis.heap; 2  3 public class Test3 { 4     public static void main(String[] args) { 5         //创建一个队列对象 6         MyQueueDefin3 queue=new MyQueueDefin3<>(); 7         //打印 8         queue.printList(); 9         //压入数据(把执行队列压满)10         for(int i=0;i<10;i++){11             queue.enqueue("数据-"+(i+1));12         }13         //打印14         queue.printList();15         //再压入一个数据到执行队列中16         queue.enqueue("数据-11");17         queue.enqueue("数据-12");18         queue.enqueue("数据-13");19         //打印20         queue.printList();21         //执行队列出列一个数据22         queue.dequeue();23         //打印24         queue.printList();25     }26 }

 运行结果:

----1·【执行队列】开始打印---------------------队列为空,无数据返回!----1·【执行队列】结束打印-------------------------2·【等待队列】开始打印---------------------队列为空,无数据返回!----2·【等待队列】结束打印---------------------数据进入执行队列!当前容量:1,剩余容量:9数据进入执行队列!当前容量:2,剩余容量:8数据进入执行队列!当前容量:3,剩余容量:7数据进入执行队列!当前容量:4,剩余容量:6数据进入执行队列!当前容量:5,剩余容量:5数据进入执行队列!当前容量:6,剩余容量:4数据进入执行队列!当前容量:7,剩余容量:3数据进入执行队列!当前容量:8,剩余容量:2数据进入执行队列!当前容量:9,剩余容量:1数据进入执行队列!当前容量:10,剩余容量:0----1·【执行队列】开始打印---------------------数据-1数据-2数据-3数据-4数据-5数据-6数据-7数据-8数据-9数据-10----1·【执行队列】结束打印-------------------------2·【等待队列】开始打印---------------------队列为空,无数据返回!----2·【等待队列】结束打印---------------------执行队列已满容量:10,数据进入等待队列!等待队列容量:1执行队列已满容量:10,数据进入等待队列!等待队列容量:2执行队列已满容量:10,数据进入等待队列!等待队列容量:3----1·【执行队列】开始打印---------------------数据-1数据-2数据-3数据-4数据-5数据-6数据-7数据-8数据-9数据-10----1·【执行队列】结束打印-------------------------2·【等待队列】开始打印---------------------数据-11数据-12数据-13----2·【等待队列】结束打印---------------------执行队列【已满】,出队数据:数据-1,当前容量:9,剩余熔炼1tips:等待队列调取一位数据补充执行队列,调取数据:数据-11,当前执行队列当前容量:10,剩余熔炼0----1·【执行队列】开始打印---------------------数据-2数据-3数据-4数据-5数据-6数据-7数据-8数据-9数据-10数据-11----1·【执行队列】结束打印-------------------------2·【等待队列】开始打印---------------------数据-12数据-13----2·【等待队列】结束打印---------------------

 三、单链表方式实现队列结构

类结构图:

 MyQueueDefin.java类

1 package com.xfwl.algorithmAnalysis.heap;  2 /**  3  * 自定义栈结构(基于单链表的形式)  4  * 队列的核心思想:先进先出  5  * @function  日常学习测试  6  * @author 小风微凉  7  * @time  2018-5-20 上午8:41:27  8  */  9 public class MyQueueDefin
{ 10 /** 11 * 头结点 12 */ 13 private Node
front; 14 /** 15 * 计数器 16 */ 17 private int nodeCount=0; 18 /** 19 * 队列构造器 20 */ 21 public MyQueueDefin(){ 22 //重置队列结构 23 front=new Node(null,null); 24 nodeCount=0; 25 } 26 /** 27 * 队列容量 28 * @return 29 */ 30 public int size(){ 31 return this.nodeCount; 32 } 33 /** 34 * 拿到最后一个结点(最新的入队列数据结点) 35 * @return 36 */ 37 private Node
findLastNode(){ 38 Node
tmp=this.front; 39 while(tmp.next!=null){ 40 tmp=tmp.next; 41 } 42 return tmp; 43 } 44 /** 45 * 数据入队列 46 * @param data 数据 47 * @return 48 */ 49 public boolean enqueue(T data){ 50 boolean bool=false; 51 try{ 52 //创建新鲜结点 53 Node
newNode=new Node<>(data,null); 54 //拿到队列尾部结点 55 this.findLastNode().next=newNode; 56 //计数器+1 57 this.nodeCount++; 58 bool=true; 59 }catch(Exception e){ 60 e.printStackTrace(); 61 throw e; 62 } 63 return bool; 64 } 65 /** 66 * 数据出队列 67 * @return 68 */ 69 public T dequeue(){ 70 if(this.size()==0){ 71 System.out.println("空队列,请先插入数据!"); 72 return null; 73 } 74 T data=this.findNode(0).data; 75 this.front.next=this.findNode(0).next; 76 this.nodeCount--; 77 return data; 78 } 79 /** 80 * 根据索引值找到结点 81 * @param index 位置索引值 82 * @return 83 */ 84 private Node
findNode(int index){ 85 if(index<0 || index>(this.size()-1)){ 86 throw new IllegalArgumentException("参数不合法,请重新输入!"); 87 } 88 //第一个数据结点 89 Node tmp=this.front.next; 90 for (int i = 0; i < this.size(); i++) { 91 if(index==i){ 92 break; 93 } 94 tmp=tmp.next; 95 } 96 return tmp; 97 } 98 /** 99 * 打印队列数据100 */101 public void printList(){102 System.out.println("-----------开始打印----------------");103 for(int i=0;i
{115 /**116 * 结点数据域117 */118 private T data;119 /**120 * 结点指针域121 */122 private Node
next;123 /**124 * 结点构造函数125 */126 public Node(T data,Node
node){127 this.data=data;128 this.next=node;129 }130 }131 }

  测试类:Test.java

1 package com.xfwl.algorithmAnalysis.heap; 2 /** 3  * 测试类 4  * @function   5  * @author 小风微凉 6  * @time  2018-5-20 上午9:01:13 7  */ 8 public class Test { 9     public static void main(String[] args) {10         //创建队列对象11         MyQueueDefin queue=new MyQueueDefin<>();12         //打印13         queue.printList();14         //入队15         queue.enqueue("当1个数据");16         queue.enqueue("当2个数据");17         queue.enqueue("当3个数据");18         queue.enqueue("当4个数据");19         queue.enqueue("当5个数据");20         //打印21         queue.printList();22         //出队23         queue.dequeue();24         //打印25         queue.printList();26         //入队27         queue.enqueue("当6个数据");28         //打印29         queue.printList();30     }31 }

  运行结果:

-----------开始打印----------------队列为空,无数据!-----------结束打印---------------------------开始打印----------------当1个数据当2个数据当3个数据当4个数据当5个数据-----------结束打印---------------------------开始打印----------------当2个数据当3个数据当4个数据当5个数据-----------结束打印---------------------------开始打印----------------当2个数据当3个数据当4个数据当5个数据当6个数据-----------结束打印----------------

 四、双链表方式实现队列结构 

类结构图

MyQueueDefin2.java 

1 package com.xfwl.algorithmAnalysis.heap;  2   3 /**  4  * 自定义栈结构(基于双链表的形式)  5  * 队列的核心思想:先进先出  6  * @function  日常学习测试  7  * @author 小风微凉  8  * @time  2018-5-20 上午8:41:27  9  */ 10 public class MyQueueDefin2
{ 11 /** 12 * 头结点 13 */ 14 private Node
front; 15 /** 16 * 尾结点 17 */ 18 private Node
back; 19 /** 20 * 计数器 21 */ 22 private int nodeCount=0; 23 /** 24 * 队列构造器 25 */ 26 public MyQueueDefin2(){ 27 //重置队列结构 28 this.front=new Node(null,null,null); 29 this.back=new Node(null,null,null); 30 this.front.next=this.back; 31 this.back.prev=this.front; 32 nodeCount=0; 33 } 34 /** 35 * 队列容量 36 * @return 37 */ 38 public int size(){ 39 return this.nodeCount; 40 } 41 /** 42 * 拿到最后一个结点(最新的入队列数据结点) 43 * @return 44 */ 45 private Node
findLastNode(){ 46 if(this.size()==0){ 47 return this.front; 48 } 49 return this.back.prev; 50 } 51 /** 52 * 数据入队列 53 * @param data 数据 54 * @return 55 */ 56 public boolean enqueue(T data){ 57 boolean bool=false; 58 try{ 59 //创建新鲜结点 60 Node
newNode=new Node<>(data,null,null); 61 //拿到队列尾部结点 62 Node lastNode=this.findLastNode(); 63 lastNode.next=newNode; 64 newNode.prev=lastNode; 65 newNode.next=this.back; 66 this.back.prev=newNode; 67 //计数器+1 68 this.nodeCount++; 69 bool=true; 70 }catch(Exception e){ 71 e.printStackTrace(); 72 throw e; 73 } 74 return bool; 75 } 76 /** 77 * 数据出队列 78 * @return 79 */ 80 public T dequeue(){ 81 if(this.size()==0){ 82 System.out.println("空队列,请先插入数据!"); 83 return null; 84 } 85 Node
deNode=this.findNode(0); 86 T data=deNode.data; 87 this.front.next=deNode.next; 88 deNode.next.prev=this.front; 89 this.nodeCount--; 90 return data; 91 } 92 /** 93 * 根据索引值找到结点 94 * @param index 位置索引值 95 * @return 96 */ 97 private Node
findNode(int index){ 98 if(index<0 || index>(this.size()-1)){ 99 throw new IllegalArgumentException("参数不合法,请重新输入!");100 }101 //第一个数据结点102 Node tmp=this.front.next;103 for (int i = 0; i < this.size(); i++) {104 if(index==i){105 break;106 }107 tmp=tmp.next;108 }109 return tmp;110 }111 /**112 * 打印队列数据113 */114 public void printList(){115 System.out.println("-----------开始打印----------------");116 for(int i=0;i
{128 /**129 * 结点数据域130 */131 private T data;132 /**133 * 结点前驱指针域134 */135 private Node
prev;136 /**137 * 结点后驱指针域138 */139 private Node
next;140 /**141 * 结点构造函数142 */143 public Node(T data,Node
prev,Node
next){144 this.data=data;145 this.prev=prev;146 this.next=next;147 }148 }149 }

  测试类:Test2.java 

1 package com.xfwl.algorithmAnalysis.heap; 2 /** 3  * 测试类 4  * @function   5  * @author 小风微凉 6  * @time  2018-5-20 上午9:01:13 7  */ 8 public class Test2 { 9     public static void main(String[] args) {10         //创建队列对象11         MyQueueDefin2 queue=new MyQueueDefin2<>();12         //打印13         queue.printList();14         //入队15         queue.enqueue("当1个数据");16         queue.enqueue("当2个数据");17         queue.enqueue("当3个数据");18         queue.enqueue("当4个数据");19         queue.enqueue("当5个数据");20         //打印21         queue.printList();22         //出队23         queue.dequeue();24         //打印25         queue.printList();26         //入队27         queue.enqueue("当6个数据");28         //打印29         queue.printList();30     }31 }

  运行结果:

-----------开始打印----------------队列为空,无数据!-----------结束打印---------------------------开始打印----------------当1个数据当2个数据当3个数据当4个数据当5个数据-----------结束打印---------------------------开始打印----------------当2个数据当3个数据当4个数据当5个数据-----------结束打印---------------------------开始打印----------------当2个数据当3个数据当4个数据当5个数据当6个数据-----------结束打印----------------

 

转载于:https://www.cnblogs.com/newwind/p/9062757.html

你可能感兴趣的文章
(trigger)触发器的定义和作用
查看>>
本地储存
查看>>
shell小脚本工具合集
查看>>
10大基础实用算法及其讲解
查看>>
推荐系统干货总结【全】
查看>>
os.path 模块
查看>>
Python scrapy 常见问题及解决 【遇到的坑】
查看>>
百度UEditor图片上传或文件上传路径自定义
查看>>
(转载)bash: ./a.sh: /bin/bash^M: bad interpreter: No such file or directory的解决方法------dos--->unix...
查看>>
AngularJS开发指南13:AngularJS的过滤器详解
查看>>
利用boost将C++携程python可以调用的库
查看>>
正则表达式收藏
查看>>
python异常处理,日志处理
查看>>
COMMON INTERVIEW QUESTIONS
查看>>
HDU1164 Eddy's research I(解法二)
查看>>
UVA11192 Group Reverse
查看>>
UVA10603 Fill
查看>>
fwt模板
查看>>
立即执行函数: (function(){...})() 与 (function(){...}()) 有什么区别?
查看>>
sth else special(json distribution)
查看>>