顺序表———线性表考研笔记
1.1顺序表的定义
用顺序存储的方式实现线性表
- 顺序存储:逻辑上相邻的元素物理位置上也相邻
- 元素之间的关系通过存储单元的邻接关系实现
1.2顺序表的实现
1.2.1静态分配
顺序表的长度不可以改变
1.2.1.1 数据对象的定义
#define MaxSize 10//定义最大长度
typedef struct{
ElemType data[MaxSize];//静态的数组存放数据元素
int Length;//顺序表的当前长度
}SqList;
1.2.1.2 数据元素的初始化 InitList(&L)
- 把每个数据元素的值设为默认值(可省略)
- 顺序表初始长度设为0(不可省略)
- 遍历、打印顺序表的元素需要用到顺序表实际长度(非MaxSize)作循环条件
void InitList(SqList *L){ //传元素的指针才能在调用函数内部修改该元素的值
for (int i = 0;i < MaxSize; ++i)
L->data[i] = 0;
L->Length = 0;//顺序表初始长度为0
}
1.2.1.3 数据元素的插入 ListInsert(&L, i , e)
在表中的第i个位置(位序)上插入指定元素e
插入成功返回True,插入失败返回False
时间复杂度的分析
- 最好情况(O(n)=1)
- 平均情况(O(n)=n)
- 最坏情况(O(n)=n)
注意事项
- 数据元素移动方式:从表尾元素开始依次向前移
- 注意位序和数组下标的关系(位序为i,数组下标为i-1)
- 判断插入位置是否合法(程序健壮性)
- 表是否已经满(不能再插入元素)
- 插入位置比表头元素还前
- 插入位置比表尾元素后一个位置还后(顺序表元素存放是连续的,不能中间空了没有元素)
bool ListInsert(SqList *L,int i,ElemType e){
if (i < 1 || i > L->Length+1)//判断i的范围是否有效
return false;
if (L->Length >= Maxsize )//当前存储空间已满,不能插入
return false;
for (int j = L->Length; j >= i ; --j)
L->data[j] = L->data[j-1];//从表尾元素开始向后移动元素
L->data[i-1] = e;//在位置i插入e
L->Length += 1;//表长加一
return true;
}
1.2.1.4 数据元素的删除 ListDelete(&L, i , &e)
删除表L中第i个位置的元素(表修改->传表的地址),并用e返回删除元素的值(传元素的地址)
删除成功返回True,删除失败返回False
时间复杂度的分析
- 最好情况(O(n)=1)
- 平均情况(O(n)=n)
- 最坏情况(O(n)=n)
注意事项
- 数据元素移动方式:从靠前的元素开始依次向后移
bool ListDelete(SqList *L;int i,ElemType &e){
if (i < 1 || i > L->Length)//判断i的范围是否有效
return false;
e = L->data[i-1];//将被删除的元素赋值给e(注意位序与下标的关系)
for(int j = i; j < L->Length ; ++j)
L->data[j-1] = L->data[j];//将第i个位置后的元素前移(移动元素下标从i开始)
L.Length -= 1;//线性表长度减1
return true;//成功删除
}
1.2.1.5 数据元素的按位查找 GetElem(L, i )
- 按位查找操作:获取表L中第i个位置(位序)的元素的值
- 时间复杂度O(1)
ElemType GetElem(SqList L,int i){
if (i < 1 || i > L->Length)//判断i的范围是否有效
return false;
return L.data[i-1];//位序和数组下标关系
}
1.2.2动态分配
- 利用malloc函数动态分配一片连续的存储区域
- 然后通过指向该片存储区域的起始位置的指针实现对元素的操作
1.2.2.1数据对象的定义
typedef struct{
ElemType *data;//指示动态分配数组的指针(顺序表的首元素)
int Maxsize;//顺序表的最大长度
int Length;//顺序表的当前长度
}SeqList;
1.2.2.2 动态数组的初始化 InitList(&L, InitSize)
void InitList(SeqList *L,int InitSize){
L->data = (ElemType *)malloc(sizeof(ElemType)*InitSize);//动态分配存储空间
L->Length = 0;
L->Maxsize = InitSize;
}
1.2.2.3 增加动态数组的长度 IncreaseSize(&L, Len)
- 重新申请内存空间,将原内存空间的元素复制到新的内存空间
- 释放原内存空间
#include <stdlib.h> //malloc、free函数的头文件
void IncreaseSize(SeqList *L, int Len){
ElemType *q = L->data;//指向顺序表动态数组首元素
L->data = (ElemType *)malloc(sizeof(ElmeType)*Len);//重新申请内存空间
for (int i =0; i < L->Length; ++i)
L->data[i] = q[i];//复制元素
L->MaxSize += Len;//顺序表的最大长度增加Len
free(q);//释放原来的内存空间
}
1.2.2.4 数据元素的按位查找 GetElem(L, i )
- 按位查找操作:获取表L中第i个位置(位序)的元素的值
- 时间复杂度O(1)
ElemType GetElem(SeqList L,int i){
if (i < 1 || i > L->Length)//判断i的范围是否有效
return ERROR;
return L.data[i-1];//位序和数组下标关系
}
1.2.2.4 数据元素的按值查找 GetElem(L, e)
按值查找操作:在表L中查找具有给定关键字值的元素
成功:返回第一个元素值等于e的位序;失败:返回0
时间复杂度 最好O(1) 最坏O(n) 平均O(n)
int LocateElem(SeqList L,ElemType e){
for (int i = 0; i < L.Length; ++i)
if (L.data[i] == e)
return i+1;//位序和数组下标关系
return 0;
}
1.3顺序表的代码注意
-
位序和数组下标的关系(位序为i,数组下标为i-1)
-
移动元素是从表尾元素开始移动还是从靠前元素开始移动
-
判断位置i是否合法(程序健壮性):不合法返回ERROR(宏定义)
- 位置比表头元素还前
- 插入位置比表尾元素后一个位置还后(顺序表元素存放是连续的,不能中间空了没有元素)
- 表是否已经满(不能再插入元素)
-
结构类型的数据元素不能直接比较,需依次对比各个分量来判断两个结构体是否相等(自定义判断函数)