问题描述:输入两个有序链表,将它们合并成一个有序链表。
我们采用的方法,主要是创建一个新的链表,在创建时新加入的表元从原本的两个链表中选取,由于链表本身是有序的,故只需不断地将两个表元进行对比,较小者存入新链表,较大者下一轮再对比。关于链表的一些基本的函数,在上一篇博客中都有提到。
以下是完整的代码,其中mergeLists是主要的合并函数:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int value;
struct Node* next;
} Node;
Node* createNode(int value) {
Node* newNode = (Node*)malloc(sizeof(Node));
if (newNode == NULL) {
printf("Memory allocation failed.\n");
exit(1);
}
newNode->value = value;
newNode->next = NULL;
return newNode;
}
Node* createOriginalList() {
Node* head = NULL;
Node* tail = NULL;
int n;
printf("Enter the number of nodes in the linked list:");
scanf("%d", &n);
printf("Enter the values of the linked list nodes:\n");
for (int i = 0; i < n; i++) {
int value;
printf("Value of Node %d:", i + 1);
scanf("%d", &value);
Node* newNode = createNode(value);
if (NULL == head) {
head = newNode;
tail = newNode;
}
else {
tail->next = newNode;
tail = newNode;
}
}
return head;
}
//合并两个有序链表
Node* mergeLists(Node* list1, Node* list2) {
Node* result = NULL;//新链表的头尾指针
Node* tail = NULL;
Node* currentS1 = list1;
Node* currentS2 = list2;
//双指针分别遍历S1和S2,直到其中一个被遍历完,按从小到大的顺序添加节点到结果中
while (currentS1 != NULL && currentS2 != NULL) {
if (currentS1->value < currentS2->value) {
Node* newNode = createNode(currentS1->value);
if (result == NULL) {//插入到头表元的情况
result = newNode;
tail = newNode;
}
else {//直接从末尾插入
tail->next = newNode;
tail = newNode;
}
currentS1 = currentS1->next;//向后历遍
}
else if (currentS1->value > currentS2->value) {
Node* newNode = createNode(currentS2->value);
if (result == NULL) {
result = newNode;
tail = newNode;
}
else {
tail->next = newNode;
tail = newNode;
}
currentS2 = currentS2->next;
}
else {
//两个节点值相等,都要插入
Node* newNode1 = createNode(currentS1->value);
if (result == NULL) {
result = newNode1;
tail = newNode1;
}
else {
tail->next = newNode1;
tail = newNode1;
}
Node* newNode2 = createNode(currentS2->value);
tail->next = newNode2;
tail = newNode2;
currentS1 = currentS1->next;
currentS2 = currentS2->next;
}
}
while (currentS1 != NULL) {//链接链表1剩下的元素(如果有)
Node* newNode = createNode(currentS1->value);
if (result == NULL) {
result = newNode;
tail = newNode;
}
else {
tail->next = newNode;
tail = newNode;
}
currentS1 = currentS1->next;
}
while (currentS2 != NULL) {//链接链表2剩下的元素(如果有)
Node* newNode = createNode(currentS2->value);
if (result == NULL) {
result = newNode;
tail = newNode;
}
else {
tail->next = newNode;
tail = newNode;
}
currentS2 = currentS2->next;
}
return result;
}
void printList(Node* head) {
if (head == NULL) {
printf("链表为空。\n");
return;
}
Node* current = head;
while (current != NULL) {
printf("%d ", current->value);
current = current->next;
}
printf("\n");
}
void freeList(Node* head) {
Node* current = head;
Node* next;
while (current != NULL) {
next = current->next;
free(current);
current = next;
}
}
int main() {
printf("Create the first sorted linked list:\n");
Node* list1 = createOriginalList();
printf("Create the second sorted linked list:\n");
Node* list2 = createOriginalList();
Node* mergedList = mergeLists(list1, list2);
printf("Merged sorted linked list: ");
printList(mergedList);
freeList(mergedList);
freeList(list2);
freeList(list1);
return 0;
}
以下是输入的样例:
这里,对于更多的情况下,我们输入的链表不一定是有序的。这时再需要将它们合并为有序的链表,可以直接在输入创建原始链表的时候,直接创建成有序的链表。之后,可以像上述方法一样合并,或者(在没有新链表要求的时候)直接将有序的链表2插入链表1中,以下为完整代码(使用的方法是后者):
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
typedef struct Node {
int value;
struct Node* next;
} Node;
Node* creatsortedlist()
{
int n;
printf("Enter the number of nodes in the linked list:");
scanf("%d", & n);
Node* head = NULL, * p, * new = NULL, * old = NULL;
printf("Enter the values of the linked list nodes:\n");
for (int i = 0; i < n; i++) {
p = (Node*)malloc(sizeof(Node));
if (p == NULL) {
printf("Memory allocation failed.\n");
exit(1);
}
printf("Value of Node %d:", i + 1);
scanf("%d", &p->value);
//对输入的每一个节点,判断其按值大小的插入位置
new = head;
while (new != NULL && p->value > new->value)
{
old = new;
new = new->next;
}
//old记录插入位置之前的节点
//new记录插入位置之后的节点
if (new == head)
{
head = p;
}
else
old->next = p;
p->next = new;
}
return head;
}
Node* merged_sortedlink(Node* head1, Node* head2)
{
Node* p, * new = NULL, * old = NULL, * p2 = head2;
while (p2 != NULL)
{
//顺序将链表2中的每一项插入到链表1中
p = (Node*)malloc(sizeof(Node));
if (p == NULL) {
printf("Memory allocation failed.\n");
exit(1);
}
p->value = p2->value;
new = head1;
while (new != NULL && p->value > new->value)
{
old = new;
new = new->next;
}
if (new == head1)
{
head1 = p;
}
else
old->next = p;
p->next = new;
p2 = p2->next;
}
return head1;
}
void printList(Node* head) {
if (head == NULL) {
printf("链表为空。\n");
return;
}
Node* prhead = head;
while (prhead != NULL) {
printf("%d ", prhead->value);
prhead = prhead->next;
}
printf("\n");
}
void freeList(Node* head) {
Node* current = head;
Node* next;
while (current != NULL) {
next = current->next;
free(current);
current = next;
}
}
int main()
{
printf("Create the first sorted linked list:");
Node* head1 = creatsortedlist();
printf("Create the second sorted linked list:");
Node* head2 = creatsortedlist();
Node* head = merged_sortedlink(head1, head2);
printf("Merged sorted linked list: ");
printList(head);
freeList(head1);
freeList(head2);
return 0;
}
以下是样例输入: