1、线性表的概述
- 线性表的二元组:linearity=(D,S)
- D={01,02,03,04,05,06}
- S={<01,04>,<04,06>,<06,02>,<02,05>,<05.03>}
- 在linearity中,数据元素是有序的,有一个头元素(01),还有一个尾元素(03),除了头元素之外其余元素都有一个直接前驱元素,除尾元素之外,其他每个元素都有一个直接后继元素,数据元素之间是一对一的关系,linearity就是一个线性结构
2、线性表抽象数据类型
ADT List{数据对象:D={ai 属于某个数据类型,i=0,1,2,3,...}D={a0,a1,a2,a3,a4,...an},表示所有的元素都是同一种数据类型数据关系:R={<ai,ai+1>}数据操作:getSize():返回线性表当中的元素个数isEmpty():返回线性表是否为空,线性表为空true,否则falseinsert(e,i):在线性表的指定索引位置i插入元素econtains(e):在线性表中判断是否包含e元素,存在返回true,不存在返回falseindexOf(e):获取元素e在线性表中的索引值,不存在返回-1remove(e):删除线性表中第一个与e相同的元素,删除成功返回删除的元素remove(i):删除线性表中指定索引值的元素,返回删除的元素replace(i,e):把线性表中索引为i的元素替换为eget(i):返回线性表中索引值为i的元素insertBefore(p,e):在线性表中元素p的前面插入元素einsertAfter(p,e):在线性表中元素p的后面插入元素e**所有涉及索引的操作都需要指定越界异常**}
抽象数据类型可以对应一个Java类
使用Java中的接口表示ADT中的数据操作,在使用类完成抽象数据类型时,只要这个类实现接口就可以完成抽象数据类型中定义的操作 ```java public interface MyList {
int getSize();//返回线性表当中的元素个数
boolean isEmpty();//返回线性表是否为空,线性表为空true,否则false
void insert(Object obj, int index);//在线性表的指定索引位置i插入元素e
boolean contains(Object obj);//在线性表中判断是否包含e元素,存在返回true,不存在返回false
int indexOf(Object obj);//获取元素e在线性表中的索引值,不存在返回-1
Object remove(Object obj);//删除线性表中第一个与e相同的元素,删除成功返回删除的元素
Object remove(int index);//删除线性表中指定索引值的元素,返回删除的元素
void replace(int index, Object obj);//把线性表中索引为i的元素替换为e
Object get(int index);//返回线性表中索引值为i的元素
void insertBefore(Object pre, Object obj);//在线性表中元素p的前面插入元素e
void insertAfter(Object af, Object obj);//在线性表中元素p的后面插入元素e
}
<a name="aKDay"></a># 4、线性表的顺序存储- 线性表的顺序存储,就是采用一组地址连续的存储空间,依次存储线性表中的元素- 以数据元素在计算机内存的地址相邻性表示数据元素之间的关系- 在Java中可以使用数组来存储线性表中的数据元素,数组就是一块连续的存储空间- 我们以insert(e,i)和remove(i)为例,分析实际数组操作过程<a name="ScDi5"></a># 5、线性表的顺序代码实现```javapublic class MyArrayList implements MyList{//定义一个数组存放数据元素private Object[] elements;//定义数组的默认初始化容量为16private static final int DEFAULT_CAPACITY = 16;//定义一个变量保存数据元素的个数private int size;//通过构造方法进行数组的初始化public MyArrayList() {elements = new Object[DEFAULT_CAPACITY];}public MyArrayList(int initialCapacity) {elements = new Object[initialCapacity];}@Overridepublic int getSize() {return size;}@Overridepublic boolean isEmpty() {if (size == 0){return true;}return false;}@Overridepublic void insert(int index, Object obj) {//判断索引值index是否越界if (index < 0 || index > size){throw new IndexOutOfBoundsException(index + "越界");}//如果数组已满,需要进行扩容,从index开始把元素依次后移动,把元素存储到index的位置if (size >= elements.length){expandSpace(); //数组扩容}//把从index开始的元素依次后移for (int j = size; j > index; j --){elements[j] = elements[j-1];}//把元素obj放入到index位置elements[index] = obj;//元素个数+1size ++;}//定义数组扩容方法private void expandSpace() {//定义一个更大的数组,扩容为原来的两倍Object[] newElements = new Object[elements.length*2];//把原数组的内容复制到新的数组当中for (int i = 0; i < elements.length; i ++){newElements[i] = elements[i];}//将原来的数组名指向新的数组elements = newElements;}@Overridepublic boolean contains(Object obj) {//通过indexOf方法来判断是否包含元素,不包含indexOf会返回-1return indexOf(obj) >= 0;}@Overridepublic int indexOf(Object obj) {//遍历数组获取指定元素的下标if (obj == null){//线性表中用户可能会添加nullfor (int i = 0; i < size; i ++){if (elements[i]==null){return i;}}}else{for (int i = 0; i < size; i ++){if (obj.equals(elements[i])){return i;}}}return -1;}@Overridepublic Object remove(Object obj) {int index = indexOf(obj);if (index < 0){throw new NoSuchElementException("没有指定元素" + obj);}Object result = remove(index);return result;}@Overridepublic Object remove(int index) {if (index < 0 || index >= size){throw new IndexOutOfBoundsException(index+"下标越界");}Object obj = elements[index];//将移除元素后的元素依次前移,最后的元素置为nullfor (int j = index; j < size; j ++){elements[j] = elements [j+1];}elements[size-1]=null;size --;return obj;}@Overridepublic void replace(int index, Object obj) {if (index < 0 || index >= size){throw new IndexOutOfBoundsException(index+"下标越界");}elements[index] = obj;}@Overridepublic Object get(int index) {if (index >= size || index < 0){throw new IndexOutOfBoundsException(index + "下标越界");}return elements[index];}@Overridepublic void insertBefore(Object pre, Object obj) {if (contains(pre)==false){throw new NoSuchElementException("没有指定元素"+pre);}int index = indexOf(pre);insert(index,obj);}@Overridepublic void insertAfter(Object suf, Object obj) {if (contains(suf)==false){throw new NoSuchElementException("没有指定元素"+suf);}int index = indexOf(suf) + 1;insert(index,obj);}@Overridepublic String toString() {//把线性表中的每一个元素连接起来,遍历数组中的每一个元素StringBuilder result = new StringBuilder();result.append("[");for (int i = 0; i < size; i ++){result.append(elements[i]+",");}//移除最后一个元素末尾的','result.deleteCharAt(result.length()-1);result.append("]");return result.toString();}}
6、测试线性表顺序代码实现
public class MyListTest {public static void main(String[] args) {//创建一个MyArrayList对象MyArrayList list = new MyArrayList();//isEmpty判断数组是否为空System.out.println(list.isEmpty());//true//getSize查看线性表元素个数System.out.println(list.getSize());//0//insert向数组中添加元素list.insert(0,"one");list.insert(1,"two");list.insert(0,"zero");//isEmpty判断数组是否为空System.out.println(list.isEmpty());//false//getSize查看线性表元素个数System.out.println(list.getSize());//3//查看线性表中的数据System.out.println(list);//[zero,one,two]//contains判断是否包含某个元素System.out.println(list.contains("one"));//trueSystem.out.println(list.contains("hello"));//false//indexOf获取元素下标System.out.println(list.indexOf("one"));//1System.out.println(list.indexOf("hello"));//-1//get获取指定下标的元素System.out.println(list.get(0));//zero// System.out.println(list.get(5));//异常:5下标越界//测试replace替换list.replace(0,"ZERO");System.out.println(list);//[ZERO,one,two]// list.replace(3,"three");//异常:3下标越界//insertBefore在指定元素前插入元素list.insertBefore("two","onePoint");System.out.println(list);//[ZERO,one,onePoint,two]// list.insertBefore("hello","nice");//异常:没有指定元素hello//insertAfter在指定元素后面插入元素list.insertAfter("ZERO","ZeroPoint");System.out.println(list);//[ZERO,ZeroPoint,one,onePoint,two]// list.insertAfter("hello","world");//异常:没有指定元素hello//测试remove(index)方法System.out.println(list.remove("ZeroPoint"));//ZeroPointSystem.out.println(list);//[ZERO,one,onePoint,two]System.out.println(list.getSize());//4//测试remove(obj)方法System.out.println(list.remove(2));//onePointSystem.out.println(list);//[ZERO,one,two]System.out.println(list.getSize());//3//测试不存在元素remove// System.out.println(list.remove("hello"));//异常:没有指定元素hello// System.out.println(list.remove(5));//异常:5下标越界}}
7、线性表的顺序存储特点
- 优点:
- 顺序存储是采用数组实现的,数组可以使用索引值快速访问每个元素

