线性表的顺序表示指的是用一组地址连续的存储单元以此存储线性表的数据元素,这种表示也称作线性表的顺序存储结构或顺序映像。通常,称这种存储结构的线性表为顺序表。特点是:逻辑上相邻的数据元素,其物理次序上也是相邻的。
顺序表的存储示意图
假设线性表的每个元素与占用l个存储单元,并以所占的第一个单元的存储地址作为数据元素的存储起始位置。则线性表中地i+1个数据元素的存储位置LOC(a i+1)和第i个数据元素的存储位置LOC(a i)之间有如下关系:
通常的,线性表的地i个数据元素ai的存储位置为:
每一个数据元素的存储位置都和线性表中的起始位置相差一个常数,这个常熟和数据元素在线性表中的位序成正比。所以,只要确定了存储线性表的起始位置,线性表中任意数据元素都可以随机存取。所以,线性表的顺序存储结构是一种随机存取的存储结构。
实现顺序表(java)
首先建立一个List接口,用来定义顺序表的一些操作
package 线性表的顺序结构;
public interface List {
//返回顺序表的大小
public int size();
//判断线性表中是否为空
public boolean isEmpty();
//向线性表中插入数据元素
public boolean insert(int index, Object obj) throws Exception;
//删除线性表中指定元素
public boolean delete(int index) throws Exception;
//获取线性表的指定元素
public Object getElem(int index);
//判断数据元素是否在链表中
public int searchList(Object obj);
//销毁线性表
public void destroyList();
//将线性表置为空表
public void clearList();
//返回线性表中第一个值与obj相同的元素在线性表中的位置
public Object locateElem(Object obj);
}
实现顺序表的操作方法:
package 线性表的顺序结构;
public class SqList implements List {
//默认的顺序表的最大长度
final int DefaultSizs = 10;
//顺序表的长度最大值
int MaxSize;
//顺序表的当前长度
int size;
//用于存储顺序表的数据元素
Object[] listArray;
public SqList() {
this.init(this.DefaultSizs);
}
public SqList(int size) {
this.init(size);
}
/**
* 初始化顺序表
* @param size
*/
public void init(int size) {
this.MaxSize = size;
this.size = 0;
this.listArray = new Object[size];
}
@Override
/**
* 获得顺序表的长度
*/
public int size() {
// TODO Auto-generated method stub
return size;
}
@Override
/**
* 判断顺便表是否为空
*/
public boolean isEmpty() {
// TODO Auto-generated method stub
return size == 0;
}
@Override
/**
* 在指定位置插入数据元素到顺序表
*/
public boolean insert(int index, Object obj) throws Exception {
// TODO Auto-generated method stub
if(index < 1 || index > size + 1) return false;
if(size >= MaxSize) return false;
for(int j = size - 1; j >= index; j--) {
this.listArray[j + 1] = this.listArray[j];
}
this.listArray[index - 1] = obj;
++size;
return true;
}
@Override
/**
* 删除顺序表中指定位置的数据元素
*/
public boolean delete(int index) throws Exception {
// TODO Auto-generated method stub
if(index < 1 || index > size) return false;
for(int j = index; j <= size - 1; j++) {
this.listArray[j - 1] = this.listArray[j];
}
--size;
return true;
}
@Override
/**
* 获得指定数据元素
*/
public Object getElem(int index) {
// TODO Auto-generated method stub
if(index < 1 || index > size) return null;
return this.listArray[index - 1];
}
@Override
/**
* 查找数据元素是否在顺序表中
* 若在表中,返回该数据元素在顺序表的序号
*/
public int searchList(Object obj) {
// TODO Auto-generated method stub
for(int j = 0; j < size; j++) {
if(this.listArray[j] == obj) return j + 1;
}
return 0;
}
public static void main(String[] args) {
SqList list = new SqList(2);
try {
list.insert(1, 100);
list.insert(2, 50);
list.insert(3, 20);
list.insert(4, 90);
for (int i = 1; i <= list.size; i++) {
System.out.println("第" + i + "个数为" + list.getElem(i));
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
/**
* 销毁顺序表
*/
public void destroyList() {
// TODO Auto-generated method stub
this.listArray = null;
this.size = 0;
}
@Override
/**
* 清空顺序表
*/
public void clearList() {
// TODO Auto-generated method stub
if(this.listArray != null && this.listArray.length != 0) {
this.listArray = new Object[this.MaxSize];
}
}
@Override
public Object locateElem(Object obj) {
// TODO Auto-generated method stub
for(int j = 0; j < size; j++) {
if(this.listArray[j] == obj) return j + 1;
}
return null;
}
}
但是在上面的代码中我们和容易的看到一个缺点,那就是存放数据元素的数组是定长的,即,上面实现的顺序表是静态顺序表。那么当数据量很大的时候,我们需要进行扩容,否则无法存储下所有数据。
修改SqList类,增加一个判断是否需要扩容的方法:
//进行扩容
public void seqListDempty() {
if(size == MaxSize) {
MaxSize *= 2;
Object[] newArr = new Object[MaxSize];
for (int i = 0; i < size; i++) {
newArr[i] = this.listArray[i];
}
this.listArray = newArr;
}
}
同时修改insert()方法:
@Override
/**
* 在指定位置插入数据元素到顺序表
*/
public boolean insert(int index, Object obj) throws Exception {
// TODO Auto-generated method stub
if(index < 1 || index > size + 1) return false;
if(size >= MaxSize) seqListDempty();
for(int j = size - 1; j >= index; j--) {
this.listArray[j + 1] = this.listArray[j];
}
this.listArray[index - 1] = obj;
++size;
return true;
}
这样我们就实现了动态顺序表。