试写一算法将两个递增有序的带头结点的单链表合并为一个递增有序的带头结点的单链表。
(利用原表结点空间)
比如现在要将下面两个链表合并,这里是要求利用原表空间
我们先创建一个辅助的链表L3,用p和q分别标记L1和L2的数据元素,tmp标记L3的尾结点
比较p和q数据大小,显然这里是p更小,让L3连上p
p=p->next
再次比较p和q元素大小,这里p>q
tmp尾部接上q
tmp=tmp->next
q=q->next;
后面的以此类推
代码如下:
//L1和L2递增,利用原表空间进行合并成一个递增序列
void merge(LinkList L1,LinkList L2,LinkList* L3) {//我们这里把L2的各个元素插到L1上
LNode* tmp = *L3;
LNode* p = L1->next;
LNode* q = L2->next;
while (p&&q) {
if (p->data < q->data) {
tmp->next = p;
tmp = tmp->next;
p = p->next;
}
else {
tmp->next = q;
tmp = tmp->next;
q = q->next;
}
}
//到这里有可能是因为某个链读完了,另一个链还没有读完
//把没读完的加到L3上
while (p) {
tmp->next = p;
tmp = tmp->next;
p = p->next;
}
while (q) {
tmp->next = q;
tmp = tmp->next;
q = q->next;
}
}
int main()
{
LinkList L1;
LinkList L2;
InitList2(&L1);//初始化一个带头结点的L1
InitList3(&L2);
printf("初始链表L1为:");//1,2,3,4,5,6,7,8,9,10
print2(L1);
printf("\n");
printf("初始链表L2为:");//0,2,2,4,4,5
print2(L2);
LinkList L3=(LNode*)malloc(sizeof(LNode));
merge(L1, L2,&L3);
printf("\n");
printf("L1和L2合并后为:");
print2(L3);
}
注:用到的创建链表和打印链表的函数
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdbool.h>
#include<malloc.h>
//单链表定义
//链表结点
int A[10] = { 1,2,3,4,5,6,7,8,9,10 };
int B[6] = { 0,2,2,4,4,5 };
typedef struct {//定义单链表结点类型
int data;//数据域
struct LNode *next;//指针域
}LNode, *LinkList;
//带头结点初始化-尾插法
void InitList2(LinkList* L) {
(*L) = (LNode*)malloc(sizeof(LNode));
(*L)->next = NULL;
LNode* rear = (*L);//标记表尾
int i = 0;
for (i = 0;i < 10;i++) {
LNode* p = (LNode*)malloc(sizeof(LNode));//创建一个新结点
p->data = A[i];//新结点赋值
rear->next = p;//接到L上
rear = p;//标记表尾
}
rear->next = NULL;
}
//带头结点初始化-尾插法
void InitList3(LinkList* L) {
(*L) = (LNode*)malloc(sizeof(LNode));
(*L)->next = NULL;
LNode* rear = (*L);//标记表尾
int i = 0;
for (i = 0;i < 6;i++) {
LNode* p = (LNode*)malloc(sizeof(LNode));//创建一个新结点
p->data = B[i];//新结点赋值
rear->next = p;//接到L上
rear = p;//标记表尾
}
rear->next = NULL;
}
void print2(LinkList L) {//打印带头结点的链表
LNode* i = L->next;//用i指针遍历整个链表
while (i != NULL) {
printf("%d ", i->data);
i = i->next;
}
}