一、数据结构
1、数据结构的定义
数据结构是计算机存储,组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。通常情况下,精心选择的数据结构可以带来更高的运行或存储效率。数据结构往往同高效的检索算法和索引技术有关。(来源于百度百科)
2、存储数据的方式
1、变量
变量声明格式: 数据类型 变量名
示例:int age
变量赋值:int age = 22;
注意事项:
- 需要注意值和类型的匹配问题。
- 在使用局部变量之前必须要赋值。
- 成员变量有默认值,但都没有多大意义,在做项目时,要给它赋值。
变量的特点:只能存放一个值。
2、数组
数组的声明格式:数组中元素的类型[] 数组名
示例:int[] ages = new int[3];
数组特点:长度固定,只能存储同种类型数据。
3、自定义类存储
自定义一个可以自动增长,可以存储任意多个 int 元素的数据结构。
实现步骤:
1、自定义一个容器类 intArray。
2、先做到可以储存多个 int 值,内部使用 int 数组。
3、类中创建一个 int 数组,当 int 数组满了之后,创建一个新的数组,并把老的数组中的值拷贝到新的数组中(实现自动扩容)。
具体代码实现:
1 import java.util.Arrays; 2 3 /** 4 * 自定义可以自动扩容的数组 5 */ 6 public class IntArray { 7 private int[] data; 8 private int index = 0; 9 10 //构造方法,初始化大小为2 11 public IntArray() { 12 this.data = new int[2]; 13 } 14 15 /** 16 * 添加数据,自动扩容 17 * add添加数据的函数 18 * 19 * @param i 20 */ 21 public void add(int i) { 22 if (index >= data.length) { 23 //如果索引大于数组长度,需要新建数组 24 int[] dataNew = new int[data.length + 2]; 25 System.arraycopy(data, 0, dataNew, 0, data.length); //拷贝数据 26 data = dataNew; 27 data[index] = i; //存值 28 index += 1; 29 } else { 30 //如果索引小于数组长度,直接存值 31 data[index] = i; 32 index += 1; 33 } 34 } 35 36 /** 37 * 通过索引删除数据 38 * 39 * @param indexId 40 */ 41 public void del(int indexId) { 42 int length = data.length; 43 System.arraycopy(data, indexId + 1, data, indexId, length - indexId - 1); 44 } 45 46 /** 47 * 通过索引查找元素 48 * 49 * @param indexId 50 */ 51 public int select(int indexId) { 52 return data[indexId]; 53 } 54 55 /** 56 * 通过索引修改数据 57 * 58 * @param indexId 59 * @param value 60 */ 61 public void update(int indexId, int value) { 62 data[indexId] = value; 63 } 64 65 /** 66 * 返回当前数组长度 67 * 68 * @return 69 */ 70 public int getLength() { 71 return data.length; 72 } 73 74 /** 75 * 查找第一个相同元素的索引 76 * 77 * @param value 78 * @return 79 */ 80 public Integer queryByValue(int value) { 81 Integer result = null; 82 for (int i = 0; i < data.length; i++) { 83 if (data[i] == value) { 84 result = i; 85 } 86 } 87 return result; 88 } 89 90 //覆写toString方法 91 @Override 92 public String toString() { 93 // TODO Auto-generated method stub 94 //把元素数组的值,拷贝到新数组里面 95 int[] newArr = new int[index]; 96 System.arraycopy(data, 0, newArr, 0, index); 97 return Arrays.toString(newArr); 98 } 99 }
测试自定义扩容的数组:
1 public class TestIntArray { 2 /** 3 * 测试自定义的扩容数组 4 */ 5 @Test 6 public void test2(){ 7 IntArray intArray = new IntArray(); 8 9 intArray.add(11); 10 intArray.add(22); 11 intArray.add(33); 12 intArray.add(44); 13 intArray.add(55); 14 //根据索引删除 15 intArray.del(2); 16 int select = intArray.select(1); 17 System.out.println(select); 18 //更新 19 intArray.update(1, 2333); 20 int select1 = intArray.select(1); 21 System.out.println(select1); 22 //通过值查询第一个索引 23 Integer index = intArray.queryByValue(55); 24 System.out.println("index: " + index); 25 //返回数组长度 26 int length = intArray.getLength(); 27 System.out.println("length: " + length); 28 System.out.println(intArray); 29 } 30 }
二、链表
1、链表定义
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。
使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的存取往往要在不同的排列顺序中转换。链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向链表,双向链表以及循环链表。(来源于百度百科)
2、基于类实现链表
1、实现步骤
1、定义容器类。
2、定义Node(口袋类),类里面定义两个字段,一个Object类型存放值,一个Node类型字段,存放下一个值。
3、在容器里面有个字段,在容器类里面还应该提供添加、查找、删除方法。
自定义Node类的代码:
1 /** 2 * 自定义Node类 3 */ 4 public class Node { 5 // 存放值 6 private Object value; 7 //存放下一个值 8 private Node next; 9 10 public Node() { 11 12 } 13 14 public Node(Object value) { 15 this.value = value; 16 } 17 18 public Object getValue() { 19 return value; 20 } 21 22 public void setValue(Object value) { 23 this.value = value; 24 } 25 26 public Node getNext() { 27 return next; 28 } 29 30 public void setNext(Node next) { 31 this.next = next; 32 } 33 }
具体实现链表代码:
1 /** 2 * 实现链表 3 */ 4 public class LinkList { 5 private Node first; 6 private int size; //链表大小,默认值为0 7 8 /** 9 * 添加节点的方法 10 * 11 * @param obj 12 */ 13 public void add(Object obj) { 14 //1、把用户传入的数据打包 15 Node node = new Node(obj); 16 17 //2、把打包好的数据挂在first上面 18 if (first == null) { 19 //如果是第一次添加,直接挂在first上面 20 first = node; 21 } else { 22 Node temp = first; 23 //不是第一次添加,寻找最后一个节点,挂在上面 24 while (temp.getNext() != null) { 25 temp = temp.getNext(); 26 } 27 temp.setNext(node); 28 } 29 size++; 30 } 31 32 public Node getFirst() { 33 return first; 34 } 35 36 public void setFirst(Node first) { 37 this.first = first; 38 } 39 40 public int getSize() { 41 return size; 42 } 43 44 public void setSize(int size) { 45 this.size = size; 46 } 47 48 //覆写toString方法 49 @Override 50 public String toString() { 51 StringBuffer stringBuffer = new StringBuffer(); 52 stringBuffer.append("["); 53 Node temp = first; //使用一个临时变量存储 54 if (temp != null) { 55 //当为第一个元素的时候 56 if (temp.getNext() == null) { 57 //没有下一个节点 58 stringBuffer.append(temp.getValue()); 59 } else { 60 stringBuffer.append(temp.getValue()).append(","); 61 } 62 } 63 64 while (temp.getNext() != null) { 65 //指针向下移动一个位置 66 temp = temp.getNext(); 67 if (temp.getNext() == null) { 68 //最后一个节点 69 stringBuffer.append(temp.getValue()); 70 } else { 71 stringBuffer.append(temp.getValue()).append(","); 72 } 73 } 74 stringBuffer.append("]"); 75 return stringBuffer.toString(); 76 } 77 }
测试链表:
1 import org.junit.Test; 2 3 public class TestLink { 4 5 /** 6 * 测试链表 7 */ 8 @Test 9 public void testLink() { 10 LinkList linkList = new LinkList(); 11 12 linkList.add(11); 13 linkList.add(22); 14 linkList.add(33); 15 linkList.add(44); 16 linkList.add(55); 17 linkList.add(66); 18 int size = linkList.getSize(); 19 System.out.println("size: " + size); //size: 6 20 System.out.println(linkList); //[11,22,33,44,55,66] 21 } 22 }