特点:先进先出 后进后出
队列是一个有序的列表
代码实现:(没有优化 数组不是环形对列 一次性对列)
public class ArrayQueueDome {public static void main(String[] args) {ArrayQueue arr = new ArrayQueue(5);arr.addArray(5);arr.addArray(4);arr.addArray(3);arr.addArray(-1);arr.addArray(1);arr.addArray(1);// 看看head数据是啥System.out.println(arr.putArray());System.out.println(arr.peek());for (int i = 0; i < 6; i++)System.out.println(arr.putArray());}}//建立一个数组队列class ArrayQueue {// 定义最大容量private int maxSize;// 队列的头尾private int rear;private int front;// 创建队列private int[] arr;public int[] getArr() {return arr;}// 创建队列的构造器public ArrayQueue(int arrMaxSize) {this.maxSize = arrMaxSize;this.arr = new int[maxSize];this.front = -1; // 指向头部的前一个位置this.rear = -1;// 指向尾部的位置(就是队列的最后一个数据)}// 判断队列是否已经满了public boolean isFull() {return maxSize == rear + 1;}// 判断队列是否为空public boolean isEmpty() {return front == rear;}// 添加数据到队列(添加数据时变得只有rear 尾)public void addArray(int i) {// 添加时要先进行判断if (isFull()) {System.out.println("full!!!!");} else {rear++;arr[rear] = i;}}// 输出信息 (输出数据时变得只有front 头)public int putArray() {// 先进行判断队列是否为空if (isEmpty()) {throw new RuntimeException("empty!!!!");} else {front++;return arr[front];}}// 显示队列的头数据是什么public int peek() {return arr[front + 1];}}
需要进行环形的更改:
代码如下:
import java.util.Scanner;public class ArrayQueueDome {public static void main(String[] args) {// 测试一把System.out.println("测试数组模拟环形队列的案例~~~");// 创建一个环形队列CircleArray queue = new CircleArray(5); // 说明设置 4, 其队列的有效数据最大是 3char key = ' '; // 接收用户输入Scanner scanner = new Scanner(System.in);//boolean loop = true;// 输出一个菜单while (loop) {System.out.println("s(show): 显示队列");System.out.println("e(exit): 退出程序");System.out.println("a(add): 添加数据到队列");System.out.println("g(get): 从队列取出数据");System.out.println("h(head): 查看队列头的数据");key = scanner.next().charAt(0);// 接收一个字符switch (key) {case 's':queue.look();break;case 'a':System.out.println("输出一个数");int value = scanner.nextInt();queue.addArray(value);break;case 'g': // 取出数据try {int res = queue.putArray();System.out.printf("取出的数据是%d\n", res);} catch (Exception e) {// TODO: handle exceptionSystem.out.println(e.getMessage());}break;case 'h': // 查看队列头的数据try {int res = queue.peek();System.out.printf("队列头的数据是%d\n", res);} catch (Exception e) {// TODO: handle exceptionSystem.out.println(e.getMessage());}break;case 'e': // 退出scanner.close();loop = false;break;default:break;}}System.out.println("程序退出~~");}}//建立一个数组队列class CircleArray {// 定义最大容量private int maxSize;// 队列的头尾private int rear;private int front;// 创建队列private int[] arr;public int[] getArr() {return arr;}// 创建队列的构造器public CircleArray(int arrMaxSize) {this.maxSize = arrMaxSize;this.arr = new int[maxSize];this.front = 0; // 指向头部的前一个位置this.rear = 0;// 指向尾部的位置(就是队列的最后一个数据)}// 判断队列是否满public boolean isFull() {return (rear + 1) % maxSize == front;}// 判断队列是否为空public boolean isEmpty() {return front == rear;}// 添加数据到队列(添加数据时变得只有rear 尾)public void addArray(int i) {// 添加时要先进行判断if (isFull()) {System.out.println("full!!!!");} else {arr[rear] = i;// 将 rear 后移, 这里必须考虑取模rear = (rear + 1) % maxSize;}}// 输出信息 (输出数据时变得只有front 头)public int putArray() {// 先进行判断队列是否为空if (isEmpty()) {throw new RuntimeException("empty!!!!");} else {int value = arr[front];front = (front + 1) % maxSize;return value;}}// 显示队列的头数据是什么public int peek() {return arr[front];}// 遍历数组public void look() {// 遍历if (isEmpty()) {System.out.println("队列空的,没有数据~~");return;}// 思路:从 front 开始遍历,遍历多少个元素// 动脑筋for (int i = front; i < front + size(); i++) {System.out.printf("arr[%d]=%d\n", i % maxSize, arr[i % maxSize]);}}// 求出当前队列有效数据的个数public int size() {return (rear + maxSize - front) % maxSize;}}
链表实现
单:
package cn.corgy.queue;public class LinkedListQueueDome {public static void main(String[] args) {HeroNode hero1 = new HeroNode(1, "王超", "hehehe");HeroNode hero2 = new HeroNode(2, "1超", "2222");HeroNode hero3 = new HeroNode(3, "2超", "11111");HeroNode hero5 = new HeroNode(3, "2超", "修改的");HeroNode hero4 = new HeroNode(4, "3超", "333333");SingleLinkedList singleLinkedList = new SingleLinkedList();singleLinkedList.addByOrder(hero1);singleLinkedList.addByOrder(hero3);singleLinkedList.addByOrder(hero2);singleLinkedList.addByOrder(hero2);singleLinkedList.show();System.out.println("************************************");singleLinkedList.updateNode(hero5);singleLinkedList.show();System.out.println("************************************");singleLinkedList.deleteNode(2);singleLinkedList.show();}}//创建单向链表class SingleLinkedList {// 创建单向列表的头部 不进行数据的储存private HeroNode head = new HeroNode(0, "", "");/*** 无序添加 与添加的顺序有关** @param heroNode 添加的节点*/public void add(HeroNode heroNode) {// 添加一个临时变量到辅助遍历全部的链表HeroNode temp = head;while (true) {// 如果遍历到最后一个节点 next就会显示nullif (temp.next == null) {break;}// 没有找到向后移动进行索引temp = temp.next;}// 跳出后进行赋值temp.next = heroNode;}/*** 有序添加 根据数据编号进行排序** @param heroNode 需要添加的节点*/public void addByOrder(HeroNode heroNode) {HeroNode temp = head;while (true) {// 如果添加的数据已经存在 打印信息 直接退出if (temp.no == heroNode.no) {System.out.println("需要添加的节点" + heroNode.no + "已经存在");return;}if (temp.next == null) {break;}// 遍历 满足temp.no < heroNode.no && heroNode.no <temp.next.no// 进行添加操作if ((temp.no < heroNode.no && heroNode.no < temp.next.no)) {HeroNode temp2 = temp.next;temp.next = heroNode;heroNode.next = temp2;return;}// 加一进位temp = temp.next;}temp.next = heroNode;}/*** 修改节点信息*/public void updateNode(HeroNode heroNode) {// 判断是否空if (head.next == null) {System.out.println("链表为空~");return;}// 通过遍历全部找到相同的编号值HeroNode temp = head;while (true) {if (temp.next == null) {System.out.println("沒有你要修改的节点");return;}if (temp.next.no == heroNode.no) {temp.next.name = heroNode.name;temp.next.nickname = heroNode.nickname;return;}// 进位temp = temp.next;}}/*** 根据编号删除某个节点*/public void deleteNode(int no) {HeroNode temp = head;while (true) {if (temp.next == null) {break;}// 删除的条件if (no == temp.next.no) {if (temp.next.next == null) {temp.next = null;return;} else {// 跳过中间那个直接指向下一个temp.next = temp.next.next;return;}}temp = temp.next;}System.out.println("没有这个节点");}/*** 链表的展示*/public void show() {// 先判断列表是否为空if (head.next == null) {System.out.println("队列为空");return;}HeroNode temp = head.next;while (true) {// 如果遍历到最后一个节点 next就会显示nullif (temp == null) {break;}System.out.println(temp);// 没有找到向后移动进行索引temp = temp.next;}}}// 定义 HeroNode,每个 HeroNode 对象就是一个节点class HeroNode {public int no;public String name;public String nickname;public HeroNode next; // 指向下一个节点// 构造器public HeroNode(int no, String name, String nickname) {this.no = no;this.name = name;this.nickname = nickname;}// 为了显示方法,我们重新 toString@Overridepublic String toString() {return "HeroNode [no=" + no + ", name=" + name + ", nickname=" + nickname + "]";}}
求单链表的有效节点:
/*** 统计链表的有效个数 有头的话要去头** @param head 头节点* @return 返回有效的个数*/public static int getLength(HeroNode head) {if (head.next == null)System.out.println("empty!!");HeroNode temp = head.next;int index = 0;while (true) {index++;if (temp.next == null)break;temp = temp.next;}return index;}}
查找单链表中倒数第K个节点
/*** 查找单链表中倒数第K个节点 调用了前面的获取有效个数的方法** @param head 头节点* @param lastNo 倒数的第K个值* @return 返回节点信息*/public static HeroNode findLastIndexNode(HeroNode head, int lastNo) {if (head.next == null) {System.out.println("链表为空");return null;}// 先获取所需链表的有效长度int size = getLength(head);// 获取要查询的节点信息(size-lastNo)int index = size - lastNo;if (lastNo <= 0 || lastNo > size) {return null;}// 获取HeroNode cur = head.next;for (int i = 0; i < index; i++) {cur = cur.next;}return cur;}
单链表的反转
/*** 但链表进行翻转 <br>* 思路:<br>* 1.创建一个新的头做新的对象 <br>* 2.将原本的链表依次向新的头进行插入<br>* 3.将老的头的next替代新的头的next** @param head 头节点*/public static void reverseQueue(HeroNode head) {// 其中空链表跟单节点列表不用进行翻转if (head.next == null || head.next.next == null)return;HeroNode reverseNode = new HeroNode(0, "", "");HeroNode cur = head.next;HeroNode next = null;// 遍历需要反转的列表进行定位while (cur != null) {next = cur.next;cur.next = reverseNode.next;reverseNode.next=cur;cur = next;}head.next = reverseNode.next;}}
从尾到头打印单链表
- 合并两个单链表 合并后依旧要有序
双**:
根据单列表进行了简单的修改 即可变成双向的列表
package cn.corgy.queue;public class DoubleLinkedQueueDome {public static void main(String[] args) {DoubleHeroNode hero1 = new DoubleHeroNode(1, "王超", "hehehe");DoubleHeroNode hero2 = new DoubleHeroNode(2, "1超", "2222");DoubleHeroNode hero3 = new DoubleHeroNode(3, "2超", "11111");DoubleHeroNode hero5 = new DoubleHeroNode(3, "2超", "修改的");DoubleHeroNode hero4 = new DoubleHeroNode(4, "3超", "333333");DoubleLinkedList doubleLinkedList = new DoubleLinkedList();doubleLinkedList.addByOrder(hero1);doubleLinkedList.addByOrder(hero3);doubleLinkedList.addByOrder(hero4);doubleLinkedList.addByOrder(hero2);doubleLinkedList.show();System.out.println("************************************");doubleLinkedList.updateNode(hero5);doubleLinkedList.show();System.out.println("************************************");doubleLinkedList.deleteNode(4);doubleLinkedList.show();}}//创建双向链表class DoubleLinkedList {// 创建单向列表的头部 不进行数据的储存private DoubleHeroNode head = new DoubleHeroNode(0, "", "");public DoubleHeroNode getHead() {return head;}/*** 遍历双向链表*/public void show() {// 先判断列表是否为空if (head.next == null) {System.out.println("队列为空");return;}DoubleHeroNode temp = head.next;while (true) {// 如果遍历到最后一个节点 next就会显示nullif (temp == null) {break;}System.out.println(temp);// 没有找到向后移动进行索引temp = temp.next;}}/*** 无序添加到列表的最后 与添加的顺序有关** @param heroNode 添加的节点*/public void add(DoubleHeroNode heroNode) {// 添加一个临时变量到辅助遍历全部的链表DoubleHeroNode temp = head;while (true) {// 如果遍历到最后一个节点 next就会显示nullif (temp.next == null) {break;}// 没有找到向后移动进行索引temp = temp.next;}// 跳出后进行赋值temp.next = heroNode;heroNode.pre = temp; // 双向的精髓}/*** 有序添加 根据数据编号进行排序** @param heroNode 需要添加的节点*/public void addByOrder(DoubleHeroNode heroNode) {DoubleHeroNode temp = head;while (true) {// 如果添加的数据已经存在 打印信息 直接退出if (temp.no == heroNode.no) {System.out.println("需要添加的节点" + heroNode.no + "已经存在");return;}if (temp.next == null) {break;}// 遍历 满足temp.no < heroNode.no && heroNode.no <temp.next.no// 进行添加操作if ((temp.no < heroNode.no && heroNode.no < temp.next.no)) {DoubleHeroNode temp2 = temp.next;// 前一个的下一节点为插入temp.next = heroNode;// 插入节点的下一个位为后一个heroNode.next = temp2;// 插入节点的前一个节点为前一个heroNode.pre = temp;// 插入节点的后一个的前一个节点为插入temp2.pre = heroNode;return;}// 加一进位temp = temp.next;}temp.next = heroNode;}/*** 修改节点信息*/public void updateNode(DoubleHeroNode heroNode) {// 判断是否空if (head.next == null) {System.out.println("链表为空~");return;}// 通过遍历全部找到相同的编号值DoubleHeroNode temp = head;while (true) {if (temp.next == null) {System.out.println("沒有你要修改的节点");return;}if (temp.next.no == heroNode.no) {temp.next.name = heroNode.name;temp.next.nickname = heroNode.nickname;return;}// 进位temp = temp.next;}}/*** 根据编号删除某个节点*/public void deleteNode(int no) {DoubleHeroNode temp = head;while (true) {if (temp.next == null) {break;}// 删除的条件if (no == temp.next.no) {if (temp.next.next == null) {// 如果是最后一各节点话直接进行删除temp.next = null;return;} else {// 跳过中间那个直接指向下一个temp.next = temp.next.next;temp.next.next.pre = temp;return;}}temp = temp.next;}System.out.println("没有这个节点");}}//定义 HeroNode,每个 HeroNode 对象就是一个节点 (定义双向的链表)class DoubleHeroNode {public int no;public String name;public String nickname;public DoubleHeroNode next; // 指向下一个节点public DoubleHeroNode pre; // 指向前一个节点// 构造器public DoubleHeroNode(int no, String name, String nickname) {this.no = no;this.name = name;this.nickname = nickname;}// 为了显示方法,我们重新 toString@Overridepublic String toString() {return "DoubleHeroNode [no=" + no + ", name=" + name + ", nickname=" + nickname + "]";}}
