1 合并线性表
将线性表Lb中的元素逐个取出,判断其是否在线性表La中,如果不在,将其插入到线性表La,具体算法如下。
Status List_Union(SqLisrPtr La, SqLisrPtr Lb)
{
ElemType elem;
Status status;
int i,j;
int len = List_Size(Lb);
for (i = 0; i < len; i++)
{
//从线性表Lb中取出元素
List_Retrieve(Lb, i, &elem);
//判断是否存在于La中
status = List_Locate(La, elem, &j);
//不存在,插入
if (status != success)
{
status = List_Insert(La, 0, elem);
//插入失败,退出
if (status != success)
{
break;
}
}
}
return status;
}
该算法必须在线性表基本操作List_Size,List_Retrieve,List_Locate和List_Insert等函数实现后,才能在计算机中调用并实际运行。运用该算法最坏的情况是Lb中的所有元素都不在La中,取出Lb第一个元素后需要将其与La中的所有m个元素进行m次比较,第二个元素进行m+1次比较,以此类推,最后一个元素进行m+n-1次比较。因此,总的比较次数为m + (m+1) + … + (m+n-1) = mn + n(n - 1)/2,时间复杂度为O(mn+n * n),若m和n同量级,算法复杂度为O(n * n)。
2 合并有序表
不破坏原链表算法:依次扫描La和Lb中的元素,比较当前元素的值,将较小的元素插入到Lc中。如此反复,直到一个线性表扫描完毕,然后将未完成的线性表余下的元素逐个插入到Lc表尾。
Status List_Merge(SqListPtr La, SqListPtr Lb, SqListPtr Lc)
{
ElemType elem1, elem2;
int i = 0, j = 0, k = 0;
int n = List_Size(La), m = List_Size(Lb);
Status status = List_Init(Lc);
while (i < n && j < m)
{
List_Retrive(La, i, &elem1);
List_Retrive(Lb, j, &elem2);
if (elem1 < elem2)
{
status = List_Insert(Lc, k, elem1);
i++;
}
else
{
status = List_Insert(Lc, k, elem2);
j++;
}
k++;
}
while (i < n)
{
List_Retrive(La, i, &elem1);
status = List_Insert(Lc, k, elem1);
i++;
k++;
}
while (j < m)
{
List_Retrive(Lb, j, &elem2);
status = List_Insert(Lc, k, elem2);
j++;
k++;
}
return status;
}
破坏原链表算法:快速简单粗暴,pc指向La的头结点,pa和pb分别指向La和Lb的第一个元素,比较pa->elem和pb->elem,取较小的元素的指针作为pc的next,并移动到下一个位置。直到pa或pb指向NULL,将pc指向另一个未完成的链表。
void List_Merge(SqListPtr La, SqListPtr Lb, SqListPtr Lc)
{
Ptr pa, pb, pc, tp;
pa = (*La)->next;
pb = (*Lb)->next;
pc = (*La);
while (pa && pb)
{
if (pa->elem < pb->elem)
{
pc->next = pa;
pc = pa;
pa = pa->next;
}
else if (pa->elem > pb->elem)
{
pc->next = pb;
pc = pb;
pb = pb->next;
}
else
{
tp = pb;
pc->next = pa;
pc = pa;
pa = pa->next;
pb = pb->next;
free(tp);
tp = NULL;
}
}
pc->next = pa ? pa : pb;
free(*Lb);
*Lc = *La;
}