【例2-5】有数据类型为整型的单链表Ha和Hb,其数据元素均按从小到大的升序排列,编写一个算法将它们合并成一个表Hc,要求Hc中结点的值也是升序排列。
算法思路:把Ha的头结点作为Hc的头结点,依次扫描Ha和Hb的结点,比较Ha和Hb当前结点数据域的值,将较小值的结点附加到Hc的末尾,如此直到一个单链表被扫描完,然后将未完的那个单链表中余下的结点附加到Hc的末尾即可。
将两表合并成一表的算法实现如下:
public LinkList<int> Merge(Linklist<int> Ha, LinkList<int> Hb)
{
LinkList<int> Hc = new LinkList<int>();
Node<int> p = Ha.Next;
Node<int> q = Hb.Next;
Node<int> s = Node<int>();
Hc = Ha;
Hc.Next = null;
while (p != null && q != null)
{
if (p.Data < q.Data)
{
s = p;
p = p.Next;
}
else
{
s = q;
q = q.Next;
}
Hc.Append(s);
}
if (p == null)
{
p = q;
}
数据结构(C#语言版)
2.3 单链表 59
while (p != null)
{
s = p;
p = p.Next;
Hc.Append(s);
}
return Hc;
}
算法的时间复杂度是O((m+n)*k),m是Ha的表长,n是Hb的表长,k是Hc的表长。
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
从上面的算法可知,把结点附加到单链表的末尾是非常花时间的,因为定位最后一个结点需要从头结点开始遍历。而把结点插入到单链表的头部要节省很多时间,因为这不需要遍历链表。但由于是把结点插入到头部,所以得到的单链表是逆序排列而不是升序排列。
把结点插入到链表Hc头部合并Ha和Hb的算法实现如下:
public LinkList<int> Merge(Linklist<int> Ha, LinkList<int> Hb)
{
LinkList<int> Hc = new LinkList<int>();
Node<int> p = Ha.Next;
Node<int> q = Hb.Next;
Node<int> s = Node<int>();
Hc = Ha;
Hc.Next = null;
//两个表非空
while (p != null && q != null)
{
if (p.Data < q.Data)
{
s = p;
p = p.Next;
}
else
{
s = q;
q = q.Next;
}
s.Next = Hc.Next;
Hc.Next = s;
}
//第2个表非空而第1个表为空
数据结构(C#语言版)
2.3 单链表 60
if (p == null)
{
p = q;
}
//将两表中的剩余数据元素附加到新表的末尾
while (p != null)
{
s = p;
p = p.Next;
s.Next = Hc.Next;
Hc.Next = s;
}
return Hc;
}
算法的时间复杂度是O(m+n),m是Ha的表长,n是Hb的表长