线性表的基本概念
线性表:有限个、类型相同的元素组成的有序序列
逻辑表示:L=<K, R>
K={k0,…kn},元素集合
R={ <ki,ki+1> | 0≤i≤n-2},关系集合
i称为ki的索引或下标
ki为ki+1的前驱,反之为后继
线性表:通常表示为L=(k0, k1, …, kn)
表中元素个数为表的长度,长度为0的表为空表
k0是第一个元素,无前驱,称为首元素;
kn是最后一个元素,无后继,称为尾元素;
线性表特点
①同一性:所有元素属于同一类型
②有序性:(首, 尾除外) 唯一前驱和唯一后继
相邻元素: 一对一的序偶<ki, ki+1>
③有穷性:元素(结点)个数有限
线性表的抽象数据类型
设:
线性表类型:List
其中数据元素类型:DataType
下标类型:Index
线性表上的操作
① 建空表:List createNullList(void)
② 在下标p处插入元素x: int insert(List list, Index p, DataType x)
③ 按位置删除:int delete(List list, Index p)
④ 按元素值删除:int delete(List list, DataType x)
⑤ 查找值为x的元素,并返回其下标:Index locate(List list, DataType x)
⑥ 判断表空:List createNullList(void)
线性表中的存储位置
逻辑相邻 <=> 物理相邻(存储位置相邻)
顺序表 L=(k0,k1,…,kn-1)
---- 首地址:k0的存储地址loc(k0)
---- 假设,每个元素占用c个存储单元
ki的存储位置:loc(ki)=loc(k0)+i*c
定义顺序表
struct SeqList //顺序表结构类型
{ int MaxNum; //表可以存放元素的最大数目
int n; //实际存放的元素数目
DataType *element; //元素数组
};
Struct SeqList Var;//定义顺序表
typedef struct SeqList Mylist;//Mylist类型定义
Mylist Var;//顺序表Var
Mylist*palist;//指向顺序表的指针palist
typedef struct SeqList*PSeqList;//指针类型定义
PSeqList palist;//指向顺序表的指针palist
struct SeqList
{ int MaxNum;
int n;
DataType *element;
};
顺序表运算的实现
- 创建空顺序表
①定义表指针,为顺序表结构申请空间;
②为数组element申请内存空间;
③设置表的最大长度MaxNum, 实际长度0;
④返回顺序表的地址,即palist。
PSeqList creatNullList_seq(int m)
{ PSeqList palist; //定义指向顺序表的指针
palist=(PSeqList)malloc(sizeof(Struct SeqList)); //为顺序表结构申请空间
if(palist != NULL) //顺序表结构空间申请成功
{ palist->element=(DataType*)malloc(sizeof(DataType )*m);
if(palist->element) //数组空间分配成功
{ palist->MaxNum = m;
palist->n = 0;
return(palist);
} //返回指向顺序表的指针
else free palist; //数组空间分配失败, 释放
}
printf(“Out of space!\n”); //结构空间分配失败
return NULL;
}
- 判断顺序表是否为空表
判断palist指向的顺序表是否为空:
int isNullList_seq(PSeqList palist)
{
return (palist->n ==0); //空则返回1
}
- 查找元素、求某元素的下标
int locate_seq(PSeqList palist, DataType x)
{ int q; //游历下标
for(q=0; q<palist->n; q++)
if (palist->element[q] == x) return q;
return -1;
}
- 在顺序表中插入元素
当palist->n <MaxNum 且0<= p <= palist->n,
- 当0<=p<= palist->n-1时,先移动,再插入新元素x
- 当p == palist->n时,直接插入新元素
最好情况?->移动0次
最坏情况?->p=0,移动n次
int insertPre_seq(PSeqList palist, int p, DataType x)
{ int q;
if (palist->n >= palist->MaxNum)//n是否大于等于maxnum,有无空位可供插入
{ prinft(“Overflow!\n”);
return 0;
}
if (p<0 || p> palist->n ) //下标p不合法(下标p不可能小于0,不可能大于n-1)
{ printf(“p does not exist! \n”); return 0; }
//下为:当插入运算有意义 … …
for (q=palist->n-1; q>=p; q--) //插入位置及之后的元素均后移一个位置
palist->element[q+1] = palist->element[q]; //下标为q的元素换到q+1去
palist->element[p] = x;//插入x,把x放到p的位置
palist->n = palist->n+1; //更新表长,元素个数+1
return 1;
}
- 从顺序表中删除元素
当 0 <= p <= palist->n-1时,运算有意义。
- 当0<=p< palist->n-1时,p之后的元素前移
- 当p == palist->n-1 时,直接更新表长
最好情况?->移动0次
最坏情况?->p=0,移动n-1次
int delete_seq(PSeqList palist, int p){
if (p<0 || p > palist->n-1) //下标p不合法(下标p不可能小于0,不可能大于n-1)
{ printf (“Not exist! \n”);
return 0;}
int q;
for(q=p; q <palist->n-1; q++)//被删除元素之后的元素均前移一个位置
palist->element[q] = palist->element[q+1]; //下标为q+1的元素换到q去
palist->n = palist->n-1;//更新表长,元素个数-1
return 1;
}
①删除表中第1个值为x的元素,返回成功与否
int delete_seq(PSeqList palist, Datatype x)
{
int p = locate_seq(palist, x);//调用locate函数定位,查找x首次出现的位置下标p
int result = delete_seq(palist, p);//删除下标为p的元素
}
顺序表分析与评价
优点:
- 存储密度高:数据本身所占空间/结点空间;
- 方便随机存取表中任一元素;
缺点: - 插入或删除,需依次移动大量元素;
- 预先分配存储空间 1)可能溢出,
2)空间可能长期闲置