一、线性表
1、介绍
由零个或多个数据元素组成的有限序列,有序表。
数据类型:一组性质相同的值的集合及定义在此集合上的一些操作的总称。
2、顺序存储结构
顺序表:用一组地址连续的存储单元存放数据。
特点:具有随机存储结构的特点,时间复杂度为o(1)。存、读数据时,不管哪个位置,时间复杂度都是o(1);插入和删除的时间复杂度是o(n)。
优点:无需为表示元素之间的逻辑关系而增加额外的存储空间;可以快速的存取表中任意位置的元素。
缺点:插入和删除操作需要移动大量元素;当线性表长度变化较大时,难以确定存储空间的容量;容易造成存储空间的"碎片"。
常见结构:数组、栈。
3、链式存储结构
链表:由一个数据域和一个指向下一个元素地址的指针域构成。存放数据的地址不一定连续。链表又主要包括:单(向)链表,单(向)循环链表,双(向)链表,双(向)循环链表。
常见结构:链表、队列。
4、顺序表与链表区别
结论:若线性表需要频繁查找,很少进行插入和删除操作,采用顺序表;若需要频繁插入和删除,采用链表。
二、稀疏数组
1、介绍
2、二维数组、稀疏数组相互转化
代码示例:
1 public class SparseArray { 2 // 构建稀疏数组.二维数组 --> 稀疏数组 3 public int[][] createSparseArr(int[][] chess) { 4 final int sum = getCount(chess); 5 6 // 创建的稀疏数组 7 int[][] sparseArr = new int[sum + 1][3]; 8 sparseArr[0][0] = chess.length; 9 sparseArr[0][1] = chess[0].length; 10 sparseArr[0][2] = sum; 11 12 // count 用于记录是第几个非 0 数据 13 int count = 0; 14 for (int i = 0; i < chess.length; i++) { 15 for (int j = 0; j < chess[i].length; j++) { 16 if (chess[i][j] != 0) { 17 count++; 18 sparseArr[count][0] = i; 19 sparseArr[count][1] = j; 20 sparseArr[count][2] = chess[i][j]; 21 } 22 } 23 } 24 25 return sparseArr; 26 } 27 28 // 恢复稀疏数组.稀疏数组 --> 二维数组 29 public int[][] recover(int[][] sparseArr) { 30 int[][] chessArr = new int[sparseArr[0][0]][sparseArr[0][1]]; 31 for (int i = 1; i < sparseArr.length; i++) { 32 chessArr[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2]; 33 } 34 35 return chessArr; 36 } 37 38 // 遍历二维数组.得到非 0 数据的个数 39 private int getCount(int[][] chess) { 40 int sum = 0; 41 for (int[] ints : chess) { 42 for (int anInt : ints) { 43 if (anInt != 0) { 44 sum++; 45 } 46 } 47 } 48 49 return sum; 50 } 51 52 public void print(int[][] chess) { 53 for (int[] row : chess) { 54 for (int data : row) { 55 System.out.printf("%d\t", data); 56 } 57 System.out.println(); 58 } 59 System.out.println(); 60 } 61 62 }