线性表
线性表是最基本、最简单、也是最常用的一种数据结构。
线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的(注意,这句话只适用大部分线性表,而不是全部。比如,循环链表逻辑层次上也是一种线性表(存储层次上属于链式存储),但是把最后一个数据元素的尾指针指向了首位结点)。
我们说“线性”和“非线性”,只在逻辑层次上讨论,而不考虑存储层次,所以双向链表和循环链表依旧是线性表。
在数据结构逻辑层次上细分,线性表可分为一般线性表和受限线性表。一般线性表也就是我们通常所说的“线性表”,可以自由的删除或添加结点。受限线性表主要包括栈和队列,受限表示对结点的操作受限制。
线性表的逻辑结构简单,便于实现和操作。因此,线性表这种数据结构在实际应用中是广泛采用的一种数据结构。
线性表(linear list)是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列。数据元素是一个抽象的符号,其具体含义在不同的情况下一般不同。
在稍复杂的线性表中,一个数据元素可由多个数据项(item)组成,此种情况下常把数据元素称为记录(record),含有大量记录的线性表又称文件(file)。
线性表中的个数n定义为线性表的长度,n=0时称为空表。在非空表中每个数据元素都有一个确定的位置,如用ai表示数据元素,则i称为数据元素ai在线性表中的位序。
线性表的相邻元素之间存在着序偶关系。如用(a1,…,ai-1,ai,ai+1,…,an)表示一个顺序表,则表中ai-1领先于ai,ai领先于ai+1,称ai-1是ai的直接前驱元素,ai+1是ai的直接后继元素。当i=1,2,…,n-1时,ai有且仅有一个直接后继,当i=2,3,…,n时,ai有且仅有一个直接前驱。
线性表的基本操作,如果需要实现一个线性表,程序首先需要确定该线性表的每个数据元素。接下来,应为为线性表实现如下基本操作:
1.初始化
2.返回线性表的长度
3.获取指定索引处的元素
4.按值查找数据元素的位置
5.直接插入数据元素
6.向指定位置输入数据元素
7.直接删除数据元素
8.删除线性表中指定位置的数据元素
9.判断线性表是否为空
10.清空线性表
**** 顺序结构的线性表
1 import java.util.Arrays; 2 3 /** 4 * <p>实现一个顺序结构的线性表</p> 5 * @author:774346810@qq.com 6 * @date:2017-5-30 7 */ 8 public class SequenceList<T> { 9 private int DEFAULT_SIZE = 16; 10 //保存数组长度 11 private int capacity; 12 //定义一个数组用于保存顺序线性表的元素 13 private Object[] elementData; 14 //保存在顺序表中元素的当前个数 15 private int size = 0; 16 //以默认数组长度创建空顺序线性表 17 public SequenceList(){ 18 capacity = DEFAULT_SIZE; 19 elementData = new Object[capacity]; 20 } 21 //以一个初始化元素创建顺序线性表 22 public SequenceList(T element){ 23 this(); 24 elementData[0] = element; 25 size++; 26 } 27 /** 28 * 以指定长度的数组来创建顺序线性表 29 * @param element 指定顺序线性表中的第一个元素 30 * @param initSize 指定顺序线性表底层数组的长度 31 */ 32 public SequenceList(T element , int initSize){ 33 capacity = 1; 34 //把capacity设为大于initSize的最小的2的n次方 35 while(capacity < initSize){ 36 capacity = capacity << 1; 37 } 38 elementData = new Object[capacity]; 39 elementData[0] = elementData; 40 size++; 41 } 42 //获取顺序线性表的长度 43 public int size(){ 44 return size; 45 } 46 //获取顺序线性表中索引为i处的元素 47 @SuppressWarnings("unchecked") 48 public T get(int i){ 49 if(i < 0 || i > size - 1){ 50 throw new IndexOutOfBoundsException("线性表索引越界"); 51 } 52 return (T) elementData[i]; 53 } 54 //查找顺序线性表中指定元素的索引 55 public int locate(T element){ 56 for(int i = 0;i < elementData.length;i++){ 57 if(elementData[i].equals(element)){ 58 return i; 59 } 60 } 61 return -1; 62 } 63 //向顺序线性表的指定位置插入一个元素 64 public void insert(T element , int index){ 65 if(index < 0 || index > size - 1){ 66 throw new IndexOutOfBoundsException("线性表索引越界"); 67 } 68 ensureCapacity(size + 1); 69 //将指定索引处之后的所有元素向后移动一格 70 System.arraycopy(elementData, index, elementData, index+1, size - index); 71 elementData[index] = element; 72 size++; 73 } 74 //在线性顺序表的开始处添加一个元素 75 public void add(T element){ 76 insert(element, size); 77 } 78 //很麻烦,而且性能很差 79 private void ensureCapacity(int minCapacity) { 80 //如果数组的原有长度小于目前所需的长度 81 if(minCapacity > capacity){ 82 //不断地将capacity * 2,直到capacity大于minCapacity 83 while(capacity < minCapacity){ 84 capacity <<= 1; 85 } 86 elementData = Arrays.copyOf(elementData, capacity); 87 } 88 } 89 //删除顺序线性表中指定索引处的元素 90 public T delete(int index){ 91 if(index < 0|| index > size){ 92 throw new IndexOutOfBoundsException("线性表索引越界"); 93 } 94 T oldValue = (T) elementData[index]; 95 int numMoved = size - index - 1;//如果size 为 2 index 为1 则 numMoved 为1 96 if(numMoved > 0){ 97 System.arraycopy(elementData, index+1, elementData, index, numMoved); 98 } 99 //清空最后一个元素 100 elementData[--size] = null; 101 return oldValue; 102 } 103 //删除顺序线性表中最后一个元素 104 public T remove(){ 105 return delete(size - 1); 106 } 107 //判断顺序线性表是否为空 108 public boolean empty(){ 109 return size == 0; 110 } 111 //清空线性表 112 public void clear(){ 113 //将底层数组所有元素赋为null 114 Arrays.fill(elementData, null); 115 size = 0; 116 } 117 public String toString(){ 118 if(size == 0){ 119 return "[]"; 120 } else { 121 StringBuilder sb = new StringBuilder(); 122 for(int i = 0;i < size;i++){ 123 sb.append(elementData[i].toString() + ","); 124 } 125 int len = sb.length(); 126 return sb.delete(len - 2, len).append("]").toString(); 127 } 128 } 129 }