两个线性表的典型应用:
-
线性表的合并
假设有两个线性表La和Lb分别表示两个集合A和B,现在要求一个新集合 A = A ⋃ B A=A\bigcup B A=A⋃B,例如,
-
有序表的合并
已知线性表La和Lb中的数据元素按值非递减有序排列,现在要求将La和Lb归并为一个线性表Lc,且Lc中的数据元素按值依旧是非递减有序排列,例如,
应用一——线性表的合并
算法的输入如下,
输出如下,
算法步骤:
依次取出Lb中的每个元素,执行以下操作:
- 在La中查找该元素
- 如果找不到,则将其插入到La的最后(去除重复元素)
算法描述:
void union(List& La, List& Lb)
{
La_len = ListLength(La); //求表La的长度
Lb_len = ListLength(Lb); //求表Lb的长度
for (i = 1; i < Lb_len; i++) //遍历表Lb
{
GetElem(Lb, i, e); //查找表Lb中的第i个元素e
if (!LocateElem(La, e)) //在表La中查找有没有值等于e的元素,若有,则返回true
ListInsert(&La, ++La_len, e); //如果表La中没有值为e的元素,则将e加入到表La中,并且表长加1
}
}
算法的时间复杂度: O ( L i s t L e n g t h ( L a ) ∗ L i s t L e n g t h ( L b ) ) O(ListLength(La)*ListLength(Lb)) O(ListLength(La)∗ListLength(Lb))
应用二——有序表的合并
算法输入如下,
算法输出如下,
算法步骤:
- 创建一个空表Lc
- 依次从La或Lb中“摘取”元素值较小的结点插入到Lc表的最后,直至其中一个表变空为止。
- 继续将La或Lb其中一个表的剩余结点插入到Lc表的最后。
用顺序表实现
设置三个指针pa,pb,pc分别指向表La,表Lb和表Lc,依次比较pa和pb所指向的元素的值,选较小的的值加入到表Lc中,此时指向较小值的指针加1,pc指针加1,直至表La和表Lb其中一个为空,在将不为空的表的剩余元素加到表Lc的末尾。为了方便判断是否到达一个表的末尾,这里还需要加两个指针pa_last和pb_last,分别指向表La和表Lb的最后一个元素。
算法描述:
void MergeList_Sq(SqList LA, SqList LB, SqList& LC)
{
pa = LA.elem;
pb = LB.elem; //pa和pb的初值分别指向两个表的第一个元素
LC.length = LA.length + LB.length; //新表的长度为两个表的长度之和
LC.elem = new ElemType[LC.length]; //为新表Lc分配一个数组空间
pc = LC.elem; //pc的初值指向LC的第一个元素
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) //依次选取两个表中值较小的结点,加到新表LC中
*pc++ = *pa++;
else
*pc++ = *pb++;
}
while (pa <= pa_last) //表LB已到达末尾,将表LA中的设于元素加到LC中
*pc++ = *pa++;
while (pb <= pb_last) //表LA已到达末尾,将表LB中的设于元素加到LC中
*pc++ = *pb++;
}
该算法的时间复杂度是:
O
(
L
i
s
t
L
e
n
g
t
h
(
L
a
)
+
L
i
s
t
L
e
n
g
t
h
(
L
b
)
)
O(ListLength(La)+ListLength(Lb))
O(ListLength(La)+ListLength(Lb)),空间复杂度是:
O
(
L
i
s
t
L
e
n
g
t
h
(
L
a
)
+
L
i
s
t
L
e
n
g
t
h
(
L
b
)
)
O(ListLength(La)+ListLength(Lb))
O(ListLength(La)+ListLength(Lb))。
用链表实现
具体步骤:
1.用La的头结点作为Lc的头结点,分别用指针pa,pb,pc来操作表La,Lb,Lc当中的结点。
2.比较pa和pb结点的data域的值,如图,pa指向的结点的data域的值较小,所以pc的next域存放1结点的地址,即,
3.之后,pc指针就要往后移一位,指向1结点,并且pa指针也要往后移一位(pb指针不用移),即,
4.再次比较pa和pb指向结点的data域值的大小,如图,2结点的值比较小,所以pc的next域存放2结点的地址,然后,将pc后移一位,pb指针后移一位,即,
5.重复步骤3和4的操作,直到其中一个表为空,此时将另一个表剩余部分加到Lc当中,即,
6.释放Lb的头结点,
算法描述:
void MergeList_L(LinkList& La, LinkList& Lb, LinkList& Lc)
{
pa = La->next;
pb = Lb->next; //初始化pa,pb为指向表La,Lb首元结点的指针
pc = Lc = La; //用La的头结点作为Lc的头结点
while (pa&&pb) //当pa和pb不为空时
{
if (pa->data <= pb->data) //比较pa,pb所指向结点的数据域大小
{
pc->next = pa; //pc的next域指向pa(pa的data域的值较小)
pc = pa; //pc移到当前结点处
pa = pa->next; //pa向后一个结点
}
else
{
pc->next = pb;
pc = pb;
pb = pb->next;
}
}
pc->next = pa ? pa : pb; //插入剩余段
delete Lb; //释放Lb的头结点
}
该算法的时间复杂度是: O ( L i s t L e n g t h ( L a ) + L i s t L e n g t h ( L b ) ) O(ListLength(La)+ListLength(Lb)) O(ListLength(La)+ListLength(Lb)),空间复杂度是: O ( 1 ) O(1) O(1)。