###顺序表和链表的比较及如何选择###
ps
一般地,存储密度越大,存储空间地利用率就越高。显然,顺序表地存储密度为1(100%),而链表地存储密度小于1。
###线性表的两个典型运用###
1.线性表的合并
-
问题描述:假设利用两个线性表La和Lb分别表示两个集合A和B,现要求一个新的集合是两个并集
-
算法步骤:一次去除Lb中的每个元素,执行以下操作:
-
在La中查找该元素
-
如果找不到,则将其插入La的最后
-
void union( List &La, List Lb) {
La_len=ListLength(La);
Lb_len=ListLength(Lb);
for(i=1: i<=Lb len; i++){
GetElem(Lb, i, e);//依次看看Lb中每个值又没有在La中有,没有就插入La
if(!Locate Elem(La, e)) Listinsert(&La, ++La len, e);
}
}
2.有序表的合并
-
问题描述:已知线性表La和Lb中的数据元素按值非递减有序排列,现要求将La和Lb归并为一个新的线性表Lc,且Lc中的数据元素仍按值非递减有序排列。
-
算法步骤:
-
创建空表Lc
-
依次从La或Lb中摘取元素值较小的结点插入Lc表的最后,直至其中一个表变空为止
-
继续将La或Lb其中一个表的剩余结点插入在Lc的最后
-
顺序表实现
void MergeList_Sq(SqList LA, SqList LB, SqList &LC) {
LA.elem;
b=LB.elem; //指针pa和pb的初值分别指向两个表的第一个元素
LC.length=LA.length+LB.length; //新表长度为待合并两表的长度之和
LC.elem=new ElemType[LC.length]; //为合并后的新表分配一个数组空间
pc=LC.elem; //指针pc指向新表的第一个元素
pa_last=LA.elem+LA.length-1; //指针pa_last指向LA的最后一个元素
pb_last=LB.elem+LB.length-1; //指针pb_last指向LB的最后一个元素
while(pa<=pa_last&&pb<=pb_last) { //两个表都非空
if(*pa<=*pb) *pc++=*pa++; //依次“摘取”两表中值较小的结点
else *pc++=*pb++;
}
while(pa<=pa_last) *pc++=*pa++;//B表已到达表尾,将LA中剩余元素加入LC
while(pb<=pb_last) *pc++=*pb++;//A表已到达表尾,将LB中剩余元素加入LC
}//MergeList_Sq
//循环的次数取决于LA,LB中数据的元素多少,Lc的长度取决于LA,LB中数据的元素多少
//时间复杂度和空间复杂度都是O(ListLength(La)+ListLength(Lb))
用链表实现
void MergeList L(LinkList &La, LinkList &Lb, LinkList &Lc) {
pa=La->next; pb=Lb->next;
pc=Lc=La; //用La的头结点作为Lc的头结点
while(pa&&pb) {
if(pa->data<=pb->data) {pc->next=pa; pc=pa; pa=pa->next;}
else {pc->next=pb; pc=pb; pb=pb->next;}
}
pc->next=pa?pa: pb;//插入剩余段
delete Lb;//释放Lb的头结点
}
//时间复杂度最坏情况是La,Lb轮流出现要加入的元素,必须要La,Lb中每一个元素都要走一遍
//最坏时间复杂度是O(ListLength(La)+ListLength(Lb))
//在原有链表基础上操作,不需要额外空间,因此空间复杂度是O(1)
###案例分析与实现###
1.一元多项式运算(仅加法)
一般多项式
稀疏多项式运算
推荐使用链式存储结构,因为不用考虑分配空间问题
//建立多项式链表
void Create Polyn(Polynomial &P, int n){
//输入m项的系数和指数,建立表示多项式的有序链表P
P=new PNode;
P->next=NULL; //先建立一个带头结点的单链表
for(i=1;i<=n;++i){ //依次输入n个非零项
s = new PNode;//生成新结点
cin >> s->coef >> s->expn;//输入系数和指数
pre = P;//pre用于保存q的前驱,初值为头结点
q=P->next; //q初始化,指向首元结点
while(q&&q->expn<s->expn){/找到第一个大于输入项指数的项"q
pre=q; q = q->next;
}
s->next=q; //将输入项s插入到q和其前驱结点pre之间
pre->next=s;
}
}
//结合链表创建头插法或尾插法理解,如果不理解先去看头插法和尾插法。
typedef struct Node
{
int coef;//coefficient:系数
int index;//index:指数
struct Node *next=NULL;
}node;
//多项式相加算法
node *addpolylist(node *la,node *lb, node &lb)//polynomial:多项式
{
node temp = new node;
node *pa, *pb, *pc;
lc=la; //以la的头结点作为lc的头结点
pa=la->next; pb=lb->next; pc=lc;//将pa,pb分别指向la,lb的首元结点
while(pa&&pb)//分别遍历,两个链表指针非空为循环条件,就是两串都还没加完
{
if(pa->index<pb->index) //pa指向结点系数大于pb
{
pc->next=pa;
pa=pa->next;
pc=pc->next;
}
else if (pa->index>pb->index)
{
pc->next=pb;
pb=pb->next;
pc=pc->next;
}
else
{
temp = new node;
temp->coef=pa->coef+pb->coef;
if(temp->coef)//系数相加非零
{
temp->index=pa->index;
pc->next=temp;
pa=pa->next;
pb=pb->next;
pc=pc->next;
}
else
{
delete temp;
pa=pa->next;
pb=pb->next;
}
}
}
pc->next=pa?pa:pb;//把pa或pb剩余没加完的非空列表加在pc后面
return lc;
}
2.图书管理系统
定义书结点类型如下,其他操作参考先前章节容易设计出!在此不介绍