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),因为队列最大的结束位置是为数组的最后一位,所有要预留一位,不然无法判断队列在数据中的有效数据
结束位置是不包含队列元素的,起始位置有队列元素
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)