第二章 线性表——课后习题解练【数据结构(c语言版 第2版)】
第二章 线性表
1.选择题
(1)(2)
答案:BA
(3)
(4)(5)(6)
答案:ADB
(7)
(8)
答案:A
(9)
(10)
答案:D
(11)
(12)(13)(14)
答案:DDA
(15)
2.算法设计题
(1)
void MergeList_L(LinkList &La, LinkList &Lb, LinkList &Lc) {// 初始化指针pa = La->next; // pa 指向 La 的第一个数据结点pb = Lb->next; // pb 指向 Lb 的第一个数据结点// 使用 La 的头结点作为 Lc 的头结点Lc = pc = La;// 遍历两个链表,直到其中一个遍历完while (pa && pb) {// 如果 pa 的数据较小,将 pc 移动到新的尾结点,pa 后移指向下一个结点if (pa->data < pb->data) {pc->next = pa;pc = pa; // pc 移动到新的尾结点pa = pa->next; // pa 后移} // 如果 pb 的数据较小,将 pb 结点链接到 pc 后面(新的尾结点),pb 后移指向下一个结点else if (pa->data > pb->data) {pc->next = pb;pc = pb; // pc 移动到新的尾结点pb = pb->next; // pb 后移}// 如果数据相等,取 La 的元素,删除 Lb 的元素else {pc->next = pa;pc = pa; // pc 移动到新的尾结点pa = pa->next; // pa 后移q = pb->next; // 保存 pb 的下一个结点delete pb; // 释放当前 pb 结点pb = q; // pb 移动到下一个结点}}// 将剩余部分链接到结果链表尾部if (pa != NULL) {pc->next = pa; // 如果 pa 不为空,链接 pa 剩余部分} else {pc->next = pb; // 否则链接 pb 剩余部分}// 释放 Lb 的头结点delete Lb; }
(2)
// 函数功能:合并两个有序链表La和Lb,结果存储在Lc中(使用头插法,结果为降序) // 参数说明: // La, Lb: 待合并的两个有序链表(带头结点) // Lc: 合并后的结果链表 void union(LinkList& La, LinkList& Lb, LinkList& Lc) {// 初始化指针pa = La->next; // pa指向La的第一个数据结点pb = Lb->next; // pb指向Lb的第一个数据结点// 使用La的头结点作为Lc的头结点Lc = pc = La;Lc->next = NULL; // 初始化Lc为空链表// 循环处理,直到两个链表都遍历完while (pa || pb) {// 选择较小的结点(或剩余结点)if (!pa) { // 如果La已遍历完//if (!pa)等价于 if (pa == NULL)q = pb; // 取Lb的当前结点pb = pb->next; // pb指针后移}else if (!pb) { // 如果Lb已遍历完q = pa; // 取La的当前结点pa = pa->next; // pa指针后移}// 比较两个链表的当前结点else if (pa->data <= pb->data) { // La的结点值较小或相等q = pa; // 取La的当前结点pa = pa->next; // pa指针后移}else { // Lb的结点值较小q = pb; // 取Lb的当前结点pb = pb->next; // pb指针后移}// 将选中的结点插入到Lc的头部(头插法)q->next = Lc->next; // 新结点的next指向原Lc的第一个结点Lc->next = q; // Lc的头结点指向新结点}// 释放Lb的头结点delete Lb; }
(3)
// 函数功能:求两个有序链表La和Lb的交集,结果存储在Lc中 // 参数说明: // La, Lb: 输入的两个有序链表(带头结点) // Lc: 输出的结果链表 void Mix(LinkList& La, LinkList& Lb, LinkList& Lc) {// 初始化工作指针pa = La->next; // pa指向La的第一个数据结点pb = Lb->next; // pb指向Lb的第一个数据结点// 使用La的头结点作为Lc的头结点Lc = pc = La;// 遍历两个链表,直到其中一个遍历完while (pa && pb) {if (pa->data == pb->data) {// 情况1:当前结点值相等,将pa结点加入结果链表pc->next = pa; // 将pa链接到结果链表pc = pa; // pc移动到新的尾结点pa = pa->next; // pa后移// 释放pb的当前结点(因为值相等,只需保留一个)q = pb;pb = pb->next;delete q;}else if (pa->data < pb->data) {// 情况2:pa结点值较小,直接释放pa结点q = pa;pa = pa->next;delete q;}else {// 情况3:pb结点值较小,直接释放pb结点q = pb;pb = pb->next;delete q;}}// 释放La的剩余结点(如果有)while (pa) {q = pa;pa = pa->next;delete q;}// 释放Lb的剩余结点(如果有)while (pb) {q = pb;pb = pb->next;delete q;}// 设置结果链表的尾结点pc->next = NULL;// 释放Lb的头结点(可选)delete Lb; }
(4)
// 函数功能:求两个递增有序单链表的差集 A - B,结果存储在链表 A 中 // 参数说明: // A, B: 两个带头结点的递增有序单链表,分别存储一个集合 // n: 结果集合元素个数的引用,调用时传入一个整型变量 void Difference(LinkedList A, LinkedList B, int &n) {// 初始化工作指针p = A->next; // p 指向链表 A 的第一个数据结点q = B->next; // q 指向链表 B 的第一个数据结点 head = A; // head 指向 p 的前驱结点(即 A 的头结点)n = 0; // 初始化计数器(引用可以直接赋值)// 同步遍历两个链表,直到其中一个遍历完while (p != NULL && q != NULL) {if (p->data < q->data) {// 情况1:A 的当前结点值小于 B 的当前结点值// 该结点属于差集,保留并继续处理head = p; // head 指针后移,保持指向 p 的前驱p = p->next; // p 指针后移n++; // 差集元素个数加1(直接使用 n,不需要解引用)}else if (p->data > q->data) {// 情况2:A 的当前结点值大于 B 的当前结点值// B 需要继续向后查找可能相等的结点q = q->next; // q 指针后移}else {// 情况3:A 和 B 的当前结点值相等// 该结点不属于差集,需要从 A 中删除head->next = p->next; // 将前驱结点的 next 指向 p 的后继结点// 删除当前结点 pu = p; // 保存要删除的结点p = p->next; // p 指针后移delete u; // 释放被删除结点的内存}}// 循环结束后,如果 A 还有剩余结点,它们都属于差集while (p != NULL) {n++; // 差集元素个数加1p = p->next; // 继续遍历 A 的剩余结点} }
(6)
// 函数功能:在单链表中查找最大值 // 参数说明:L是带头结点的单链表 // 返回值:链表中最大的元素值,若链表为空则返回NULL int Max(LinkList L) {// 检查链表是否为空(只有头结点)if (L->next == NULL) {return NULL;}// 初始化指针LNode *pmax = L->next; // 假设第一个结点为最大值LNode *p = L->next->next; // 从第二个结点开始遍历// 遍历链表查找最大值while (p != NULL) {// 如果当前结点值大于已知最大值if (p->data > pmax->data) {pmax = p; // 更新最大值指针}p = p->next; // 移动到下一个结点}// 返回最大值结点的数据return pmax->data; }
(7)
// 函数功能:逆置带头结点的单链表 // 参数说明:L - 带头结点的单链表(引用传递) void inverse(LinkList &L) {// 初始化指针LNode *p = L->next; // p指向链表第一个结点L->next = NULL; // 将头结点的next置空,准备重建链表// 遍历原链表,逐个结点逆置while (p != NULL) {LNode *q = p->next; // q临时保存p的后继结点// 将当前结点p插入到新链表的头部(头结点之后)p->next = L->next; // 将p的next指向原头结点的后继L->next = p; // 头结点指向新的首元结点p = q; // p移动到原链表的下一个结点} }
(8)
void delete(LinkList &L, int mink, int maxk) {if (L == NULL || L->next == NULL) return; // 空链表直接返回LNode *pre = L; // pre始终指向当前结点的前驱LNode *p = L->next; // p从首元结点开始遍历while (p != NULL) {if (p->data > mink && p->data < maxk) {// 找到需要删除的结点pre->next = p->next; // 跳过当前结点LNode *temp = p; // 临时保存要删除的结点p = p->next; // p指针后移free(temp); // 释放内存} else {// 不需要删除的结点pre = p;p = p->next;}} }