这篇文章的代码是有序链表尽可能少的借助额外空间的归并:
我们提供两个有序升链表A和B(后一个元素不小于前一个元素)。
原理很简单:
假如有一个有序升链表A和一个除头节点之外只含有一个节点的链表B,并且链表B存储的唯一一个数值不小于A链表末端的数值,那么为了将两个链表归并我们需要将B的节点(当然没有头节点)接到A的末尾。
那么整个归并过程可以简化为:假设p1为链表A的中间指针,p1将链表A分为前后两段前段记为A1。记B的第一个数据的地址为p2,且p1指向的数据不大于p2,但是p1的下一个节点的数值比p2的数值大。那么我们要做的是将A1接到p2后边,重新记录第一个节点的指针p2和中间指针p1。当p1不满足条件时p1后移。重复上述过程直到p1的下一个节点为空。
代码如下:
#include<iostream>
#define datatype int
#include<cstdlib>
using namespace std;
//一个节点,包含数据和下个节点的地址
typedef struct LNode{
datatype data;//数据
int len;
struct LNode* next;//下一个数据的地址
}LNode,*PLink;//给指针类型起别名
void InitList(PLink &l)
{
l= new LNode;//申请一片空间,并让l指向这片空间(创立头节点)
l->next=nullptr;//头节点的下一个地址不存在
l->len=0;
}
PLink SortLink(PLink A,PLink B)//升序链表的归并排序
{
PLink p1=A->next;
PLink p2=B->next;
PLink temp=nullptr;
if(p1->val>p2->val) //为了方便后续操作我们要确保p1指向的值不大于p2
{
p1=B->next;
p2=A->next;
}
while(true)
{
if(p1->next==nullptr || p2->next==nullptr) break;//归并结束跳出循环
if(p1->next->val > p2->next->val)
{
temp=p1->next;//记录链表地址
p1->next=p2;
p1=p1->next;//重新记录p1
p2=temp;
}
else p1=p1->next;
}
if(A->next->val>B->next->val) return B;
return A;
}