算法(一)(稀疏数组、队列、环形队列)

算法(一)(稀疏数组、队列、环形队列),第1张

算法(一)(稀疏数组队列、环形队列)

kmp算法<部分匹配表>
汉罗塔

线性 栈 队列 列表
非线性 图 树

数据结构(data structrue)
程序 = 数据结构 + 算法

约瑟夫问题

单链表
单向环形链表
稀疏数组

修路问题 -》最小生成树(加权值)【数据结构】 + 普利姆算法
最短路径问题 -》 图+弗洛伊德算法
汉罗塔 -》 分治算法
八皇后问题 -》 回溯法

数据结构(datastructrue)

线性结构 和 非线性结构

1、线性结果作为最常用的数据结构,其特点是数据元素之间存在一对一的线性关系
2、 线性结构有两种不同的存储结构,即顺序存储结构和链式存储结构。顺序存储的线性表称为顺序表,顺序表中的存储元素是连续的
3、 链式存储的线性表称为链表,链表中的存储元素不一定是连续的,元素节点中存放元素以及相邻元素的地址信息
链式结构可以很好的用到碎片内存
4、 线性结构常见的有:数组、队列、链表和栈,

非线性结构:二维数组、多维数组、广义表、树结构、图结构

稀疏数组 和 队列


第一行 分别代表 一共有多少行 一共有多少列 一共有多少非0数据
只存有必要的数据
稀疏数组转变多维数组的存储格式 如上图把6*7的数组转化成了3*9的数组
二维数组转稀疏数组的思路
1、遍历 原始的二维数组,得到有效数据的个数 sum
2、根据sum就可以创建 稀疏数组 sparseArr int[sum+1][3]
3、将二维数组的有效数据存入到稀疏数组
稀疏数组转原始二维数组的思路
1、先读取读取稀疏数组的第一行,根据第一行的数据,创建原始的二维数组,比如上面的原始数组 chessArr2 = int[11][11]
2、再读取稀疏数组后几行的数组,并赋给原始的二维数组即可


代码案例
这里把生成的稀疏数组存到文件里面 这里用Integer包装类方便数字和字符串的转化
然后再取出来,因为java我不是专业的写的可能很丑,逻辑是这样的

package com.company;

public class Main {
    //    read
    public static void main(String[] args) {
        Integer[][] arr = new Integer[11][11];
        for (Integer i = 0; i < arr.length; i++) {
            for (Integer j = 0; j < arr[i].length; j++) {
                arr[i][j] = 0;
            }
        }
        arr[1][2] = 1;
        arr[2][3] = 2;
        arr[3][3] = 2;
        for (Integer[] row : arr) {
            for (Integer col : row) {
                System.out.printf("%dt", col);
            }
            System.out.println();
        }
        int sum = 0;
        for (Integer i = 0; i < arr.length; i++) {
            for (Integer j = 0; j < arr[i].length; j++) {
                if (arr[i][j] != 0) {
                    sum++;
                }
            }
        }
        System.out.println(sum);
//        创建一个对应的稀疏稀疏数组
        Integer[][] sparseArr = setSparseArr(sum, arr);
        write.writeArray(sparseArr);
        for (Integer[] row : sparseArr) {
            for (Integer col : row) {
                System.out.printf("%dt", col);
            }
            System.out.println();
        }
        System.out.println("---------");
        Integer[][] oldArray = reSparseArr(write.readArray(sparseArr));
        for (Integer[] row : oldArray) {
            for (Integer col : row) {
                System.out.printf("%dt", col);
            }
            System.out.println();
        }
    }

    //    从稀疏数组回复原数组
    private static Integer[][] reSparseArr(Integer[][] sparseArr) {
        Integer[][] array = new Integer[sparseArr[0][0]][sparseArr[0][1]];
        for (Integer i = 0; i < array.length; i++) {
            for (Integer j = 0; j < array[i].length; j++) {
                array[i][j] = 0;
            }
        }
        for (Integer i = 1; i < sparseArr.length; i++) {
            array[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
        }
        return array;
    }
    //    原数组转化位稀疏数组

    private static Integer[][] setSparseArr(int sum, Integer[][] array) {
        Integer[][] sparseArr = new Integer[sum + 1][3];
        int sparseArrIndex = 1;
        // 用于记录是第几个非零数据 0位内容已经固定所有从1开始
        sparseArr[0][0] = array.length;
        sparseArr[0][1] = array[0].length;
        sparseArr[0][2] = sum;
        for (Integer k = 0; k < array.length; k++) {
            for (Integer j = 0; j < array[k].length; j++) {
                if (array[k][j] != 0) {
                    sparseArr[sparseArrIndex][0] = k;
                    sparseArr[sparseArrIndex][1] = j;
                    sparseArr[sparseArrIndex][2] = array[k][j];
                    sparseArrIndex++;
                }
            }
        }
        return sparseArr;
    }
}

write.js
package com.company;

import java.io.*;


public class write {
    public static void writeArray(Integer[][] array) {
        try {
//            Integer bWrite[][] = array;

            OutputStream os = new FileOutputStream("test.txt");
            OutputStreamWriter writer = new OutputStreamWriter(os, "UTF-8");
            for (int x = 0; x < array.length; x++) {
                for (int y = 0; y < array[x].length; y++) {
                    for (int z = 0; z < array[x][y].toString().length(); z++) {
                        writer.append(array[x][y].toString().charAt(z));
                    }
                    writer.append("列");
                }
                writer.append("行");
                // writes the bytes
            }
            writer.close();
            os.close();
        } catch (IOException e) {
            System.out.print(e);
        }
    }

    public static Integer[][] readArray(Integer[][] array) {
        File f = new File("test.txt");
        Integer[][] oldArray = new Integer[0][];
        try {
            FileInputStream fip = new FileInputStream(f);
            // 构建FileInputStream对象

            InputStreamReader reader = new InputStreamReader(fip, "UTF-8");
            // 构建InputStreamReader对象,编码与写入相同

            StringBuffer sb = new StringBuffer();
            while (reader.ready()) {
                sb.append((char) reader.read());
                // 转成char加到StringBuffer对象中
            }
            System.out.println();
            reader.close();
            // 关闭读取流
            fip.close();
            String[] rowList = sb.toString().split("行");
            String[] colList;
            oldArray = new Integer[rowList.length][3];
            for (int i = 0; i < rowList.length; i++) {
                colList = rowList[i].split("列");
                for (int y = 0; y < colList.length; y++) {
//                    System.out.println(colList[y]);
                    oldArray[i][y] = Integer.valueOf(colList[y]);
                }
            }
        } catch (IOException e) {
            System.out.print(e);
        }
        return oldArray;

    }


}

test.txt
11列11列3列行1列2列1列行2列3列2列行3列3列2列行

队列
队列是一个有序列表,可以用数组或者链表来实现
遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取出

队列需要三个变量:最大容量、最前面的指针、最后面的指针
队列
package com.company;

import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        // write your code here
        ArrayQueue arrayQueue = new ArrayQueue(3);
        char key = '1'; // 接受用户输入
        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':
                    arrayQueue.showQueue();
                    break;
                case 'a':
                    System.out.println("请输入一个数组");
                    arrayQueue.addQueue(scanner.nextInt());
                    break;
                case 'g':
                    try {
                        System.out.printf("取出的数据是%d", arrayQueue.getQueue());
                    } catch (RuntimeException err) {
                        System.out.println(err.getMessage());
                    }
                    break;
                case 'h':
                    try {
                        System.out.printf("查看头数据是%d", arrayQueue.headQueue());
                    } catch (RuntimeException err) {
                        System.out.println(err.getMessage());
                    }
                    break;
                case 'e':
                    scanner.close();
                    loop = false;
                    break;
            }
        }
        System.out.println("程序结束");
    }
}

ArrayQueue.java
package com.company;
// 使用数组模拟队列-编写一个ArrayQueue类
public class ArrayQueue {
    private int maxSize;
//    表示数组最大容量
    private int front;
//    队列头
    private int rear;
//    队列尾
    private int[] arr;
//    该数据用于存储数据,模拟队列
// 创建队列的构造器
    public ArrayQueue(int arrMaxSize){
        maxSize = arrMaxSize;
        arr = new int[maxSize];
        front = -1; // 指向队列头部,分析出front时指向队列头的前一个位置
        rear = -1; // 指向队列尾,指向队列尾的数据(即就是队列最后一个数据)
    }
    public boolean isFull(){
        return maxSize - 1 == rear;
    }
    public boolean isEmpty(){
        return front == rear;
    }
    public void addQueue(int n){
        if(isFull()){
            System.out.println("队列已满");
            return;
        }
        rear ++; // 让rear后移
        arr[rear] = n;
    }
//    获取队列的数据,出队列
    public int getQueue(){
        if(isEmpty()){
//            通过抛出异常来处理
            throw new RuntimeException("队列为空");
        }
        front++; // 让front后移
        int queueData = arr[front];
//        rear--;
//        front --;
//        for (int i = 1; i < arr.length; i++) {
//                arr[i - 1] = arr[i];
//                if(i == arr.length - 1){
//                    arr[i] = 0;
//                }
//        }
        return queueData;
    }
    public void showQueue(){
        if (isEmpty()){
            System.out.println("队列空");
            return;
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.printf("arr[%d]=%dn",i,arr[i]);
        }
    }
    // 显示队列的头是谁,不是取出数据
    public int headQueue(){
        if (isEmpty()){
            throw new RuntimeException("队列为空");
        }
        return arr[front + 1];
    }
}

环形队列

环形队列示例代码
package com.company;


public class Queue {
    private int maxSize;
    private int front;
    private int rear;
    private int[] arr;
    //    rear = 0;
    //    front = 2;
    //    maxSize = 3;

    public Queue(int arrMaxSize) {
        front = 0;
        rear = 0;
        maxSize = arrMaxSize;
        arr = new int[maxSize];
    }

    // 0 + 3 - 3 % 3 ==
    public boolean isFull() {
        return size() + 1 == maxSize;
    }

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

    public void addQueue(int n) {
        if (isFull()) {
            System.out.println("队列满了");
            return;
        }
        arr[rear] = n;
        rear = (rear + 1) % maxSize;
    }

    public int getQueue() {
        if (isEmpty()) {
            throw new RuntimeException("队列为空,你取啥");
        }
        int value = arr[front];
        front = (front + 1) % maxSize;
        return value;
    }

    public void showQueue() {
        if (isEmpty()) {
            throw new RuntimeException("队列为空,没啥好展示的");
        }
        for (int i = front; i < front + size(); i++) {
            System.out.printf("打印第几位arr[%d]内容为%d", (i) % maxSize, arr[(i) % maxSize]);
            System.out.print("n");
        }
    }

    public int size() {
//        (0 - 2 + 3) % 3
//        (2 - 0 + 3) % 3
        return (rear - front + maxSize) % maxSize;
    }

    public int headQueue() {
        return arr[front];
    }
}

个人理解:我本来以为队列的先进先出后进后出,是当前一个数据出去之后,后面的数据会整体向前移动,然后把最后一位置空(就像在 ArrayQueue.java 我注释的那小段代码)
但是实际上是通过不断修改队列的起始位置和结束位置,不断的改变数组中的有效区域实现的代码中多次出现的%是为了让起始位置和结束位置超出数组的最大范围后从头开始,
创建一个4位的数组的话那么队列的最大容量就是(4-1),因为队列最大的结束位置是为数组的最后一位,所有要预留一位,不然无法判断队列在数据中的有效数据
结束位置是不包含队列元素的,起始位置有队列元素

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/4828670.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-10
下一篇 2022-11-10

发表评论

登录后才能评论

评论列表(0条)

保存