线性结构的特点:
线性结构是最简单最直接的数据关系,数据元素之间一一对应。
线性表的概念
线性表是由n个类型相同数据元素的有限序列。
线性表的特点:
同一性:线性表是由同类数据元素组成的,每一个a必须是同一数据对象
有穷性:线性表是由有限个数据元素组成,表长度就是表中数据元素的个数
有序性:线性表中相邻数据元素之间存在着序偶关系
抽象数据类型的使用:
由于抽象数据类型定义了相应模型上的基本 运算集,可如同使用整形类型的加减乘除运算集合一样,只要列出线性表抽象数据类型LinearList 就可以直接使用其上的基本运算集
抽象数据类型的使用:
抽象数据类型一经定义,就可以多次使用
在实际问题中可利用线性表抽象数据类型的9种基本运算的组合实现对线性表进行合并、分拆、排序等多种需求。
1、线性结构的特点
线性结构是最简单、最基本的结构,数据元素间是一一对应关系。
2、线性表定义
是由n个数据元素的有限序列。除第一个和最后一个元素以外,其余的每个元素都只有唯一的直接前驱和直接后继。
3、线性表抽象数据类型定义
线性表ADT包括抽象数据类型的名称及数据元素、结构关系、基本操作集合三部分。
线性表的顺序存储结构
节点顺序存,节点线性化
类型和变量的区别:
例如:两室一厅就是一个类型的定义,是一个类型是一个规格,这样301,302 这种门牌号都可以使具有这种规格的空间,这就是变量。
自定义类型定义了一种规格,如顺序表的数据类型定义SeqList
typedef struct
{
ElemType elem[MAXSIZE] //线性表占用的数组空间
int last; //线性表的最后一个元素在数组中的位置下标
}SeqList;
(2)变量是规格类型的具体空间,两种定义方式
-
将L定义为 Seql list:类型的变量,如 Seqlist L 将顺序表定义为一个变量。使用的时候我们
可通过属性访问方式L.elem[i-1]访问顺序表中序号为i的元素ai。 -
将L定义为指向 Seqlist类型的指针变量,如 SeqList *L 可通过指针访问方式L->elem[i-1]访问顺序表中序号为i的元素ai。
类型是一种规格的定义,而变量是一种空间的定义。
线性表的基本运算
增删改查
在上面的定义中,我们通过一个结构体,进行了一个简单线性表的定义,我们在C语言或者C++z中可以通过一个结构体来进行定义,在Java中没有结构体,我么可以通过一个类来进行线性表的表示。
使用Java语言先定义一个线性表 ,然后我们再定义其中的基本操作
Java JDK中有ArrayList和LinkedList两个类很好的实现了顺序存储和链式存储。因此学习数据结构的最好方式是去研究JDK源码。
我们可以看一下Java中ArrayList和LinkedList的区别:
-
ArrayList和LinkedList可想从名字分析,它们一个是Array(动态数组)的数据结构,一个是Link(链表)的数据结构,此外,它们两个都是对List接口的实现。ArrayList是数组队列,相当于动态数组;LinkedList为双向链表结构,也可当作堆栈、队列、双端队列
-
当随机访问List时(get和set操作),ArrayList比LinkedList的效率更高,因为LinkedList是线性的数据存储方式,所以需要移动指针从前往后依次查找。
-
当对数据进行增加和删除的操作时(add和remove操作),LinkedList比ArrayList的效率更高,因为ArrayList是数组,所以在其中进行增删操作时,会对操作点之后所有数据的下标索引造成影响,需要进行数据的移动。
-
从利用效率来看,ArrayList自由性较低,因为它需要手动的设置固定大小的容量,但是它的使用比较方便,只需要创建,然后添加数据,通过调用下标进行使用;而LinkedList自由性较高,能够动态的随数据量的变化而变化,但是它不便于使用。
下面使用Java实现一个顺序表
首先定义一个线性表,并定义线性表中的插入删除的相关的操作。
package com.shunxubiao;
/***
*
* @author lei
*
*/
public class MyArrayList {
//定义一个用来保存数据的数组
private Object arr[];
//定义一个空数组,用来初始化空数组
private Object[] DEFAULT_EMPTY = {
};
//数组的初始容量,我们可以参照ArrayList源码,数组的初始容量为10
private static final int DEFAULT_SIZE = 10;
//数组的大小,也就是数组的最大容量
private int maxSize;
//定义线性表的大小,线性表的当前个数
private int size;
//带参构造方法,提供能构造指定容量的空列表
public MyArrayList(int inittalSize){
if (inittalSize > 0) {
this.arr = new Object[inittalSize];
this.maxSize = inittalSize;
}else if (inittalSize == 0) {
this.arr = DEFAULT_EMPTY;
}else {
throw new IllegalArgumentException("不能为负,非法容量"+inittalSize);
}
}
//空参构造,用来初始化一个空数组
public MyArrayList(){
this.arr = DEFAULT_EMPTY;
}
}
//往线性表中指定位置插入数据
//在指定位置插入元素,首先就是需要判断插入位置是否正确,然后判断数组长度是否越界,
//如果已经满了我们需要重新增加数组的长度,一般是增加1.5倍长度,ArrayList JDK源码中也是增加1.5倍的数组长度。
//然后移动数组元素,空出需要插入的位置,最后把数据插入到数组中。
//在数组的指定位置插入元素。
public void insert(int i,Object elem){
//首先判断数组插入的位置是否合法
if (i < 0) {
new IllegalArgumentException("插入位置不合法");
}
if(i > size){
new IllegalArgumentException("插入位置越界,当前数组的大小为:"+size);
}
Object oldArr[];
Object newArr[];//用来存放扩容后的容量
//如果当前线性表中数组为满的,需要增加数组的存储空间
if (i == maxSize) {
oldArr = arr;
newArr = new MyArrayList[(int) (maxSize*1.5)];
//把旧数组中的元素赋值到新的数组中
for (int j = 0; j < newArr.length; j++) {
newArr[j] = oldArr[j];
}
maxSize = (int) (maxSize*1.5);
arr = newArr;
}
//如果插入的位置是最后一个元素,不需要移动元素
if (i == size) {
arr[i] = elem;
size++;
return;
}
//如果插入的不是最后一个位置,需要移动元素,先移动位置,空出带插入位置元素
for (int j = size;j > i;j--) {
arr[j] = arr[j-1];
}
//移动完之后,插入元素
arr[i] = elem;
size++;
//查看数组中的元素
for (int j = 0; j < arr.length; j