Java編程內(nèi)功-數(shù)據(jù)結(jié)構(gòu)與算法「隊(duì)列」
基本介紹
隊(duì)列是一個(gè)有序列表,可以用數(shù)組或者鏈表來實(shí)現(xiàn)
遵循先入先出的原則,即先存入隊(duì)列的數(shù)據(jù),要先取出.后存入的要后取出
數(shù)組模擬隊(duì)列
隊(duì)列本身是有序列表,若使用數(shù)組的結(jié)構(gòu)來存儲(chǔ)隊(duì)列的數(shù)據(jù),則隊(duì)列數(shù)組的聲明如下圖,其中maxSize是該隊(duì)列的最大容量.
因?yàn)殛?duì)列的輸入\輸出是分別從前后端來處理,因此需要兩個(gè)變量front及rear分別記錄隊(duì)列前后端的下標(biāo),front會(huì)隨著數(shù)據(jù)輸出而改變,而rear則是隨著數(shù)據(jù)輸入而改變.

代碼案例
- package com.structures.queue;
 - import java.util.Scanner;
 - public class ArrayQueueDemo {
 - public static void main(String[] args) {
 - ArrayQueue arrayQueue = new ArrayQueue(3);
 - char key = ' ';//接受用戶輸入
 - Scanner scanner = new Scanner(System.in);
 - boolean loop = true;
 - //輸出一個(gè)菜單
 - while (loop) {
 - System.out.println("s(show):顯示隊(duì)列");
 - System.out.println("e(exit):退出程序");
 - System.out.println("a(add):添加數(shù)據(jù)到隊(duì)列");
 - System.out.println("g(get):從隊(duì)列取出數(shù)據(jù)");
 - System.out.println("h(head):查看隊(duì)列頭的數(shù)據(jù)");
 - key = scanner.next().charAt(0);
 - switch (key) {
 - case 's':
 - arrayQueue.showQueue();
 - break;
 - case 'a':
 - System.out.println("輸入一個(gè)整數(shù)");
 - int value = scanner.nextInt();
 - arrayQueue.addQueue(value);
 - break;
 - case 'g':
 - try {
 - int queue = arrayQueue.getQueue();
 - System.out.printf("取出的數(shù)據(jù)是%d", queue);
 - }catch (Exception e){
 - System.out.println(e.getMessage());
 - }
 - break;
 - case 'e':
 - scanner.close();
 - loop = false;
 - break;
 - case 'h':
 - try {
 - int head = arrayQueue.headQueue();
 - System.out.printf("取出隊(duì)列頭的數(shù)據(jù)是%d", head);
 - }catch (Exception e){
 - System.out.println(e.getMessage());
 - }
 - default:
 - break;
 - }
 - }
 - System.out.println("程序退出");
 - }
 - }
 - //使用數(shù)組模擬隊(duì)列-編寫一個(gè)ArrayQueue類
 - class ArrayQueue {
 - //表示數(shù)組最大容量
 - private int maxSize;
 - //隊(duì)列頭
 - private int front;
 - //隊(duì)列尾
 - private int rear;
 - //用于存放數(shù)據(jù),模擬隊(duì)列
 - private int[] arr;
 - //創(chuàng)建隊(duì)列構(gòu)造器
 - public ArrayQueue(int arrMaxSize) {
 - maxSize = arrMaxSize;
 - arr = new int[maxSize];
 - front = -1;//指向隊(duì)列頭的前一個(gè)位置
 - rear = -1;//指向隊(duì)列尾的數(shù)據(jù),即就是隊(duì)列最后一個(gè)數(shù)據(jù)
 - }
 - //判斷隊(duì)列是否滿
 - public boolean isFull() {
 - return rear == maxSize - 1;
 - }
 - //判斷隊(duì)列是否為空
 - public boolean isEmpty() {
 - return rear == front;
 - }
 - //添加數(shù)據(jù)到隊(duì)列
 - public void addQueue(int n) {
 - if (isFull()) {
 - System.out.println("隊(duì)列不能加入數(shù)據(jù)");
 - return;
 - }
 - rear++;//讓rear 后移
 - arr[rear] = n;
 - }
 - //獲取隊(duì)列數(shù)據(jù),出隊(duì)列
 - public int getQueue() {
 - if (isEmpty()) {
 - throw new RuntimeException("隊(duì)列為空,不能取數(shù)據(jù)");
 - }
 - front++;
 - return arr[front];
 - }
 - //顯示隊(duì)列所有數(shù)據(jù)
 - public void showQueue() {
 - if (isEmpty()) {
 - System.out.println("隊(duì)列為空,沒有數(shù)據(jù)");
 - }
 - for (int i = 0; i < this.arr.length; i++) {
 - System.out.printf("arr[%d]=%d\n", i, arr[i]);
 - }
 - }
 - //顯示隊(duì)列的頭數(shù)據(jù),注意不是取數(shù)據(jù)
 - public int headQueue() {
 - if (isEmpty()) {
 - throw new RuntimeException("隊(duì)列為空,沒有數(shù)據(jù)");
 - }
 - return arr[front + 1];
 - }
 - }
 
問題分析
- 目前這個(gè)數(shù)組使用一次就不能用,沒有達(dá)到復(fù)用的效果.
 - 將這個(gè)數(shù)組使用算法,改進(jìn)成一個(gè)環(huán)形的隊(duì)列:取模%
 
改進(jìn)成環(huán)形隊(duì)列的思路分析
- front變量的含義做一個(gè)調(diào)整:front 就指向隊(duì)列的第一個(gè)元素,也就是arr[front]就是隊(duì)列的第一個(gè)元素,front的初始值=0
 - rear變量的含義做一個(gè)調(diào)整:rear 指向隊(duì)列的最后一個(gè)元素的后一個(gè)位置,因?yàn)橄M粘鲆粋€(gè)空間作為約定.rear初始值=0
 - 當(dāng)隊(duì)列滿時(shí),條件是(rear+1)%maxSize = front.
 - 當(dāng)隊(duì)列為空時(shí)條件,rear == front 空.
 - 當(dāng)我們這樣分析,隊(duì)列中有效的數(shù)據(jù)的個(gè)數(shù)=(rear+maxSize-front)%maxSize.
 
環(huán)形隊(duì)列代碼案例
- package com.structures.queue;
 - import java.util.Scanner;
 - public class CircleArrayQueue {
 - public static void main(String[] args) {
 - CircleArray arrayQueue = new CircleArray(4);//這里設(shè)置4,其隊(duì)列的有效數(shù)據(jù)最大是3
 - char key = ' ';//接受用戶輸入
 - Scanner scanner = new Scanner(System.in);
 - boolean loop = true;
 - //輸出一個(gè)菜單
 - while (loop) {
 - System.out.println("s(show):顯示隊(duì)列");
 - System.out.println("e(exit):退出程序");
 - System.out.println("a(add):添加數(shù)據(jù)到隊(duì)列");
 - System.out.println("g(get):從隊(duì)列取出數(shù)據(jù)");
 - System.out.println("h(head):查看隊(duì)列頭的數(shù)據(jù)");
 - key = scanner.next().charAt(0);
 - switch (key) {
 - case 's':
 - arrayQueue.showQueue();
 - break;
 - case 'a':
 - System.out.println("輸入一個(gè)整數(shù)");
 - int value = scanner.nextInt();
 - arrayQueue.addQueue(value);
 - break;
 - case 'g':
 - try {
 - int queue = arrayQueue.getQueue();
 - System.out.printf("取出的數(shù)據(jù)是%d", queue);
 - }catch (Exception e){
 - System.out.println(e.getMessage());
 - }
 - break;
 - case 'e':
 - scanner.close();
 - loop = false;
 - break;
 - case 'h':
 - try {
 - int head = arrayQueue.headQueue();
 - System.out.printf("取出隊(duì)列頭的數(shù)據(jù)是%d", head);
 - }catch (Exception e){
 - System.out.println(e.getMessage());
 - }
 - default:
 - break;
 - }
 - }
 - System.out.println("程序退出");
 - }
 - }
 - class CircleArray {
 - //表示數(shù)組最大容量
 - private int maxSize;
 - //front變量的含義做一個(gè)調(diào)整:front 就指向隊(duì)列的第一個(gè)元素,也就是arr[front]就是隊(duì)列的第一個(gè)元素,front的初始值=0
 - private int front;
 - //rear變量的含義做一個(gè)調(diào)整:rear 指向隊(duì)列的最后一個(gè)元素的后一個(gè)位置,因?yàn)橄M粘鲆粋€(gè)空間作為約定.rear初始值=0
 - private int rear;
 - //用于存放數(shù)據(jù),模擬隊(duì)列
 - private int[] arr;
 - public CircleArray(int arrMaxSize) {
 - maxSize = arrMaxSize;
 - arr = new int[maxSize];
 - }
 - //判斷隊(duì)列是否滿
 - public boolean isFull() {
 - return (rear + 1) % maxSize == front;
 - }
 - //判斷隊(duì)列是否為空
 - public boolean isEmpty() {
 - return rear == front;
 - }
 - //添加數(shù)據(jù)到隊(duì)列
 - public void addQueue(int n) {
 - if (isFull()) {
 - System.out.println("隊(duì)列滿,隊(duì)列不能加入數(shù)據(jù)");
 - return;
 - }
 - //直接將數(shù)據(jù)加入
 - arr[rear] = n;
 - //將rear后移,這里必須考慮取模
 - rear = (rear + 1) % maxSize;
 - }
 - //獲取隊(duì)列數(shù)據(jù),出隊(duì)列
 - public int getQueue() {
 - if (isEmpty()) {
 - throw new RuntimeException("隊(duì)列為空,不能取數(shù)據(jù)");
 - }
 - //這里需要分析front是指向隊(duì)列的第一個(gè)元素,
 - //1.先把front對(duì)應(yīng)的值保存到一個(gè)臨時(shí)變量,
 - //2.將front后移,考慮取模
 - //3.將臨時(shí)保存的變量返回
 - int value = arr[front];
 - front = (front + 1) % maxSize;
 - return value;
 - }
 - //顯示隊(duì)列所有數(shù)據(jù)
 - public void showQueue() {
 - if (isEmpty()) {
 - System.out.println("隊(duì)列為空,沒有數(shù)據(jù)");
 - }
 - //從front開始遍歷
 - for (int i = front; i < front + size(); i++) {
 - System.out.printf("arr[%d]=%d\n", i % maxSize, arr[i % maxSize]);
 - }
 - }
 - //求出當(dāng)前隊(duì)列有效數(shù)據(jù)的個(gè)數(shù)
 - public int size() {
 - return (rear + maxSize - front) % maxSize;
 - }
 - //顯示隊(duì)列的頭數(shù)據(jù),注意不是取數(shù)據(jù)
 - public int headQueue() {
 - if (isEmpty()) {
 - throw new RuntimeException("隊(duì)列為空,沒有數(shù)據(jù)");
 - }
 - return arr[front];
 - }
 - }
 
【編輯推薦】















 
 
 

 
 
 
 