顺序表
假定线性表的元素类型为ElemType,线性表的存储类型描述为
#define MaxSize 50 //定义线性表的最大长度
typedef struct{
ElemType data[MaxSize]; //顺序表的元素
int length; //顺序表的当前长度
}SqList; //顺序表的类型定义
顺序表的动态分配
#define InitSize 100
typedef struct{
ElemType *data; //指示动态分配数组的指针
int MaxSize,length; //数组的最大容量和当前个数
}SeqList; //动态分配顺序表的类型定义
C++的动态分配语句为
L.data = new Elemtype[InitSize]
顺序表的特点:
- 随机访问(最重要的特点),通过首地址和元素序号,在O(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[j - 1] = e; //位置i(下标i-1)处放入e
L.length++; //顺序表长度加1
return true;
}
}
- 最好情况:在表尾插入,没有移动元素,时间复杂度为O(1)
- 最坏情况:在表头插入,移动全部元素,时间复杂度为O(n)
- 平均情况:有n+1个位置可供插入,概率相等,移动元素个数从0到n,则平均次数为n/2
- 线性表插入算法的平均时间复杂度为O(n)
删除操作
bool ListDelete(Sqlist &L,int i,Elemtype &e){
if(i < 1||i > L.length) //判断i的范围
return false;
e = L.data[i - 1];
for (j = i;j < L.length;j++)
L.data[j - 1] =L.data[j]; //位置i(下标i-1)处后的元素前移
L.length--; //顺序表长度减1
return true;
}
- 最好情况:删除表尾元素,不用移动元素,时间复杂度为O(1)
- 最坏情况:删除表首元素,移动所有元素,时间复杂度为O(n)
- 平均情况:有n个位置可供删除,概率相等,移动元素个数从0到n-1,则平均次数为(n-1)/2
- 线性表删除算法的平均时间复杂度为O(n)
按值查找(顺序查找)
int LocateElem(Sqlist L,ElemType e){
int i;
for(i = 0;i < L.length;i++){
if(L.data[i] == e) //下标为i的元素等于e
return i + 1; //返回其位序i+1
}
return 0; //退出循环,查找失败
}
- 最好情况:查找的元素就在表头,时间复杂度为O(1)
- 最差情况:查找的元素在表尾(或不存在),时间复杂度为O(n)
- 平均情况:有n个位置可供查找,概率相等,查找次数从1到n,则平均次数为(1+n)/2
- 线性表查找算法的平均时间复杂度为O(n)