线性表
定义:
线性表是一个有限的集合,寻找相同性质的数据元素,
特点:
数据元素是有限的
数据元素都是相同性质的、
线性表中元素和序号是一 一对应的,一个序号对应一个元素,
逻辑结构:
(a0,a1,a2…an-1) 相邻关系
n --> 元素的个数
每个元素的唯一位置,通过下标索引来表示。
抽象数据类型 ADT:
ADT list{
//二元组
D = {ai | 0 <= i<=n-1,i = 0,1,2,3,4…n-1} i是下标
R = {<ai,ai+1> } ai和ai +1 都属于D,i =0,1,2….n-2}
}
图解:
注意:注意区分长度和容量两个的概念区别,不要混淆了。
线性表方法:
public SqList() 构造方法,实例化线性表对象,并准备数据
void createList(E[] e) 根据数组e创建线性表,
int size(int a) 求线性表的长度,长度用size表示
void setSize(int i) 设置线性表的长度设置为a
void updateCapactiy(int newCapacity) 实现数组容量的扩容和缩小
void add(E a) 添加一个元素a到线性表的末尾
void insert(int i,E e) 将数据e插入到线性表中下标为i的位置
void delete(int i) 删除线性表中下标为i的元素
void swap(int I,int j ) 将下标i和下标j的数据进行互换
E getElem(int i) 获取指定下标为i的元素
int getNo(E e) 获取线性表中第一个值e的下标
String toString() 将线性表的元素拼接成字符串并返回
注意:当元素快要溢出的时候,扩容需要进行2倍容量扩容。
线性表的顺序存储结构
实现:
Array 数组实现
容量:
数组的总空间,能存放的最大元素个数,
长度:
size = 元素实际个数
最后元素:
size -1
代码实现:(就是实现上面的那些线性表方法,div一个线性表)
package dataStruct;
import sun.net.www.content.text.plain;
import sun.tools.jar.resources.jar;
/*
顺序线性表的模拟(数组实现)
*/
public class SqList<E> { // 泛型类
final int initCapacity = 10; // 数组的初始容量
public E[] data;// 用来存储元素的数组data
public int size; // 用来存储数组元素的个数
public int capacity;// 用来表示数组的最大容量
/*
* 构造方法 (实例化的时候创建一个数组)
*/
public SqList() { //
// 创建数组
data = (E[]) new Object[initCapacity];
// 刚创建的线性表容量 = 初始容量
capacity = initCapacity;
// 刚开始是没有元素的,所以长度为0
size = 0;
}
/*
* 实现数组容量的扩容和缩小
*/
private void updateCapacity(int newCapacity) {
// 模仿数组扩容方式
E[] newdata = (E[]) new Object[newCapacity];
for (int i = 0; i < size; i++) { // 把元素转移到newdata
newdata[i] = data[i];
}
// 更新容量
capacity = newCapacity;
// 更新数组元素
data = newdata;
}
/*
* 根据指定数组创建线性表
*/
public void CreateList(E[] e) {
int j = 0;
// 将数组e的元素放图data数组里面,
for (int i = 0; i < e.length; i++) {
// 考虑会不会溢出,是否扩容
if (size == capacity) { // size等于最大容量,说明需要进行扩容了
updateCapacity(2 * size);
}
data[j] = e[i];
// 纪录元素个数
j++;
}
// 更新长度
size = j;
}
/*
* 返回线性包的长度,大小
*/
public int size() {
return size;
}
/*
* 添加元素至末尾 (size-1当前租后一个元素,所以我们添加就是size下标)
*/
public void add(E a) {
if (size == capacity) {
updateCapacity(2 * capacity);
}
// 添加末尾
data[size] = a;
// 更新长度
size++;
}
/*
* 设置长度
*/
public void setSize(int a) {
// 考虑长度a是否合理, 0<a <size
if (a < 0 || a > size) {
throw new IllegalArgumentException("长度不在有效范围内");
}
size = a;
}
/*
* 根据下标i获取元素
*/
public E GetElem(int i) {
// 在有效范围内
if (i < 0 || i >= size) {
throw new IllegalArgumentException("下标不在有效范围内");
}
return (E) data[i];
}
/*
* 获取线性表中第一个值为e的下标
*/
public int getNo(E e) {
// 使用for循环进行元素的比较, 遍历data数组,但是如果e不在数组里面,
int i = 0; // 代表data元素序号
while (i < size && !data[i].equals(e)) { // i< size 还没有找到e元素
i++;
break;
}
// 循环完了还是没找到,
if (i == size) {
return -1;
}
// 两个条件都满足,找到了
return i;
}
/*
* 交换元素
*/
public void Swap(int i, int j) {
if (i < 0 || i > size - 1 || j < 0 || j > size - 1) {
throw new IllegalArgumentException("下标不在有效范围内!");
}
E temp = data[i];
data[i] = data[j];
data[j] = temp;
}
/*
* 指定下标插入元素(下标为i后面的元素往后移动1位)
*/
public void insertElem(int i, E e) {
// 判断下标i的范围是否合理
if (i < 0 || i > size - 1) {
throw new IllegalArgumentException("下标不在指定范围内");
}
// 判断容量是否足够
if (i == size) {
updateCapacity(2 * capacity);
}
// 从后往前移动
for (int j = size; j > i; j--) {
data[j] = data[j - 1]; // 移动1位
}
// 移动完指定位置就空出来了,直接赋值
data[i] = e;
}
/*
* 删除元素(后面的值进行覆盖)
*/
public void Delete(int i) {
// 下标是否合理
if (i < 0 || i > size - 1) {
throw new IllegalArgumentException("下标不在指定范围内");
}
for (int j = i; j < size - 1; j++) {
data[j] = data[j + 1];// 覆盖
}
size--;
// 如果删除到一定的数目,需要进行缩小容量 capacity 120 size = 1/4 capacity = 30, capacity = 60;
// 四分之一,进行减容量到一半
if (size == capacity / 4 && capacity > initCapacity) {// 同时满足大于初始容量
updateCapacity(capacity / 2); // 减到一半
}
}
/*
* 元素拼接成字符串返回
*/
public String toString() {
String answar = "";
for (int i = 0; i < data.length; i++) {
answar += data[i];
}
return answar;
}
}
注意:我们删除元素哪里进行判断减少线性表容量,是因为避免资源浪费。
实现调用:
现在我们就能直接使用这个我们自定义的线性表了,并实现里面的方法,
package dataStruct;
/*
* 自定义线性表的实现
*/
public class SqList_Test {
public static void main(String[] args) {
// 实例化线性表对象
SqList<Object> sqList = new SqList<>();
// 根据指定数组实现创建线性表
Object[] arr = { 1, 2, 3, 4, 5, 6 };
sqList.CreateList(arr);
// 返回线性表大小
System.out.println(sqList.size());
// 获取指定元素第一次出现的下标
System.out.println(sqList.getNo(2));
// 获取指定下标的元素
System.out.println(sqList.GetElem(1));
}
}