1、线性表
线性表是有限个相同元素有顺序地排列的集合。
实现方式通常分为顺序表实现和链表实现。
Java中的线性表有:
Vector、ArrayList :顺序表实现。
LinkedList :双向链表实现。
1、顺序表(数组)实现线性表
直接分配一块连续的内存存储数据。比如数组,就是一个天然的顺序表。
优点:
是空间利用率高,通过索引查找元素快。
缺点:
不确定需要存储的元素个数,可能会浪费空间,插入元素,删除元素效率不高(除了在结尾操作)。
例子:
import java.util.Arrays; /** * 顺序表实现线性表结构 * @author lurenjia * @date 2022/12/6-16:08 */ public class Mylist { //储存数据的数组 private Object[] elementData; //元素个数 private int size; /** * 无参构造,创建一个大小为4的数组 */ public Mylist() { elementData = new Object[4]; } /** * 指定位置插入元素 * @param index 索引 * @param o 元素 */ public void add(int index,Object o){ if(size==elementData.length){ //元素个数等于数组长度时,扩容为原数组长的1.5倍 elementData = Arrays.copyOf(elementData,elementData.length+(elementData.length>>1)); } if(size!=0) { //1、第index个元素之后的元素都往后移一位 System.arraycopy(elementData, index, elementData, index + 1, size - index); //2、改变第index个元素的值 elementData[index] = o; }else { elementData[index]=o; } size++; } /** * 加入元素在最后 * @param o 元素 */ public void add(Object o){ add(size,o); } /** * 通过索引获得元素 * @param index 索引 * @return 元素 */ public Object get(int index){ return elementData[index]; } /** * 在容器中查找指定的元素,若存在则返回它第一次出现的位置,若不存在返回-1. * @param o 要查找的元素 * @return 位置或-1 */ public int contains(Object o){ for(int i=0;i<elementData.length;i++){ if(elementData[i]==o){ return i; } } return -1; } /** * 获取容器大小 * @return 容器大小 */ public int size() { return size; } @Override public String toString() { return "Mylist{" + "elementData=" + Arrays.toString(elementData) + ", size=" + size + '}'; } }
2、单链表实现线性表
节点中分为两个空间,一个存放数据,一个存放下一个节点的地址。
优点:
插入元素,删除元素效率高,不会有空闲的空间。
缺点:
查找元素效率低。
例子:
package lurenjia.test; /** * 单链表实现线性表结构 * @author lurenjia * @date 2022/12/6-16:24 */ public class MyLink { //头节点,不放内容 private MyNode first = new MyNode(); //容器大小 private int size; /** * 在指定的位置插入元素 * @param i 位置 * @param obj 插入的元素 */ public void add(int i,Object obj){ //1、获取前驱 MyNode temp = getNode(i); //2、创建新节点 MyNode newNode = new MyNode(); newNode.setData(obj); //3、新节点的后继指向前驱的后继 newNode.setNextNode(temp.getNextNode()); //4、前驱的后继指向新节点 temp.setNextNode(newNode); size++; } /** * 在结尾加入元素 * @param obj 元素 */ public void add(Object obj){ add(size,obj); } /** * 通过索引获取元素 * @param index * @return */ public Object get(int index){ MyNode tempNode = getNode(index); return tempNode.getData(); } /** * 通过索引获取节点 * @param index * @return */ private MyNode getNode(int index){ if(index>size){ throw new RuntimeException("索引越界"+index); }else { //1.获取头节点 MyNode tempNode = first; for(int i =0;i<index;i++){ //2.循环找到目标节点 tempNode=tempNode.getNextNode(); } return tempNode; } } /** * 获取容器大小 * @return */ public int size() { return size; } }