求解一道数据结构题目,要求使用c语言。已知两个带表头节点的单链表A和B,其元素值递增排序,设计一个算法,将A和B合并成一个递减有序(相同值只保留一个)的链表C,并要求利用原表结点。要求给出问题求解的算法描述,并分析其时间复杂度。最好给一下代码。
算法描述:
时间复杂度为O(m+n),其中m和n分别为链表A和B的长度。
代码实现:
#include <stdlib.h>
struct ListNode {
int val;
struct ListNode *next;
};
struct ListNode* merge_lists(struct ListNode* A, struct ListNode* B){
// 定义链表C为空链表
struct ListNode* C = (struct ListNode*)malloc(sizeof(struct ListNode));
C->next = NULL;
// 初始化指针pa和pb
struct ListNode *pa = A->next, *pb = B->next;
// 遍历链表A和链表B
while (pa && pb) {
if (pa->val <= pb->val) {
// 将较小值的结点插入链表C的头部
struct ListNode* tmp = pa->next;
pa->next = C->next;
C->next = pa;
pa = tmp;
} else {
struct ListNode* tmp = pb->next;
pb->next = C->next;
C->next = pb;
pb = tmp;
}
}
// 处理剩余结点
if (pa) {
struct ListNode* tmp = pa->next;
pa->next = C->next;
C->next = pa;
pa = tmp;
}
if (pb) {
struct ListNode* tmp = pb->next;
pb->next = C->next;
C->next = pb;
pb = tmp;
}
// 逆序链表C
struct ListNode *prev = NULL, *curr = C->next;
while (curr) {
struct ListNode* next_node = curr->next;
curr->next = prev;
prev = curr;
curr = next_node;
}
// 删除相同值的结点
curr = prev;
while (curr && curr->next) {
if (curr->val == curr->next->val) {
curr->next = curr->next->next;
} else {
curr = curr->next;
}
}
return prev;
}
链表合并
有帮助的话 采纳一下
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node *next;
} Node, *Pnode;
typedef struct LinkList {
Pnode head;
} LinkList, *plinkList;
// 创建一个单链表
plinkList CreateList() {
plinkList L = (plinkList) malloc(sizeof(LinkList));
L->head = NULL;
return L;
}
// 向链表尾部插入一个节点
void InsertNode(plinkList L, int data) {
Pnode s = (Pnode) malloc(sizeof(Node));
s->data = data;
s->next = NULL;
if (L->head == NULL) {
L->head = s;
} else {
Pnode p = L->head;
while (p->next) p = p->next;
p->next = s;
}
}
// 输出单链表的所有节点
void PrintList(plinkList L) {
Pnode p = L->head;
while (p) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
// 归并两个递增链表A和B,产生一个递减链表C
plinkList MergeList(plinkList A, plinkList B) {
Pnode pa = A->head, pb = B->head;
Pnode pc = NULL; // C的头节点
Pnode p = NULL; // pc的尾节点
while (pa && pb) {
if (pa->data > pb->data) {
if (pc == NULL) { // C链表为空,将较大值节点设为头节点
pc = pa;
p = pa;
pa = pa->next;
} else { // 插入到C链表尾部
p->next = pa;
p = pa;
pa = pa->next;
}
} else {
if (pc == NULL) { // C链表为空,将较大值节点设为头节点
pc = pb;
p = pb;
pb = pb->next;
} else {
p->next = pb;
p = pb;
pb = pb->next;
}
}
}
// 将未到达尾节点的链表直接接到pc后面
if (pa) p->next = pa;
if (pb) p->next = pb;
return pc;
}
int main() {
plinkList A = CreateList();
InsertNode(A, 1);
InsertNode(A, 3);
InsertNode(A, 5);
PrintList(A);
plinkList B = CreateList();
InsertNode(B, 2);
InsertNode(B, 4);
InsertNode(B, 6);
InsertNode(B, 8);
PrintList(B);
plinkList C = MergeList(A, B);
PrintList(C);
return 0;
}