当前位置:   article > 正文

通过Java实现数据结构:链式队列以及顺序循环队列

通过Java实现数据结构:链式队列以及顺序循环队列

目录

(一)链式队列

一、代码结构

二、程序源码

1.PollEmptyException类:

2.MyQueue类(包含双向链表节点内部类,当然类外定义也可以):

(1)定义

(2)内部类ListNode

(3)成员变量

(4)  相关方法

1)入队方法

2)出队方法(包括一个出队判空抛出异常的底层方法)

3)获取队头元素方法(调用判空抛出异常的方法)

4)判断队列是否为空的方法

三、测试案例

Test类源码如下

运行结果如下

(二)顺序循环队列

一、代码结构

二、程序源码

1.PollEmptyException类:

2.OfferFullException类:

3.MyQueue类:

(1)定义

(2)成员变量

(3)相关方法

1)构造方法

2)入队方法(包括一个入队判满抛出异常的底层方法)

3)出队方法(包括一个出队判空抛出异常的底层方法)

4)获取队头元素方法(调用判空抛出异常的方法)

5)判断队列是否为满的方法

6)判断队列是否为空的方法

三、测试案例

Test类源码如下

运行结果如下


        队列是一种先进先出的特殊数据结构,在Java的集合框架中可以通过应用了Queue接口的LinkedList集合类实现(LinkedList不仅可以作为双向链表使用,也可以作为栈和队列使用)。本文将以双向链表为底层结构模拟实现队列(链式队列)以及以数组为底层结构模拟实现队列(顺序循环队列),并实现队列中的入队、出队、获取队头元素、判断队列是否为空的方法。

(一)链式队列

一、代码结构

1.MyQueue:实现链式队列。

2.PollEmptyException:用于队列为空时做出非法操作时抛出异常。

3.Test:其main方法用于测试MyQueue相关操作。

二、程序源码

1.PollEmptyException类

  1. public class PollEmptyException extends RuntimeException{
  2. public PollEmptyException() {
  3. super();
  4. }
  5. public PollEmptyException(String message) {
  6. super(message);
  7. }
  8. }

注意:PollEmptyException属于运行时异常,应当继承于RuntimeException,并且重写相关方法。

2.MyQueue类(包含双向链表节点内部类,当然类外定义也可以):

(1)定义
public class MyQueue
(2)内部类ListNode
  1. static class ListNode{
  2. //数组域
  3. public int val;
  4. //两个指针域
  5. public ListNode prev;
  6. public ListNode next;
  7. //指定数值的构造方法
  8. public ListNode(int val){
  9. this.val=val;
  10. }
  11. }
(3)成员变量
  1. //队头指针
  2. private ListNode front;
  3. //队尾指针
  4. private ListNode rear;
(4)  相关方法
1)入队方法
  1. //入队方法
  2. public int offer(int val){
  3. ListNode listNode=new ListNode(val);
  4. if(front==null){
  5. front=rear=listNode;
  6. }else{
  7. rear.next=listNode;
  8. listNode.prev=rear;
  9. rear=listNode;
  10. }
  11. return listNode.val;
  12. }
2)出队方法(包括一个出队判空抛出异常的底层方法)
  1. //判空抛出异常方法
  2. private void checkPollisEmpty(){
  3. if(front==null){
  4. throw new PollEmptyException();
  5. }
  6. }
  7. //出队方法
  8. public int poll(){
  9. //出队判空抛出异常
  10. try{
  11. checkPollisEmpty();
  12. }catch (PollEmptyException e){
  13. e.printStackTrace();
  14. }
  15. int val= front.val;
  16. //判断是否为单一元素队列
  17. if(front.next==null)
  18. {
  19. front=rear=null;
  20. }
  21. front=front.next;
  22. front.prev=null;
  23. return val;
  24. }
3)获取队头元素方法(调用判空抛出异常的方法)
  1. //获取队头元素方法
  2. public int peek(){
  3. //判空抛出异常
  4. try{
  5. checkPollisEmpty();
  6. }catch (PollEmptyException e){
  7. e.printStackTrace();
  8. }
  9. return front.val;
  10. }
4)判断队列是否为空的方法
  1. //判断队列是否为空
  2. public boolean isEmpty(){
  3. return front==null;
  4. }

三、测试案例

Test类源码如下

  1. public class Test {
  2. public static void main(String[] args) {
  3. MyQueue myQueue=new MyQueue();
  4. //入队操作
  5. myQueue.offer(1);
  6. myQueue.offer(2);
  7. myQueue.offer(3);
  8. //获取队头元素值
  9. System.out.println("当前队头元素值为"+myQueue.peek());
  10. System.out.println("*****************************");
  11. //出队操作
  12. System.out.println("出队元素值为"+myQueue.poll());
  13. System.out.println("当前队头元素值为"+myQueue.peek());
  14. System.out.println("*****************************");
  15. //判空操作
  16. System.out.println(myQueue.isEmpty());
  17. }
  18. }

运行结果如下

(二)顺序循环队列

        顺序循环队列与链式队列的区别是,其底层通过数组实现,并且多出了判满操作。

        由于入队时只能从队尾rear处入队,出队时只能从队头front处出队,所以显而易见队头前面的存储空间会随着队列的使用而被搁置浪费(即无法再被新元素占用),所以我们可以通过令front以及rear两个指示器循环移动的方式实现逻辑上为环的循环数组,进而实现顺序循环队列,具体代码如下。

一、代码结构

1.MyQueue:实现链式队列。

2.PollEmptyException:用于队列为空时做出非法操作时抛出异常。

3.OfferFullException:用于队列为满时做出非法操作时抛出异常。

4.Test:其main方法用于测试MyQueue相关操作。

二、程序源码

1.PollEmptyException类:
  1. public class PollEmptyException extends RuntimeException{
  2. public PollEmptyException() {
  3. super();
  4. }
  5. public PollEmptyException(String message) {
  6. super(message);
  7. }
  8. }
2.OfferFullException类:
  1. public class OfferFullException extends RuntimeException{
  2. public OfferFullException() {
  3. super();
  4. }
  5. public OfferFullException(String message) {
  6. super(message);
  7. }
  8. }

注意:PollEmptyException和OfferFullException均属于运行时异常,应当继承于RuntimeException,并且重写相关方法。 

3.MyQueue类:
(1)定义
public class MyQueue
(2)成员变量
  1. //数组引用,指向队列所储存元素的数组
  2. private int[]elem;
  3. //队头指示器(指向当前队头元素的位置)
  4. private int front;
  5. //队尾指示器(指向下一个入队元素的位置)
  6. private int rear;
(3)相关方法
1)构造方法
  1. public MyQueue(){
  2. elem=new int[10];
  3. }
2)入队方法(包括一个入队判满抛出异常的底层方法)
  1. //检查队列是否为满的方法
  2. private void checkFull(){
  3. if(isFull()){
  4. throw new OfferFullException();
  5. }
  6. }
  7. //入队方法
  8. public int offer(int val){
  9. //判满抛出异常
  10. try{
  11. checkFull();
  12. }catch (OfferFullException e){
  13. e.printStackTrace();
  14. }
  15. elem[rear]=val;
  16. rear=(rear+1)%elem.length;
  17. return val;
  18. }

入队时rear加1再对数组长度取余数,就可以保证rear在数组下标中不断循环,从而避免空间浪费。 

3)出队方法(包括一个出队判空抛出异常的底层方法)
  1. //检查队列是否为空的方法
  2. private void checkEmpty(){
  3. if(isEmpty()){
  4. throw new PollEmptyException();
  5. }
  6. }
  7. //出队方法
  8. public int poll(){
  9. //判空抛出异常
  10. try{
  11. checkEmpty();
  12. }catch (PollEmptyException e){
  13. e.printStackTrace();
  14. }
  15. int val=elem[front];
  16. front=(front+1)%elem.length;
  17. return val;
  18. }

出队时front加1再对数组长度取余数,就可以保证front在数组下标中不断循环,从而避免空间浪费。  

4)获取队头元素方法(调用判空抛出异常的方法)
  1. //获取队头元素方法
  2. public int peek(){
  3. //判空抛出异常
  4. try{
  5. checkEmpty();
  6. }catch (PollEmptyException e){
  7. e.printStackTrace();
  8. }
  9. return elem[front];
  10. }
5)判断队列是否为满的方法
  1. //判断队列是否为满方法
  2. public boolean isFull(){
  3. return (rear+1)%elem.length==front;
  4. }

注意:循环顺序队列判满不能直接简单地判断front和rear是否直接相等,因为直接相等时也可能时队列为空的情况,此时二者无法区分。因此为了正确判满,可以采用故意空出一个存储空间的方法,此时队列的实际存储大小为数组长度减一,判满时可以判断rear+1再对数组长度取余是否等于front来检测队列是否为满,这也与判断队列为空区分开(即判断队列为空此时可以采取直接判断front与rear是否相等的方式)。

除去空出存储空间的方法,也可以设置队列有效元素个数usedSize或者标志位flag,通过对标志变量进行检查也可以起到判满判空的效果。

6)判断队列是否为空的方法
  1. //判断队列是否为空方法
  2. public boolean isEmpty(){
  3. return front==rear;
  4. }

三、测试案例

Test类源码如下

  1. public class Test {
  2. public static void main(String[] args) {
  3. MyQueue myQueue=new MyQueue();
  4. //入队操作
  5. myQueue.offer(1);
  6. myQueue.offer(2);
  7. myQueue.offer(3);
  8. //获取队头元素值
  9. System.out.println("当前队头元素值为"+myQueue.peek());
  10. System.out.println("*****************************");
  11. //出队操作
  12. System.out.println("出队元素值为"+myQueue.poll());
  13. System.out.println("当前队头元素值为"+myQueue.peek());
  14. System.out.println("*****************************");
  15. //判空操作
  16. System.out.println(myQueue.isEmpty());
  17. }
  18. }

运行结果如下

以上便是通过Java实现链式队列以及顺序循环队列的全部内容,如有不当,敬请斧正!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/爱喝兽奶帝天荒/article/detail/880206
推荐阅读
相关标签
  

闽ICP备14008679号