2.2.1 🍭线性表的顺序表示
线性表的顺序表示指的是用一组地址连续的存储单元依次存储线性表的数据元素。线性表的这种机内表示称作线性表的顺序存储结构或顺序映像(sequential mapping),通常,称这种存储结构的线性表为顺序表。采用顺序表表示的线性表,表中逻辑位置相邻的数据元素将存放到存储器中物理地址相邻的存储单元之中,即以元素在计算机内“物理位置相邻”来表示线性表中数据元素之间的逻辑关系。
假设线性表的每个元素需占用L个存储单元,并以所占的第一个单元的存储地址作为数据元
素的存储位置,则线性表中第 i+1 个数据元素的存储位置LOC(a i+1 )和第 i 个数据元素的存储位置LOC(ai)之间满足下列关系:
LOC(a(i+1))= LOC(ai)+ L
LOC(ai)= LOC(a1)+ (i-1)*L
LOC(a1)是线性表的第一个数据元素的存储位置,通常称作线性表的起始位置或基地址
由 ⇡ 可知,在顺序表中,任一数据元素的存放位置是从起始位置开始的,与该数据元素的位序成正比的对应存储位置,可以借助上述存储地址计算公式确定。因此,可以根据顺序表中数据元素的位序,随机访问表中的任一元素,也就是说,顺序表是一种随机存取的存储结构。
2.2.2 🍭顺序表的实现
顺序表的泛型类定义☛:
public class sequenceList<T> {
final int maxSize = 10; //顺序表中一维数组的初始长度
private T[] listArray; //存储元素的数组对象
private int length; //保存顺序表的当前长度
public sequenceList() {} //构造一个空的线性表
public sequenceList(int n) {}
public boolean add(T obj, int pos){} //在线性表中插入一个新元素
public T remove(int pos){} //删除线性表中某个元素
public int find(T obj){} //在线性表中查找一个元素
public T value(int pos){} //获取线性表中一个元素
public boolean modify(T obj, int pos){} //更新线性表中某个元素
public boolean isEmpty(){} //判空
public int size(){} //求线性表中数据元素的个数
public void nextOrder(){} //依次访问栈中每个元素并输出
public void clear(){} //销毁一个已经存在的线性表
}
1. 顺序表的初始化
顺序表的初始化就是为顺序表分配一个预定义大小的数组空间,无参数构造方法设置顺序表长度为maxSize,有参数方法设置顺序表数组长度为形参n。初始化时将顺序表的当前长度length设为“0”。构造方法的算法如下 📢
public sequenceList() {
length = 0; //线性表初始为空
listArray = (T[]) new Object[maxSize];
}
public sequenceList(int n) {
if(n<=0){
System.out.println("error");
System.exit(1);
}
length = 0; //线性表初始为空
listArray = (T[]) new Object[n];
}
2. 顺序表的插入
顺序表的插入是指在顺序表的第pos-1个元素和第pos个元素之间插入一个新的元素,此时,顺序表中插入位置前后的元素之间的逻辑关系将发生变化,因此,除非pos=n+1,否则必须通过顺序移动数据元素的存储位置才能体现逻辑关系的变化。插人过程如 ⇩ 所示👀
一般情况下,在第pos(1≤pos≤length)个元素之前插入一个元素时,需将第length至第pos共(length-pos+1)个元素向后移动一个位置,过程如 ⇩ y
public boolean add(T obj, int pos){
if(pos<1 || pos>length+1){
System.out.println("pos值不合法");
return false;
}
if(length == listArray.length){
T[] p = (T[]) new Ojbect[length*2];
for(int i = 0;i<length;i++)
p[i] = listArray[i];
listArray = p;
}
for(int i=length;i>=pos;i--)
listArray[i] = listArray[i-1];
listArray[pos-1] = obj;
length++;
return true;
}
📢 注意:
- 🚩要检验插入位置的有效性,这里pos的有效范围是:1≦pos≦length+1,其中length为原表长
- 🚩顺序表中数据区域有listArray.length个存储单元,所以在向顺序表中做插入时先检查表空间是否满了,在表满了的情况下需要重新分配2倍的存储空间,并进行原有数据的复制
- 🚩注意数据的移动方向。从表尾开始依次向前,一个一个往后移动数据元素,最后要把插入的元素obj放到数组下标为pos的地方
- 🚩顺序表的长度+1,插入成功返回true
3. 顺序表的删除
public T remove(int pos){
if(isEmpty()){
System.out.println("顺序表为空,无法进行删除操作");
return null;
} else {
if(pos<1 || pos>length){
System.out.println("pos值不合法");
return null;
}
T x = listArray[pos-1];
for(int i = pos;i<length;i++)
listArray[i-1] = listArray[i];
length--;
return x;
}
}
注意 🧲 :
- 🍗空表不能删除
- 🍗要检查删除位置的有效性(删除第pos个元素时,pos取值为1≦pos≦length,否则第pos个🍗元素不存在)
- 🍗注意数据移动方向,把删除位置pos之后的数据一次前移一个位置,最后顺序表的长度-1
- 🍗返回已做备份的被删除元素
在顺序存储结构的线性表中插入或和删除一个数据元素,平均移动表中一半元素,算法add和remove的时间复杂度为O(n)
4. 顺序表的查找
在顺序表中查找是否存在和obj相同的数据元素的最简便的方法是:令obj和顺序表中的数据元素逐个比较,如算法⇩所示👀
public int find(T, obj){
if(isEmpty()){
System.out.println("顺序表为空");
return -1;
}else{
for(int i=0;i<length;i++){
if(listArray[i].equals(obj))
return i+1;
}
return -1;
}
}
本算法的基本操作是“元素值比较”,若顺序表中存在和j相同的元素,则比较次数为(1≤i≤length),否则为length,即算法find的时间复杂度为O(n),n为表长的一般性表示。
5. 获取顺序表的第pos个位置的元素
顺序表中第pos个元素存放在数组listArray下标为pos-1的位置,也就是☛当位置转换为下标时要进行一个减一的运算。算法中1≤pos≤length,当pos值有效时返回listArray pos-1,否则返回null,如▼所示。
public T value(int pos){
if(isEmpty()){
System.out.println("顺序表为空");
return null;
}else[
if(pos<1 || pos>length){
System.out.println("pos值不合法");
return null;
}
return listArray[pos-1];
]
}
6. 修改顺序表第pos个位置的元素
首先检查参数pos的合理性,当1≤pos≤length时,用参数obj的值替换顺序表中第pos个元素,当pos取值超出合法范围时,返回false,表示修改失败,代码如下:
public boolean modify(T obj, int pos){
if(isEmpty()){
System.out.println("顺序表为空");
return false;
}else{
if(pos<1 || pos>length){
System.out.println("error");
return false;
}
listArray[pos-1]=obj;
return true;
}
}
7. 判断顺序表是否为空
上面的代码已经出现了很多次,下面再单独写一次➢
public boolean isEmpty(){
return length == 0;//判断句,正确则返回true为空,反之则为false
}
8. 求顺序表的长度
public int size(){
return length;
}
9. 正序输出顺序表中所有元素
按照逻辑次序依次输出顺序表中每一个数据元素
public void nextOrder(){
for(int i=0;i<length;i++)
System.out.println(listArray[i]);
}
10. 清空顺序表
清空顺序表代码:
public void clear(){
length = 0;
}
11. 对上面讨论的顺序储存结构的线性表进行调试
public class text{
public static void main(String[] args) {
sequenceList<Integer> L = new sequenceList<Integer>;
int state, e, i;
int[] a = {23, 56, 12, 49, 35};
for(int i=0;i<a.length;i+)
L.add(a[i], i+1); //将数组中元素插入到顺序表
System.out.println("顺序表中的元素为:");
L.nextOrder();
L.add(30, 4);
System.out.println("执行插入操作后,顺序表的数据元素为");
L.nextOrder();
e = L.remove(5);
System.out.println("执行删除操作后顺序表中的数据元素为:");
L.nextOrder();
i = L.find(12); //在顺序表中查找元素12的位序
System.out.println("元素12在线性表中的位序为:"+i);
}
}
🚩注意一下:直接运行这个程序是会报错的,这个程序引用的有上面的函数,需要将上面的函数也写上才可以正确运行