顺序表相关概念
- 顺序表:用一组地址连续的存储单元依次存储线性表的数据元素,是一种随机存取的存储结构
- 存取结构:分为随机存取和非随机存取(又称顺序存取)
(1) 随机存取就是直接存取,可以通过下标直接访问的那种数据结构,与存储位置无关,例如数组。
非随机存取就是顺序存取了,不能通过下标访问了,只能按照存储顺序一个个访问,与存储位置有关,例如链表。
(2) 顺序存取就是存取第N个数据时,必须先访问前(N-1)个数据 (list)。
随机存取就是存取第N个数据时,不需要访问前(N-1)个数据,直接就可以对第N个数据操作 (array)。
- 顺序表插入或删除元素时,元素可直接通过下标访问,时间主要耗费在移动元素上(即移动元素为时间复杂度的基本操作)
顺序表的表示与相关操作的实现
- 顺序表的表示
#define LIST_INIT_SIZE 100//线性表储存空间的初始分配量
#define LISTINCREMENT 10//线性表储存空间的分配增量
typedef struct{
ElemType *base;//储存空间的基地址
int length;//顺序表的长度
int listSize;//当前分配储存容量(以sizeof(elemtype)为单位)
}List;
- 相关操作函数
Status InitList(List *L);
//线性表初始化
Status InsertElemIntoList(List *L,int i,ElemType e);
//插入元素
Status DeleteElemFromList(List *L, int i);
//删除元素
Status ModifyElem(List *L, int i, ElemType e);
//修改元素
ElemType GetElemfromList(List L, int i);
//根据下标得到元素
int IsLocalElem(List L, ElemType e);
//判断元素是否在线性表中
int GetElemIndex(List L, ElemType e);
//根据元素得到下标
Status ClearList(List *L);
//清空顺序表
Status DestroyList(List *L);
//销毁线性表
Status TraverseList(List L);
遍历线性表的元素
- 线性表初始化
Status InitList(List *L){
L->base=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));
if(!L->base){
return OVERFLOW;
}
L->length=0;
L->listSize=LIST_INIT_SIZE;
return OK;
}
- 插入元素
Status InsertElemIntoList(List *L,int i,ElemType e){
if(i<1||i>L->length+1){
return ERROR;
}//检查i是否在线性表中
if(L->length>=L->listSize){
ElemType *newBase=(ElemType*)realloc(L->base,(L->listSize+LISTINCREMENT)*sizeof(ElemType));
if(!newBase){
return OVERFLOW;
}
L->base=newBase;
L->listSize+=LISTINCREMENT;
}//检查插入后储存空间是否足够
ElemType *insert=&L->base[i-1];
for(ElemType *p=&L->base[L->length-1];p>=insert;p--){
*(p+1)=*p;
}//把第i个元素及之后元素向后平移一位
*insert=e;
L->length++;
return OK;
}
在平移时要注意为何写作(p+1)=p,与后边删除操作时的平移作比较
- 删除元素
ElemType DeleteElemFromList(List *L,int i,ElemType &e){
if(i<1||i>L->length){
return ERROR;
}
ElemType *target;
target=&L->base[i-1];
e=*target;
//以下是对指针取址取值的比较
//e=target
//*取值,啥也不带是地址
// e=L->base[i-1];
//&取址,啥也不带是值
int count=0;
for(ElemType *p=&L->base[L->length-1];p>=target;p--){
*(target+count)=*(target+1+count);
count++;
}
L->length--;
return e;
}
比插入时比较可发现,插入时是从后往前平移,而删除时是从前往后平移
- 修改元素
Status ModifyElem(List *L,int i,ElemType e){
if(i<1||i>L->length){
return ERROR;
}
L->base[i-1]=e;
return OK;
}
- 根据下标获取元素
Status GetElemfromList(List L,int i){
if(i<1||i>L.length){
return ERROR;
}
return L.base[i-1];
}
- 检查元素是否在线性表中
Status IsLocalElem(List L,ElemType e){
for(int i=0;i<L.length;i++){
if(L.base[i]==e){
return 1;
}
}
return 0;
}
- 根据元素获取下标
Status GetElemIndex(List L,ElemType e){
for(int i=0;i<L.length;i++){
if(L.base[i]==e){
return i+1;
}
}
return 0;
}
- 清空顺序表
Status ClearList(List *L){
for(int i=0;i<L->length;i++){
L->base[i]=0;
}
L->length=0;
return OK;
}
- 销毁顺序表
Status DestroyList(List *L){
free(L->base);
L->length=0;
L->listSize=0;
L->base=NULL;
return OK;
}
- 遍历线性表中的元素
Status TraverseList(List L){
for(int i=0;i<L.length;i++){
printf("The %dth elem is %d:",i+1,L.base[i]);
}
return OK;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。