线性表
顺序表
优缺点
链表
头插法
尾插法
算法设计题 1 2 6 7很重要 课件上有演示过程
-
将两个递增的有序链表合并为一个递增的有序链表。要求结果链表仍使用原来两个链表的存储空间, 不另外占用其它的存储空间。表中不允许有重复的数据。
-
思路:合并后的新表使用头指针Lc指向,pa和pb分别是链表La和Lb的工作指针,初始化为相应链表的第一个结点,从第一个结点开始进行比较,当两个链表La和Lb均未到达表尾结点时,依次摘取其中较小者重新链接在Lc表的最后。如果两个表中的元素相等,只摘取La表中的元素,删除Lb表中的元素,这样确保合并后表中无重复的元素。当一个表到达表尾结点,为空时,将非空表的剩余元素直接链接在Lc表的最后。
void MergeList(LinkList &La, LinkList &Lb, LinkList &Lc) { //合并链表La和Lb,合并后的新表使用头指针Lc指向 pa = La->next; pb = Lb->next; //pa和pb分别是链表La和Lb的工作指针,初始化为相应链表的第一个结点 Lc = pc = La; //用La的头结点作为Lc的头结点 while (pa && pb) { if (pa->data < pb->data) { pc->next = pa; pc = pa; pa = pa->next; } //取较小者La中的元素,将pa链接在pc的后面,pa指针后移 else if (pa->data > pb->data) { pc->next = pb; pc = pb; pb = pb->next; } //取较小者Lb中的元素,将pb链接在pc的后面,pb指针后移 else //相等时取La中的元素,删除Lb中的元素 { pc->next = pa; pc = pa; pa = pa->next; q = pb->next; delete pb; pb = q; } } pc->next = pa ? pa : pb; //插入剩余段 delete Lb; //释放Lb的头结点 }
-
-
将两个非递减的有序链表合并为一个非递增的有序链表。要求结果链表仍使用原来两
个链表的存储空间, 不另外占用其它的存储空间。表中允许有重复的数据[题目分析]
合并后的新表使用头指针Lc指向,pa和pb分别是链表La和Lb的工作指针,初始化为相应链表的第一个结点,从第一个结点开始进行比较,当两个链表La和Lb均未到达表尾结点时,依次摘取其中较小者重新链接在Lc表的表头结点之后,如果两个表中的元素相等,只摘取La表中的元素,保留Lb表中的元素。当一个表到达表尾结点,为空时,将非空表的剩余元素依次摘取,链接在Lc表的表头结点之后。void MergeList(LinkList &La, LinkList &Lb, LinkList &Lc, ) { //合并链表La和Lb,合并后的新表使用头指针Lc指向 pa = La->next; pb = Lb->next; //pa和pb分别是链表La和Lb的工作指针,初始化为相应链表的第一个结点 Lc = pc = La; //用La的头结点作为Lc的头结点 Lc->next = NULL; while (pa || pb) { //只要存在一个非空表,用q指向待摘取的元素 if (!pa) { q = pb; pb = pb->next; } //La表为空,用q指向pb,pb指针后移 else if (!pb) { q = pa; pa = pa->next; } //Lb表为空,用q指向pa,pa指针后移 else if (pa->data <= pb->data) { q = pa; pa = pa->next; } //取较小者(包括相等)La中的元素,用q指向pa,pa指针后移 else { q = pb; pb = pb->next; } //取较小者Lb中的元素,用q指向pb,pb指针后移 q->next = Lc->next; Lc->next = q; //将q指向的结点插在Lc 表的表头结点之后 } delete Lb; //释放Lb的头结点 }
-
设计一个算法,通过一趟遍历在单链表中确定值最大的结点。
假定第一个结点中数据具有最大值,依次与下一个元素比较,若其小于下一个元素,则设其下一个元素为最大值,反复进行比较,直到遍历完该链表。
ElemType Max(LinkList L)
{
if (L->next == NULL)
return NULL;
pmax = L->next; //假定第一个结点中数据具有最大值
p = L->next->next;
while (p != NULL)
{ //如果下一个结点存在
if (p->data > pmax->data)
pmax = p; //如果p的值大于pmax的值,则重新赋值
p = p->next; //遍历链表
}
return pmax->data;
}
- 设计一个算法,通过遍历一趟,将链表中所有结点的链接方向逆转,仍利用原表的存储空间。
从首元结点开始,逐个地把链表L的当前结点p插入新的链表头部。
void inverse(LinkList &L)
{ // 逆置带头结点的单链表 L
p = L->next;
L->next = NULL;
while (p)
{
q = p->next; // q指向*p的后继
p->next = L->next;
L->next = p; // *p插入在头结点之后
p = q;
}
}
循环链表
双向链表
链表的优缺点
顺序表和链表的比较
有序表
已知线性表La 和Lb中的数据元素按值非递减有序排列,现要求将La和Lb归并为一个新的线性表Lc,且Lc中的数据元素仍按值非递减有序排列
S(n) = O(n) 顺序表和链表实现这个S(n)是不同的
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]; //为合并后的新表分配一个数组空间
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++; //LB表已到达表尾
while (pb <= pb_last)
*pc++ = *pb++; //LA表已到达表尾
} //MergeList_Sq
上面这两种都是 允许有重复数据 不允许有重复数据则要单独考虑pa->data ==pb->data 算法设计部分有笔记
``
[外链图片转存中…(img-4Lud1CrF-1609502573906)]
上面这两种都是 允许有重复数据 不允许有重复数据则要单独考虑pa->data ==pb->data 算法设计部分有笔记