java数据结构与算法(稀疏数组、环形队列)01-Double_happy

介绍

字符串匹配问题:

1.有一个字符串 str1="双喜 double happy 双喜 double happy kairis" 
str2="happy 双喜" 
问:
	判断Str1 是否 有 Str2 如果存在,就返回第一次出现的位置,如果没有,则返回 -1
	要求:
		用最快的速度来完成匹配
你的思路?
	1.如果你没有学过 kmp 算法 你一定是 
	暴力匹配 即:
		happy 匹配 str1 如果总的str2 匹配不上 就从头继续 匹配  这是最简单的实现
    这样 需要很多次回头从新匹配 很慢!!

 如果你会 
 KMP算法:
 	会用一个 部分匹配表  进行匹配   效率将提升!!

数据结构

数据结构:
	线性结构 和 非线性结构

线性结构:
	1.数据元素之间存在一对一的线性关系
	2.存储结构:
		顺序存储结构
		链式存储结构

		顺序存储的线性表 -> 顺序表   元素是 连续的
		链式存储的线性表->链表   元素不一定是连续     存的是:元素+相邻元素的地址
  	3.有:
  		数组、队列、链表、栈
 非线性结构:
 	有:
 		二维数组、多维数组、广义表、树结构、图结构

稀疏数组和队列

编写五子棋程序中 有 存盘退出+续上盘的功能?

你如何实现!

棋盘:  11×11 大小
1.如下左面图  把棋盘保存 该如何做?

注意:
	二维数组 :
		1表示黑子
		2表示蓝子
	二维数组有很多默认值是0,记录很多没有意义的数据  
		 ---》建议使用 稀疏数组  对二维数组 进行 压缩

java数据结构与算法(稀疏数组、环形队列)01-Double_happy_第1张图片

稀疏数组:
	一个数组中元素 大部分是0 或者为 同一个值得数组 可以使用 稀疏数组 来保存该数组

1.记录数组 一共有几行几列  多少个不同的值
2.把不同值得元素 的  行列值 记录在一个小的数组中  这个小数组 就是 稀疏数组
案例:
	6×7 = 42个数据
下图:
	稀疏数组: 9×3 =27个数据
		第一行 : 有几行 有几列  几个非0的值
		其他行:记录非0的元素  所在的 行、列、值、

42-》27 数据压缩了!!!

java数据结构与算法(稀疏数组、环形队列)01-Double_happy_第2张图片

上面 棋盘的实现思路:

二维数组 转 稀疏数组的思路:

1. 遍历  原始的二维数组,得到有效数据的个数 sum
2. 根据sum 就可以创建 稀疏数组 sparseArr   int[sum + 1] [3]
3. 将二维数组的有效数据数据存入到 稀疏数组

稀疏数组转原始的二维数组的思路 :

1. 先读取稀疏数组的第一行,根据第一行的数据,创建原始的二维数组,比如上面的 
  chessArr2 = int [11][11]
2. 在读取稀疏数组后几行的数据,并赋给 原始的二维数组 即可.
java: 二维数组 转 稀疏数组
package datastructure;

public class SparseArrayApp {
    public static void main(String[] args) {

        /**
         *  11*11
         *   1 黑子
         *   2 篮子
         */
        System.out.println("-----二维数组 -> 稀疏数组-----");
        int[][] chessArrRaw = new int[11][11];
        chessArrRaw[1][2] =1;
        chessArrRaw[2][3] =2;

        System.out.println("原始的二维数组:");
        for (int[] row : chessArrRaw) {
            for (int data : row) {
                System.out.printf("%d\t",data);
            }
            System.out.println();
        }

        /**
         *  二维数组 -> 稀疏数组
         *  1.遍历二维数组 得到非0数据的个数
         */
        int count = 0;
        for (int i = 0; i < chessArrRaw.length; i++) {
            for (int j = 0; j < chessArrRaw.length; j++) {
                if (chessArrRaw[i][j] != 0) {
                    count++;
                }
            }
        }
        System.out.println("二维数组的非0元素的个数: count=" +count);

        //2.创建稀疏数组 赋值
        int[][] sparseArr = new int[count + 1][3];
        sparseArr[0][0]= chessArrRaw.length;
        sparseArr[0][1]= chessArrRaw.length;
        sparseArr[0][2]= count;

        int flag =0;//记录是 第几个非0 的数据
        for (int i = 0; i < chessArrRaw.length; i++) {
            for (int j = 0; j < chessArrRaw.length; j++) {
                if (chessArrRaw[i][j] != 0) {
                    flag++;
                    sparseArr[flag][0] =i;  //行
                    sparseArr[flag][1] =j;  //列
                    sparseArr[flag][2] =chessArrRaw[i][j]; //值本身
                }
            }
        }

        //输出稀疏数组
        System.out.println("稀疏表为:");
        for (int i = 0; i < sparseArr.length; i++) {
            System.out.printf("%d\t%d\t%d\t\n",sparseArr[i][0],sparseArr[i][1],sparseArr[i][2]);
        }


        /**
         * 稀疏数组 -> 二维数组
         */
        System.out.println();
        System.out.println("-----稀疏数组 -> 二维数组-----");
        int[][] chessArrRes = new int[sparseArr[0][0]][sparseArr[0][1]];

        // 从稀疏数组的第二行开始 取值 并赋值给二维数组
        for (int i = 1; i 
结果:
-----二维数组 -> 稀疏数组-----
原始的二维数组:
0	0	0	0	0	0	0	0	0	0	0	
0	0	1	0	0	0	0	0	0	0	0	
0	0	0	2	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
二维数组的非0元素的个数: count=2
稀疏表为:
11	11	2	
1	2	1	
2	3	2	

-----稀疏数组 -> 二维数组-----
恢复的二维数组:
0	0	0	0	0	0	0	0	0	0	0	
0	0	1	0	0	0	0	0	0	0	0	
0	0	0	2	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0
scala 代码:  二维数组 转 稀疏数组
里面我添加了 scala 遍历的高级写法 
package com.datastructure

object SparseArrayApp {

  def main(args: Array[String]): Unit = {

    println("----二维数组 -> 稀疏数组----")
    println()
    val chessArrRaw: Array[Array[Int]] = Array.ofDim[Int](11,11)
    chessArrRaw(1)(2)=1
    chessArrRaw(2)(3)=2

    println("原始的二维数组: ")
    for(row <- chessArrRaw) {
      for(data <- row) {
        printf("%d\t",data)
      }
      println()
    }

 /*   println("原始的二维数组: ")
    chessArrRaw.init.map(row =>{
      row.indices.map(i=>printf("%d\t",row(i)))
      println()
    })*/

    //二维数组-> 稀疏数组
    var count =0
    for(i <- 0 until  chessArrRaw.size) {
      for(j <- 0 until chessArrRaw.size) {
        if(chessArrRaw(i)(j) != 0){
          count = count +1
        }
      }
    }
    println(s"二维 数组非0元素个数: Count=${count}")

    val sparseArr = Array.ofDim[Int](count+1,3)
    sparseArr(0)(0)=chessArrRaw.length
    sparseArr(0)(1)=chessArrRaw.length
    sparseArr(0)(2)=count

    var flag = 0
    for(i <- 0 until  chessArrRaw.size) {
      for(j <- 0 until chessArrRaw.size) {
        if(chessArrRaw(i)(j) != 0){
          flag = flag+1
          sparseArr(flag)(0)=i
          sparseArr(flag)(1)=j
          sparseArr(flag)(2)=chessArrRaw(i)(j)
        }
      }
    }


    //输出 稀疏数组
    println("稀疏表为:")
    for(i<- 0 until sparseArr.length) {
      printf("%d\t%d\t%d\t\n",sparseArr(i)(0),sparseArr(i)(1),sparseArr(i)(2))
    }

/*    sparseArr.indices.map(i => {
      printf("%d\t%d\t%d\t\n",sparseArr(i)(0),sparseArr(i)(1),sparseArr(i)(2))
    })*/


    /**
      * 稀疏数组 -> 二维数组
      */

    println()
    println("----稀疏数组 -> 二维数组----")
    val chessRes = Array.ofDim[Int](sparseArr(0)(0),sparseArr(0)(1))
    sparseArr.indices.filter( i => i!=0).map(i=>{
      chessRes(sparseArr(i)(0))(sparseArr(i)(1)) = sparseArr(i)(2)
    })

    //遍历
    chessRes.init.map(row =>{
      row.indices.map(i=>printf("%d\t",row(i)))
      println()
    })

  }

}


结果:
----二维数组 -> 稀疏数组----

原始的二维数组: 
0	0	0	0	0	0	0	0	0	0	0	
0	0	1	0	0	0	0	0	0	0	0	
0	0	0	2	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
二维 数组非0元素个数: Count=2
稀疏表为:
11	11	2	
1	2	1	
2	3	2	

----稀疏数组 -> 二维数组----
0	0	0	0	0	0	0	0	0	0	0	
0	0	1	0	0	0	0	0	0	0	0	
0	0	0	2	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	

稀疏数组总结:
 1.这个技巧 节省空间 提升效率

队列

特点:
	先进先出(先存入队列的数据 要先取出)
	eg:使用场景 
		银行排队 叫号系统

1.队列是一个有序列表   可以用数组 或者 链表来实现
数组:=》 顺序存储
链表:=>链式存储
使用数组模拟环形队列:
	1.队列:
		  front:表示队列的头部
		  rear:表示队列的尾部   
    2.第二个图:表示当 有数据 添加进来的时候 
       front 不变
       rear 位置增加
     3.第三个图:
     	   表示从  队列 取数据的情况
         是从 front 开始取出
    注意:
    	加数据 -> rear
    	取数据 -> front

java数据结构与算法(稀疏数组、环形队列)01-Double_happy_第3张图片
队列的实现方式

数组模拟队列:

java:

package datastructure;

import java.util.Scanner;

public class ArrayQueueApp {

    public static void main(String[] args) {

        ArrayQueue queue = new ArrayQueue(3);
        char insert = ' ';//接受 用户的输入

        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): 队列头");
            System.out.println("l(show): 列出队列数据");

            insert = scanner.next().charAt(0);

            switch (insert) {
                case 's':
                    queue.showQueue();
                    break;
                case 'e':
                    scanner.close();
                    loop=false;
                    break;
                case 'a':
                    System.out.println("输入一个数:");
                    int value = scanner.nextInt();
                    queue.addQueue(value);
                    System.out.println("添加完成");
                    break;
                case 'g':
                    try {
                        System.out.printf("取出的数据是%d\n", queue.getQueue());
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'h':
                    try {
                        System.out.printf("queue head 数据是%d\n", queue.headQueue());
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'l':
                    queue.showQueue();
                default:
                    break;
            }
        }

        System.out.println("---程序退出---");

    }
}

//
class ArrayQueue{
    private  int maxSize;
    private int front;
    private int rear;
    private int[] data; //用于存放数据 模拟队列

    public ArrayQueue(int arrMaxSize) {
        this.maxSize = arrMaxSize;
        this.data = new int[maxSize];
        this.front =-1; //指向队列头部 的前一个位置
        this.rear = -1;// 指向队列尾部 指向队列尾部的 具体的位置
    }

    public boolean isFull(){
        return  rear == maxSize -1 ;
    }

    public boolean isEmpty(){
        return  rear == front;
    }

    public void  addQueue(int num){
        if(isFull()){
            System.out.println("队列已经满了,不能添加数据");
            return;
        }

        rear++; //rear 后移
        data[rear] = num;
    }

    public int getQueue(){
        if(isEmpty()){
            System.out.println("队列是空的");
            throw new RuntimeException("队列是空的");
        }

        front++; //后移 front
         return  data[front];
    }

    public void showQueue(){
        if(isEmpty()){
            System.out.println("队列是空的");
            return;
        }
        for (int i = 0; i < data.length; i++) {
            System.out.printf("data[%d]=%d\n",i,data[i]);
        }
    }

    public int headQueue(){
        if (isEmpty()){
            System.out.println("队列是空的");
            throw new RuntimeException("队列是空的");
        }

        return data[front + 1];
    }

}
结果:

s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
s
队列是空的
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
a
输入一个数:
10
添加完成
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
a
输入一个数:
20
添加完成
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
a
输入一个数:
30
添加完成
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
s
data[0]=10
data[1]=20
data[2]=30
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
h
queue head 数据是10
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
g
取出的数据是10
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
s
data[0]=10
data[1]=20
data[2]=30
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
h
queue head 数据是20
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
l
data[0]=10
data[1]=20
data[2]=30
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据

scala:
package com.datastructure

import java.util.Scanner

object ArrayQueueApp {

  def main(args: Array[String]): Unit = {

    val queue = new ArrayQueue(3)
    var insert:Char = ' '
    var loop = true

    val scanner = new Scanner(System.in)

    while (loop){
      println("s(show): 显示队列")
      println("e(exit): 退出程序")
      println("a(add): 添加数据到队列")
      println("g(get): 从队列取出数据")
      println("h(head): 队列头")
      println("l(show): 列出队列数据")

      insert = scanner.next().charAt(0)

      insert match {
        case 's' => queue.showQueue()
        case 'e' =>{
          scanner.close()
          loop = false
        }
        case 'a' =>{
          println("输入一个数:")
          val value = scanner.nextInt
          queue.addQueue(value)
          println("添加完成")
        }
        case 'g' =>
          try
            printf("取出的数据是%d\n", queue.getQueue)
          catch {
            case e: Exception =>
              println(e.getMessage)
          }
        case 'h' =>
          try
            printf("queue head 数据是%d\n", queue.headQueue)
          catch {
            case e: Exception =>
              println(e.getMessage)
          }

        case 'l' =>
          queue.showQueue()
        case _ =>
      }
    }

    println("---程序退出---")
  }

}

class ArrayQueue{
  private var maxSize:Int =_
  private var front:Int =_
  private var rear:Int =_
  private var data:Array[Int] =_

  def this(arrMaxSize:Int){
    this()
    this.maxSize = arrMaxSize
    data = Array.ofDim[Int](maxSize)
    front = -1
    rear = -1
  }

  def isFull()={
    rear == maxSize -1
  }

  def isEmpty()={
    rear == front
  }

  def addQueue(num : Int)={
    if(isFull()){
      println("队列是满的 不能添加")
    }

    rear = rear +1
    data(rear) = num
  }

  def getQueue() ={
    if(isEmpty()){
      throw new RuntimeException("队列是空的")
    }

    front = front +1
    data(front)
  }

  def showQueue() : Unit={
    if(isEmpty()){
      println("队列是空的")
      return
    }

    data.indices.map(i =>{
      printf("data[%d]=%d\n",i,data(i))
    })
  }

  def headQueue()={
    if(isEmpty()){
      throw  new RuntimeException("队列是空的")
    }
    data(front + 1)
  }


}

结果:
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
s
队列是空的
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
a
输入一个数:
10
添加完成
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
a
输入一个数:
20
添加完成
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
a
输入一个数:
30
添加完成
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
s
data[0]=10
data[1]=20
data[2]=30
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
g
取出的数据是10
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
g
取出的数据是20
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
g
取出的数据是30
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
s
队列是空的
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
a
输入一个数:
10
队列是满的 不能添加
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
	at com.datastructure.ArrayQueue.addQueue(ArrayQueueApp.scala:91)
	at com.datastructure.ArrayQueueApp$.main(ArrayQueueApp.scala:34)
	at com.datastructure.ArrayQueueApp.main(ArrayQueueApp.scala)
注意:
数组模拟队列:
	从上面的结果看 有一个很大的问题:
	1. 取出的数据 0 1 位置的 之后 0 1 这两个位置就用不了
	2.  满了之后 再添加 添加不进去  
	3. 你的这个数组 只用了 一次 !!
	
当然你会觉得是代码问题!!   没有做成环形的队列! 

数组模拟队列 ->做成 环形队列 是需要算法的

java数据结构与算法(稀疏数组、环形队列)01-Double_happy_第4张图片

优化:
	把  数组 取出的 空间能够复用
	因为之前 取出之后 之前的空间存的数据 就是无效数据了

环形队列:
思路如下:
1.  front 变量的含义做一个调整: 
  front 就指向队列的第一个元素, 也就是说 arr[front] 就是队列的第一个元素 
    front 的初始值 = 0
2.  rear 变量的含义做一个调整:
   rear 指向队列的最后一个元素的后一个位置. 因为希望空出一个空间做为约定.
    rear 的初始值 = 0
3. 当队列满时,条件是  (rear  + 1) % maxSize == front 【满】
          3这个 很好理解:
          		rear +1 就是 约定 最后一个元素+1 如果等于 maxsize  
          		front 不动 为0的时候   ,就是队列 一个数也没有取出
                取模之后 就是等于 front
                一定要注意:
                	rear 指向队列的最后一个元素的后一个位置
                	这是一个环形队列 

4. 对队列为空的条件, rear == front 空

5. 当我们这样分析, 队列中有效的数据的个数  
   (rear + maxSize - front) % maxSize   // rear = 1 front = 0 
   
我们就可以在原来的队列上修改得到,一个环形队列

java数据结构与算法(稀疏数组、环形队列)01-Double_happy_第5张图片

 java:
 package datastructure;

import java.util.Scanner;

public class CircleArrayQueueApp {

    public static void main(String[] args) {

        CircleArrayQueue queue = new CircleArrayQueue(3);
        char insert = ' ';//接受 用户的输入

        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): 队列头");
            System.out.println("l(show): 列出队列数据");

            insert = scanner.next().charAt(0);

            switch (insert) {
                case 's':
                    queue.showQueue();
                    break;
                case 'e':
                    scanner.close();
                    loop=false;
                    break;
                case 'a':
                    System.out.println("输入一个数:");
                    int value = scanner.nextInt();
                    queue.addQueue(value);
                    System.out.println("添加完成");
                    break;
                case 'g':
                    try {
                        System.out.printf("取出的数据是%d\n", queue.getQueue());
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'h':
                    try {
                        System.out.printf("queue head 数据是%d\n", queue.headQueue());
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'l':
                    queue.showQueue();
                default:
                    break;
            }
        }

        System.out.println("---程序退出---");

    }
}

//
class CircleArrayQueue {
    private  int maxSize;
    private int front;
    private int rear;
    private int[] data; //用于存放数据 模拟队列

    public CircleArrayQueue(int arrMaxSize) {
        this.maxSize = arrMaxSize;
        this.data = new int[maxSize];
        this.front =0;
        this.rear = 0;
    }

    public boolean isFull(){

        return  (rear +1)% maxSize == front ;
    }

    public boolean isEmpty(){
        return  rear == front;
    }

    public void  addQueue(int num){
        if(isFull()){
            System.out.println("队列已经满了,不能添加数据");
            return;
        }

        data[rear] = num;
        //将rear后移 必须考虑取模 因为 取模是为了 消除无效的数据
        rear = (rear+1) % maxSize;
    }

    public int getQueue(){
        if(isEmpty()){
            System.out.println("队列是空的");
            throw new RuntimeException("队列是空的");
        }

        //分析 是指向 队列的第一个元素    取出 再后移嘛
        int value = data[front];
        front = (front +1 ) % maxSize;
         return  value;
    }

    public void showQueue(){
        if(isEmpty()){
            System.out.println("队列是空的");
            return;
        }
        //从 front 开始遍历 遍历多少个元素
        for (int i = front; i < front + size(); i++) {
            System.out.printf("data[%d]=%d\n",i % maxSize,data[i % maxSize]);
        }
    }


    //当前有效数据的个数
    public int size(){
        return (rear+maxSize -front) % maxSize;
    }

    public int headQueue(){
        if (isEmpty()){
            System.out.println("队列是空的");
            throw new RuntimeException("队列是空的");
        }

        return data[front];
    }

}
scala:
package com.datastructure

import java.util.Scanner

object CircleArrayQueueApp {

  def main(args: Array[String]): Unit = {

    val queue = new CirleArrayQueue(3)
    var insert:Char = ' '
    var loop = true

    val scanner = new Scanner(System.in)

    while (loop){
      println("s(show): 显示队列")
      println("e(exit): 退出程序")
      println("a(add): 添加数据到队列")
      println("g(get): 从队列取出数据")
      println("h(head): 队列头")
      println("l(show): 列出队列数据")

      insert = scanner.next().charAt(0)

      insert match {
        case 's' => queue.showQueue()
        case 'e' =>{
          scanner.close()
          loop = false
        }
        case 'a' =>{
          println("输入一个数:")
          val value = scanner.nextInt
          queue.addQueue(value)
          println("添加完成")
        }
        case 'g' =>
          try
            printf("取出的数据是%d\n", queue.getQueue)
          catch {
            case e: Exception =>
              println(e.getMessage)
          }
        case 'h' =>
          try
            printf("queue head 数据是%d\n", queue.headQueue)
          catch {
            case e: Exception =>
              println(e.getMessage)
          }

        case 'l' =>
          queue.showQueue()
        case _ =>
      }
    }

    println("---程序退出---")
  }

}

class CirleArrayQueue{
  private var maxSize:Int =_
  private var front:Int =_
  private var rear:Int =_
  private var data:Array[Int] =_

  def this(arrMaxSize:Int){
    this()
    this.maxSize = arrMaxSize
    data = Array.ofDim[Int](maxSize)
    front = 0
    rear = 0
  }

  def isFull()={
    (rear +1)%maxSize == front
  }

  def isEmpty()={
    rear == front
  }

  def addQueue(num : Int) :Unit={
    if(isFull()){
      System.out.println("队列已经满了,不能添加数据")
      return
    }
    data(rear) = num
    rear = (rear +1) % maxSize
  }

  def getQueue() ={
    if(isEmpty()){
      throw new RuntimeException("队列是空的")
    }

    val value = data(front)
    front = (front +1) % maxSize
    value
  }

  def showQueue() : Unit={
    if(isEmpty()){
      println("队列是空的")
      return
    }

    for(i <- front until front+size() ){
      printf("data[%d]=%d\n",i % maxSize,data(i % maxSize))
    }
  }

  def size()={
    (rear +maxSize -front) % maxSize
  }

  def headQueue()={
    if(isEmpty()){
      throw  new RuntimeException("队列是空的")
    }
    data(front)
  }


}

结果:
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
a
输入一个数:
10
添加完成
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
a
输入一个数:
20
添加完成
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
a
输入一个数:
30
队列已经满了,不能添加数据
添加完成
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
s
data[0]=10
data[1]=20
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
g
取出的数据是10
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
g
取出的数据是20
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
s
队列是空的
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
a
输入一个数:
20
添加完成
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
s
data[2]=20
s(show): 显示队列
e(exit): 退出程序
a(add): 添加数据到队列
g(get): 从队列取出数据
h(head): 队列头
l(show): 列出队列数据
总结:
 环形队列:
 	1. rear 和 front 后移的时候 要考虑 取模!!! 、
 	   即:
 	   	front = (front +1 ) % maxSize
 	 2. 有效数据的个数
 	   (rear+maxSize -front) % maxSize
 	 3. 取值
 	     直接取值即可 
 	        data(front) = 》 头
 	        data(reat) =》 就是 尾部 
 	        添加的时候 要后移!!! 这根代码有关 
 	  4.遍历 队列
 	       从 front 开始遍历 遍历多少个元素:
 	       	 1.当前有效数据的个数
 	       	 	(rear+maxSize -front) % maxSize    = size()
 	       	 2.front + size()  就是 从front开始遍历 的结尾
 	       	 3.  
 	       	    //从 front 开始遍历 遍历多少个元素
		        for (int i = front; i < front + size(); i++) {
		            System.out.printf("data[%d]=%d\n",i % maxSize,data[i % maxSize]);
		        }
           
            下标:
            	i % maxSize     记得是要考虑取模的
        5.约定预留 要注意!!
      

你可能感兴趣的:(java)