2.6 顺序表和链表的比较
2.6.1 空间性能的比较
2.6.2 时间性能的比较
链式存储结构的优点:
- 结点空间可以动态申请和释放;
- 数据元素的逻辑次序靠结点的指针域来指示,插入和删除时不需要移动数据元素。
链式存储结构的缺点:
- 存储密度小,每个结点的指针域需要额外的占用存储空间。当每个结点的数据域所占的字节不多时,指针域所占存储空间的比重显得很大。(空间利用率低);
- 链式存储结构是非随机存储结构。对任一结点的操作都要从头指针依指针链查找到该结点,增加了算法的复杂度。
2.7 线性表的应用
2.7.1 线性表的合并
【例2.1】 求解一般集合的并集问题
【问题描述】已知集合A和B,求集合A=AUB。
例如:A={7, 5, 3, 11} ,B={2, 6, 3},则A={7, 5, 3, 11, 2, 6}。
【问题分析】利用两个线性表LA和LB分别表示集合A和B,只需将在LB中且不在LA中的元素插入LA中即可。
【算法步骤】
- 将集合A和B表示为顺序表数据结构,即表LA和表LB;
- 分别获取LA表长m和LB表长n;
- 从表LB中第1个数据元素开始,循环n次执行以下操作:
- 取LB中第i个元素赋值给e;
- 在LA中查找元素e,若不存在,则将e插在表LA的最后。
void MergeList(SqList &LA, SqList LB){
//已知顺序表LA和LB,将两个顺序表合并,要求去掉重复的元素。
if(LA.listsize<LA.length+LB.length) newbase = (ElemType *)
realloc(LA.elem, (LA.listsize+LB.length)*sizeof(ElemType));
if(!newbase) exit(OVERFLOW); //分配失败
LA.elem=newbase; //新基址
LA.listsize+=LB.length; //增加存储容量
pa_last=LA.elem+LA.length-1; //LA中最后一个元素的位置
pb_last=LB.elem+LB.length-1; //LB中最后一个元素的位置
pa_insert=LA.elem+LA.length; //设置插入指针
flag=1; //设置插入标志
for(pb=LB.elem; pb<=pb_last; pb++) {
flag=1;
for(pa=LA.elem; pa<=pa_last; pa++)
if(*pa==*pb) { flag=0; break; }
if(flag==1) *pa_insert++=*pb;
}
} //MergeList
基本操作:元素的比较
最坏比较次数:m*n
时间复杂度:O(m*n)
void MergeList(SqList &LA, SqList LB) {
m=LA.Length; n=LB.Length;
for(i=1; i<n; i++) {
GetElem(LB, i, e);
if(! LocateElem(LA, e, status (*compare) (ElemType, e)))
ListInsert_Sq(LA, ++m, e);
} }
2.7.2 有序表的合并
【例2.2】 求解有序集合的并集问题
【问题描述】已知两个有序集合A和B,其中数据元素按值非递减有序排列,求集合C=AUB,使C中的数据元素仍按值非递减有序排列。
例如:A=(3, 5, 8, 11), B=(2, 6, 8, 9, 11, 15, 20)。则
C=(2, 3, 5, 6, 8, 8, 9, 11, 11, 15, 20)。
【问题分析】利用两个线性表LA和LB分别表示集合A和B,且要保留相同元素。
【算法步骤】
- 分别获取LA表长m和LB表长n,并创建一个表长为m+n的空表LC;
- 分别初始化指针pa、pb、pc,让其分别指向表LA、LB、LC的第一个元素;
- 当指针pa和pb均未到达相应表尾时,则依次比较pa和pb所指向的元素值,从LA或LB中“摘取”元素值较小的元素插入到LC的表尾;
- 如果pb已到达LB的表尾,依次将LA的剩余元素插入LC的表尾;
- 如果pa已到达LA的表尾,依次将LB的剩余元素插入LC的表尾。
void MergeList(SqList LA, SqList LB, SqList &LC){
//已知顺序线性表LA和LB中的数据元素按值非递减排列,归并
LA和LB得到新的顺序线性表LC,LC的元素也按值非递减排列
pa=LA.elem;
pb=LB.elem;
LC.listsize=LC.length=LA.length+LB.length;
pc=LC.elem=(ElemType*)malloc(LC.listsize*sizeof(ElemType));
if(!LC.elem) exit(OVERFLOW); //分配失败
pa_last=LA.elem+LA.length-1; //LA中最后一个元素的位置
pb_last=LB.elem+LB.length-1; // LB中最后一个元素的位置
while(pa<=pa_last && pb<=pb_last){
if(*pa<=*pb) *pc++=*pa++; //将LA中的元素插入LC
else *pc++=*pb++; //将LB中的元素插入LC
}
while(pa<=pa_last) *pc++=*pa++; //插入LA中剩下的元素
while(pb<=pb_last) *pc++=*pb++; //插入LB中剩下的元素
} //MergeList_Sq
基本操作:元素的赋值
赋值次数:m+n
时间复杂度:O(m+n)
2.9小结
☆★☆线性表是整个数据结构课程的重要基础☆★☆
① 逻辑结构特性:元素间存在线性关系;
② 线性表两种常用的存储结构:顺序存储(顺序表)和链式存储(链表);
③ 顺序表中元素的逻辑上的线性关系是通过其存储的相邻位置反映的,可借助数组来实现,顺序表的元素可随机存取;
④ 链表中元素的逻辑上的线性关系是通过指针来反映的,链表的元素只能顺序访问。
顺序表和链表的比较
单链表、循环链表和双向链表的比较