c语言结点按升序排列,C语言将两个主要节点合并到升序链接列表中

14b3cf46fe6da3ee1ff501e07180e706.png

顾名思义,

合并链表是将数据按顺序存储的两个链表中的数据合并到一个链表中进行存储. 例如,在处理多项式的加法和减法时,需要合并两个多项式的数据. 合并的方法有很多: 如果存储方法不同,则可以分别提取两个链表的数据以生成新的链表,以存储原始两个链表的数据以及其中一个链表的数据. 列表可以依次插入到另一个列表中. 转到链接列表的相应位置. 当遇到相同的数据时,可以采用仅保留一个数据的方法和保留两个数据的方法. 这些差异需要针对特定​​的问题进行分析,但是细节上只有一些差异. 总体思路是相同的. 本文主要介绍在另一个链表的相应位置中插入链表的方法. 插入完成后,链表将被销毁. ,并且以相同的方式保留相同的数据.

首先让我们抛弃链接列表的操作,然后首先合并两组不同的数据,以了解应如何将按升序排列的两组数据合并为一组数据. 让我们分析这些数据集(该组的第二个数据插入第一组):

1 5 9 13 15

2 7 12

对于这组数据,我们可以轻松地说在“ 1”之前插入“ 2”,在“ 5”之前插入“ 7” ...那么我们如何得出这个结论,让我们详细描述我们现在是如何得出此结论的: “首先,遍历第一组数据并找到比要插入的数据大的第一组数据中的前一个. 数据“ i”,然后将数据插入到插入“ i”之后.

e67b2a0222cabb8e7c4b33024539d994.png

以上描述解决了插入数据的一般情况c语言链表排序算法,包括我们使用“大于此数据”来解释如何处理相同的数据,但是问题仍然存在,让我们观察以下数据集:

2 4 7 9

1 3 6 8

我们想将第二组数据插入到第一组数据中. 根据前面的陈述,找到不小于要插入的数据的第一个数据的先前数据“ i”,但是我们发现第一个数据集“第一个数据符合我们的要求,那么它自然就没有前一个数据. 这里我们给出一个解决方案: 在插入工作之前,首先比较两个链表的第一个元素,如果链表的第一个元素小于第二个链表的第一个元素,则开始合并工作,如果链表中的第一个元素不少于第二个链表中的第一个元素. 我们首先交换两个链表的头节点,使链表一变成链表二. 但是,此方法仅适用于当前情况,因为我们要实现的是将链表2的元素添加到链表1中,然后销毁链表2,这意味着我们只需要获取链表即可. 最后,只要执行我们的合并列表程序后,可以将链接列表转换为合并结果列表c语言链表排序算法,所以我们可能必须更改传递列表的头节点的值.

根据上述声明,我们必须在开始合并之前比较两个链接列表的第一个元素. 如果链表2的第一个元素大于链表1的第一个元素,则交换两个链表的控制头,然后执行后续合并工作.

以上问题已解决,但最后一种情况仍然缺失. 让我们观察以下数据集:

1df46fb5999904a7e7562ea331996836.png

1 3 4 6 7

2 6 9 10 13

我们可以看到第二组数据被顺序插入到第一组数据中. 当为“ 9”时,第一组数据没有位置可插入,但应在末尾附加,因此我们不能执行上一个操作,而应执行另一个操作. 我们的具体实现如下:

如果我们找不到比要在第一组数据中插入的数据大的数据,则将要插入的数据之后的数据与要插入的数据一起附加到第一组数据的末尾.

根据上述分析,我们需要在链表上执行四个操作: 1.找到比指定链中的目标数据大的第一个节点的前任节点; 2.将指定的元素插入指定的列表中. 3.将所有元素添加到链接列表中指定位置之后到指定链接列表的末尾; 4.交换两个链接列表的头节点.

下面,我们将分发这四个操作(注意: A_LINE是我们为方便起见而定义的结构. 只有int类型的数量和A_LINE类型的下一个成员*没有任何意义,只是为了完成合并的链接列表):

bc6eea9a3ff841604f876f6bc2b540a9.png

1. 在指定链中找到第一个节点的前一个节点,该前一个节点大于目标数据:

A_LINE *getFirstLocalBiggerThanEle(A_LINE head, A_LINE ele) {

A_LINE *p;

A_LINE *q;

for (p = head.next; p->next != NULL && ele.num >= p->num; p = p->next)

q = p;

if (p->next == NULL) {

return NOT_FOUND;

}

return q;

}

我们使用A_LINE * p遍历链接列表一,并使用A_LINE * q实时保存当前节点的前任节点. 链表尚未遍历,并且当前元素仍小于或等于目标元素,循环继续. 循环结束后,请确定循环结束的原因. 如果循环由于遍历链表而结束,则意味着在整个链表中没有比目标节点大的节点. 返回NOT_FOUND;如果找到的元素大于目标元素,则最后返回该元素的前任节点的地址“ q”.

2. 将指定元素插入到指定链表的指定位置:

void insertEleToLine(A_LINE *local, A_LINE ele) {

A_LINE *newEle;

newEle = (A_LINE *)calloc(1, sizeof(A_LINE));

newEle->next = local->next;

local->next = newEle;

newEle->num = ele.num;

}

在第一步中,我们已经可以获取需要插入的位置的第一个地址,然后我们将在下一步中完成插入. 对于那些研究了链表的人来说并不困难. 本文将不专注于此.

82610e6d295245ecd1f038118786ffea.gif

3. 将一条数据附加到指定的链接列表的末尾:

void appendLineToLineEnd(A_LINE *line, A_LINE targetLine) {

A_LINE *tarP;

for (tarP = targetLine.next; tarP->next != NULL; tarP = tarP->next)

;

tarP->next = line;

}

A_LINE *此处给出的行表示要插入的链表的第一个元素的第一个地址,而targetLine表示要插入的链表的头节点. 首先找到目标链接列表的最后一个节点的第一个地址,然后将要插入到链接列表的最后一个节点的下一个成员更改为链接列表的第一个元素的第一个地址.

但是这里有一个问题. 这里的分配相当于将链接列表2的部分节点直接直接放置在链接列表一的末尾. 它不是副本,然后附加到链接列表一的末尾,从而使链接列表二. 一些节点属于链表1和链表2,链表2将在最后释放,然后它的最后几个节点也将被释放. 为了防止这种情况的发生,我们必须将列表2中要插入到列表1中的部分节点的前任节点的下一个成员分配为NULL,这等效于从列表中删除该节点的该部分. 清单2,但这不会导致内存泄漏. 这些节点连接到链表一的末尾,因此当链表一被释放时,这些节点仍将被释放.

4. 交换两个链接列表的头节点:

void exchangeLine(A_LINE *head1, A_LINE *head2) {

A_LINE temp;

temp = *head1;

*head1 = *head2;

*head2 = temp;

}

5. 合并链表的完整代码:

void margeLine(A_LINE *targetLine, A_LINE *resourceLine) {

A_LINE *tarP = targetLine->next;

A_LINE *srcP = resourceLine->next;

A_LINE *srcPreP;

A_LINE *local;

if (tarP->num >= srcP->num) {

exchangeLine(targetLine, resourceLine);

}

for (srcP = srcPreP = resourceLine->next; srcP != NULL; srcP = srcP->next) {

local = getFirstLocalBiggerThanEle(*targetLine, *srcP);

if (local != NOT_FOUND) {

insertEleToLine(local, *srcP);

}

else {

appendLineToLineEnd(srcPreP->next, *targetLine);

srcPreP->next = NULL;

destoryLine(resourceLine);

return;

}

srcPreP = srcP;

}

destoryLine(resourceLine);

}

最后,我们给出整体可测试的代码:

本文来自电脑杂谈,转载请注明本文网址:

http://www.pc-fly.com/a/jisuanjixue/article-180269-1.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值