1.编写算法,在单链表中查找第一个值为x的结点,并输出其前驱和后继的存储位置。
#include <stdio.h>
#include <stdlib.h>
// 链表节点定义
typedef struct Node {
int data;
struct Node *next;
} Node;
// 链表定义
typedef struct {
Node *head;
} LinkedList;
// 初始化链表
void initLinkedList(LinkedList *list) {
list->head = NULL;
}
// 在链表尾部插入节点
void insertAtTail(LinkedList *list, int value) {
Node *newNode = (Node *)malloc(sizeof(Node));
if (!newNode) {
printf("Memory error\n");
return;
}
newNode->data = value;
newNode->next = NULL;
if (list->head == NULL) {
list->head = newNode;
} else {
Node *temp = list->head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
}
}
// 查找值为 x 的节点并输出其前驱和后继的存储位置
void findNodeAndPrintPredecessorSuccessor(LinkedList *list, int x) {
if (list->head == NULL) {
printf("The linked list is empty.\n");
return;
}
Node *prev = NULL;
Node *current = list->head;
Node *next = current->next;
while (current != NULL) {
if (current->data == x) {
printf("Node with value %d found.\n", x);
if (prev != NULL) {
printf("Predecessor address: %p\n", (void *)prev);
} else {
printf("No predecessor (it's the head node).\n");
}
if (next != NULL) {
printf("Successor address: %p\n", (void *)next);
} else {
printf("No successor (it's the last node).\n");
}
return;
}
prev = current;
current = next;
if (next != NULL) {
next = next->next;
}
}
printf("Node with value %d not found.\n", x);
}
// 打印链表的内容
void printLinkedList(const LinkedList *list) {
Node *temp = list->head;
while (temp != NULL) {
printf("%d -> ", temp->data);
temp = temp->next;
}
printf("NULL\n");
}
int main() {
LinkedList list;
initLinkedList(&list);
// 用户输入链表中的元素
int n;
printf("Enter the number of elements in the linked list: ");
scanf("%d", &n);
printf("Enter the elements of the linked list:\n");
for (int i = 0; i < n; i++) {
int value;
scanf("%d", &value);
insertAtTail(&list, value);
}
printf("Original linked list: ");
printLinkedList(&list);
int x;
printf("Enter the value to search for: ");
scanf("%d", &x);
findNodeAndPrintPredecessorSuccessor(&list, x);
// 清理内存
Node *current = list.head;
while (current != NULL) {
Node *temp = current;
current = current->next;
free(temp);
}
return 0;
}
数据结构定义
// 链表节点定义
typedef struct Node {
int data;
struct Node *next;
} Node;
// 链表定义
typedef struct {
Node *head;
} LinkedList;
Node
结构体定义了一个链表节点,包含两个成员:int data
:存储节点的数据。struct Node *next
:指向下一个节点的指针。
LinkedList
结构体定义了一个链表,包含一个成员:Node *head
:指向链表头节点的指针。
初始化链表
// 初始化链表
void initLinkedList(LinkedList *list) {
list->head = NULL;
}
- 将链表的头节点初始化为
NULL
,表示链表为空。
在链表尾部插入节点
// 在链表尾部插入节点
void insertAtTail(LinkedList *list, int value) {
Node *newNode = (Node *)malloc(sizeof(Node));
if (!newNode) {
printf("Memory error\n");
return;
}
newNode->data = value;
newNode->next = NULL;
if (list->head == NULL) {
list->head = newNode;
} else {
Node *temp = list->head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
}
}
- 创建一个新的节点
newNode
,并分配内存。 - 将新节点的数据设置为
value
,并将next
指针设置为NULL
。 - 如果链表为空(即
head
为NULL
),将新节点设置为头节点。 - 否则,遍历链表找到最后一个节点,并将新节点链接到最后一个节点的
next
指针上。
查找值为 x 的节点并输出其前驱和后继的存储位置
// 在链表尾部插入节点
void insertAtTail(LinkedList *list, int value) {
Node *newNode = (Node *)malloc(sizeof(Node));
if (!newNode) {
printf("Memory error\n");
return;
}
newNode->data = value;
newNode->next = NULL;
if (list->head == NULL) {
list->head = newNode;
} else {
Node *temp = list->head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
}
}
- 检查链表是否为空,如果是,则输出提示信息并返回。
- 初始化三个指针:
prev
:前一个节点,初始为NULL
。current
:当前节点,初始为头节点。next
:下一个节点,初始为头节点的下一个节点。
- 使用
while
循环遍历链表:- 如果当前节点的数据等于
x
,输出当前节点的信息:- 输出当前节点的值。
- 如果有前一个节点,输出前一个节点的地址;否则输出没有前驱。
- 如果有下一个节点,输出下一个节点的地址;否则输出没有后继。
- 移动
prev
和current
指针。 - 如果
next
不为NULL
,移动next
指针。
- 如果当前节点的数据等于
- 如果遍历完整个链表都没有找到值为
x
的节点,输出提示信息。
打印链表的内容
// 打印链表的内容
void printLinkedList(const LinkedList *list) {
Node *temp = list->head;
while (temp != NULL) {
printf("%d -> ", temp->data);
temp = temp->next;
}
printf("NULL\n");
}
- 遍历链表,逐个打印每个节点的数据。
- 打印完所有节点后,输出一个换行符。
主函数
int main() {
LinkedList list;
initLinkedList(&list);
// 用户输入链表中的元素
int n;
printf("Enter the number of elements in the linked list: ");
scanf("%d", &n);
printf("Enter the elements of the linked list:\n");
for (int i = 0; i < n; i++) {
int value;
scanf("%d", &value);
insertAtTail(&list, value);
}
printf("Original linked list: ");
printLinkedList(&list);
int x;
printf("Enter the value to search for: ");
scanf("%d", &x);
findNodeAndPrintPredecessorSuccessor(&list, x);
// 清理内存
Node *current = list.head;
while (current != NULL) {
Node *temp = current;
current = current->next;
free(temp);
}
return 0;
}
- 初始化一个链表
list
。 - 提示用户输入链表中元素的数量
n
。 - 提示用户输入链表中的每个元素,并调用
insertAtTail
函数将其插入到链表中。 - 打印原始链表的内容。
- 提示用户输入要查找的值
x
,并调用findNodeAndPrintPredecessorSuccessor
函数查找值为x
的节点并输出其前驱和后继的存储位置。 - 清理链表中所有节点的内存,防止内存泄漏。
- 返回0,表示程序正常结束。
示例运行
假设用户输入以下数据:
Enter the number of elements in the linked list: 5
Enter the elements of the linked list:
3 1 4 1 5
Original linked list: 3 -> 1 -> 4 -> 1 -> 5 -> NULL
Enter the value to search for: 4
Node with value 4 found.
Predecessor address: 0x5555555592b0
Successor address: 0x5555555592d0
在这个示例中:
- 用户输入了5个元素
[3, 1, 4, 1, 5]
。 - 原始链表为
3 -> 1 -> 4 -> 1 -> 5 -> NULL
。 - 用户输入要查找的值
4
,程序找到值为4
的节点,并输出其前驱和后继的存储地址。
2.在单循环链表中,编写算法实现将链表中数据域为奇数的结点移至表头,将链表中数据域为偶数的结点移至表尾。
#include <stdio.h>
#include <stdlib.h>
// 链表节点定义
typedef struct Node {
int data;
struct Node *next;
} Node;
// 链表定义
typedef struct {
Node *head;
} LinkedList;
// 初始化链表
void initLinkedList(LinkedList *list) {
list->head = NULL;
}
// 在链表尾部插入节点
void insertAtTail(LinkedList *list, int value) {
Node *newNode = (Node *)malloc(sizeof(Node));
if (!newNode) {
printf("Memory error\n");
return;
}
newNode->data = value;
if (list->head == NULL) {
list->head = newNode;
newNode->next = newNode; // 循环链表特性
} else {
Node *temp = list->head;
while (temp->next != list->head) {
temp = temp->next;
}
temp->next = newNode;
newNode->next = list->head; // 循环链表特性
}
}
// 调整链表顺序,将奇数节点移至表头,偶数节点移至表尾
void rearrangeLinkedList(LinkedList *list) {
if (list->head == NULL || list->head->next == list->head) {
return; // 如果链表为空或只有一个元素,则无需处理
}
Node *oddHead = NULL;
Node *oddTail = NULL;
Node *evenHead = NULL;
Node *evenTail = NULL;
Node *current = list->head;
Node *start = list->head;
do {
if (current->data % 2 == 0) { // 偶数节点
if (evenHead == NULL) {
evenHead = current;
evenTail = current;
} else {
evenTail->next = current;
evenTail = current;
}
} else { // 奇数节点
if (oddHead == NULL) {
oddHead = current;
oddTail = current;
} else {
oddTail->next = current;
oddTail = current;
}
}
current = current->next;
} while (current != start);
// 连接奇数部分和偶数部分
if (oddHead != NULL) {
oddTail->next = evenHead;
list->head = oddHead;
} else {
list->head = evenHead;
}
if (evenTail != NULL) {
evenTail->next = list->head; // 循环链表特性
}
}
// 打印链表的内容
void printLinkedList(const LinkedList *list) {
if (list->head == NULL) {
printf("NULL\n");
return;
}
Node *temp = list->head;
do {
printf("%d -> ", temp->data);
temp = temp->next;
} while (temp != list->head);
printf("HEAD\n");
}
int main() {
LinkedList list;
initLinkedList(&list);
// 用户输入链表中的元素
int n;
printf("Enter the number of elements in the circular linked list: ");
scanf("%d", &n);
printf("Enter the elements of the circular linked list:\n");
for (int i = 0; i < n; i++) {
int value;
scanf("%d", &value);
insertAtTail(&list, value);
}
printf("Original circular linked list: ");
printLinkedList(&list);
rearrangeLinkedList(&list);
printf("Rearranged circular linked list: ");
printLinkedList(&list);
// 清理内存
if (list.head != NULL) {
Node *current = list.head;
Node *start = list.head;
do {
Node *temp = current;
current = current->next;
free(temp);
} while (current != start);
}
return 0;
}
数据结构定义
// 链表节点定义
typedef struct Node {
int data;
struct Node *next;
} Node;
// 链表定义
typedef struct {
Node *head;
} LinkedList;
Node
结构体定义了一个链表节点,包含两个成员:int data
:存储节点的数据。struct Node *next
:指向下一个节点的指针。
LinkedList
结构体定义了一个链表,包含一个成员:Node *head
:指向链表头节点的指针。
初始化链表
// 初始化链表
void initLinkedList(LinkedList *list) {
list->head = NULL;
}
- 将链表的头节点初始化为
NULL
,表示链表为空。
在链表尾部插入节点
// 在链表尾部插入节点
void insertAtTail(LinkedList *list, int value) {
Node *newNode = (Node *)malloc(sizeof(Node));
if (!newNode) {
printf("Memory error\n");
return;
}
newNode->data = value;
if (list->head == NULL) {
list->head = newNode;
newNode->next = newNode; // 循环链表特性
} else {
Node *temp = list->head;
while (temp->next != list->head) {
temp = temp->next;
}
temp->next = newNode;
newNode->next = list->head; // 循环链表特性
}
}
- 创建一个新的节点
newNode
,并分配内存。 - 将新节点的数据设置为
value
。 - 如果链表为空(即
head
为NULL
),将新节点设置为头节点,并将next
指针指向自身,形成一个单节点的循环链表。 - 否则,遍历链表找到最后一个节点,并将新节点链接到最后一个节点的
next
指针上,同时将新节点的next
指针指向头节点,保持循环特性。
调整链表顺序,将奇数节点移至表头,偶数节点移至表尾
// 调整链表顺序,将奇数节点移至表头,偶数节点移至表尾
void rearrangeLinkedList(LinkedList *list) {
if (list->head == NULL || list->head->next == list->head) {
return; // 如果链表为空或只有一个元素,则无需处理
}
Node *oddHead = NULL;
Node *oddTail = NULL;
Node *evenHead = NULL;
Node *evenTail = NULL;
Node *current = list->head;
Node *start = list->head;
do {
if (current->data % 2 == 0) { // 偶数节点
if (evenHead == NULL) {
evenHead = current;
evenTail = current;
} else {
evenTail->next = current;
evenTail = current;
}
} else { // 奇数节点
if (oddHead == NULL) {
oddHead = current;
oddTail = current;
} else {
oddTail->next = current;
oddTail = current;
}
}
current = current->next;
} while (current != start);
// 连接奇数部分和偶数部分
if (oddHead != NULL) {
oddTail->next = evenHead;
list->head = oddHead;
} else {
list->head = evenHead;
}
if (evenTail != NULL) {
evenTail->next = list->head; // 循环链表特性
}
}
- 检查链表是否为空或只有一个节点,如果是,则直接返回。
- 初始化四个指针:
oddHead
和oddTail
:分别指向奇数节点的头部和尾部。evenHead
和evenTail
:分别指向偶数节点的头部和尾部。
- 使用
do-while
循环遍历链表:- 如果当前节点的数据是偶数,将其链接到偶数部分。
- 如果当前节点的数据是奇数,将其链接到奇数部分。
- 循环结束后,连接奇数部分和偶数部分:
- 如果有奇数部分,将奇数部分的尾部链接到偶数部分的头部,并将链表的头节点设置为奇数部分的头部。
- 如果没有奇数部分,将链表的头节点设置为偶数部分的头部。
- 如果有偶数部分,将偶数部分的尾部链接到链表的头节点,保持循环特性。
打印链表的内容
// 打印链表的内容
void printLinkedList(const LinkedList *list) {
if (list->head == NULL) {
printf("NULL\n");
return;
}
Node *temp = list->head;
do {
printf("%d -> ", temp->data);
temp = temp->next;
} while (temp != list->head);
printf("HEAD\n");
}
- 检查链表是否为空,如果是,则输出
NULL
并返回。 - 使用
do-while
循环遍历链表,逐个打印每个节点的数据。 - 循环结束后,输出一个换行符。
主函数
int main() {
LinkedList list;
initLinkedList(&list);
// 用户输入链表中的元素
int n;
printf("Enter the number of elements in the circular linked list: ");
scanf("%d", &n);
printf("Enter the elements of the circular linked list:\n");
for (int i = 0; i < n; i++) {
int value;
scanf("%d", &value);
insertAtTail(&list, value);
}
printf("Original circular linked list: ");
printLinkedList(&list);
rearrangeLinkedList(&list);
printf("Rearranged circular linked list: ");
printLinkedList(&list);
// 清理内存
if (list.head != NULL) {
Node *current = list.head;
Node *start = list.head;
do {
Node *temp = current;
current = current->next;
free(temp);
} while (current != start);
}
return 0;
}
- 初始化一个链表
list
。 - 提示用户输入链表中元素的数量
n
。 - 提示用户输入链表中的每个元素,并调用
insertAtTail
函数将其插入到链表中。 - 打印原始链表的内容。
- 调用
rearrangeLinkedList
函数调整链表顺序,将奇数节点移至表头,偶数节点移至表尾。 - 再次打印链表的内容,显示调整后的结果。
- 清理链表中所有节点的内存,防止内存泄漏。
- 返回0,表示程序正常结束。
示例运行
假设用户输入以下数据:
Enter the number of elements in the circular linked list: 5
Enter the elements of the circular linked list:
3 1 4 1 5
Original circular linked list: 3 -> 1 -> 4 -> 1 -> 5 -> HEAD
Rearranged circular linked list: 3 -> 1 -> 1 -> 5 -> 4 -> HEAD
在这个示例中:
- 用户输入了5个元素
[3, 1, 4, 1, 5]
。 - 原始循环链表为
3 -> 1 -> 4 -> 1 -> 5 -> HEAD
。 - 调整链表顺序后,奇数节点
[3, 1, 1, 5]
被移至表头,偶数节点[4]
被移至表尾,结果为3 -> 1 -> 1 -> 5 -> 4 -> HEAD
。
3.将两个有序线性表 LIST 1=(a1,a2,...,an)和LIST 2=(b1,b2,...bm)链接成一个有序线性表LIST3 ,并删除 LIST 3中相同的结点,即 LIST3中若有多个结点具有相同的数据域,只保留一个结点,使得 LIST3中所有结点的数据域都不相同。在采用顺序表和单链表两种形式下分别设计C语言算法实现上述功能。
顺序表
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 1000 // 最大容量
// 顺序表类型定义
typedef struct {
int data[MAX_SIZE]; // 存储数据的数组
int length; // 当前长度
} SeqList;
// 初始化顺序表
void initSeqList(SeqList *list) {
list->length = 0;
}
// 插入元素到顺序表
void insertElement(SeqList *list, int value) {
if (list->length >= MAX_SIZE) {
printf("Sequence list is full.\n");
return;
}
list->data[list->length++] = value;
}
// 合并两个有序顺序表并删除重复节点
void mergeSeqLists(SeqList *list1, SeqList *list2, SeqList *list3) {
int i = 0, j = 0, k = 0;
while (i < list1->length && j < list2->length) {
if (list1->data[i] < list2->data[j]) {
if (k == 0 || list1->data[i] != list3->data[k - 1]) {
list3->data[k++] = list1->data[i];
}
i++;
} else if (list1->data[i] > list2->data[j]) {
if (k == 0 || list2->data[j] != list3->data[k - 1]) {
list3->data[k++] = list2->data[j];
}
j++;
} else {
if (k == 0 || list1->data[i] != list3->data[k - 1]) {
list3->data[k++] = list1->data[i];
}
i++;
j++;
}
}
while (i < list1->length) {
if (k == 0 || list1->data[i] != list3->data[k - 1]) {
list3->data[k++] = list1->data[i];
}
i++;
}
while (j < list2->length) {
if (k == 0 || list2->data[j] != list3->data[k - 1]) {
list3->data[k++] = list2->data[j];
}
j++;
}
list3->length = k;
}
// 打印顺序表的内容
void printSeqList(const SeqList *list) {
for (int i = 0; i < list->length; i++) {
printf("%d ", list->data[i]);
}
printf("\n");
}
int main() {
SeqList list1, list2, list3;
initSeqList(&list1);
initSeqList(&list2);
initSeqList(&list3);
// 用户输入顺序表1中的元素
int n1;
printf("Enter the number of elements in LIST1: ");
scanf("%d", &n1);
printf("Enter the elements of LIST1:\n");
for (int i = 0; i < n1; i++) {
int value;
scanf("%d", &value);
insertElement(&list1, value);
}
// 用户输入顺序表2中的元素
int n2;
printf("Enter the number of elements in LIST2: ");
scanf("%d", &n2);
printf("Enter the elements of LIST2:\n");
for (int i = 0; i < n2; i++) {
int value;
scanf("%d", &value);
insertElement(&list2, value);
}
printf("LIST1: ");
printSeqList(&list1);
printf("LIST2: ");
printSeqList(&list2);
mergeSeqLists(&list1, &list2, &list3);
printf("Merged and deduplicated LIST3: ");
printSeqList(&list3);
return 0;
单链表
#include <stdio.h>
#include <stdlib.h>
// 链表节点定义
typedef struct Node {
int data;
struct Node *next;
} Node;
// 链表定义
typedef struct {
Node *head;
} LinkedList;
// 初始化链表
void initLinkedList(LinkedList *list) {
list->head = NULL;
}
// 在链表尾部插入节点
void insertAtTail(LinkedList *list, int value) {
Node *newNode = (Node *)malloc(sizeof(Node));
if (!newNode) {
printf("Memory error\n");
return;
}
newNode->data = value;
newNode->next = NULL;
if (list->head == NULL) {
list->head = newNode;
} else {
Node *temp = list->head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
}
}
// 合并两个有序单链表并删除重复节点
void mergeLinkedLists(LinkedList *list1, LinkedList *list2, LinkedList *list3) {
Node *p1 = list1->head;
Node *p2 = list2->head;
Node *tail = NULL;
Node *prev = NULL;
while (p1 != NULL && p2 != NULL) {
if (p1->data < p2->data) {
if (prev == NULL || p1->data != prev->data) {
if (tail == NULL) {
tail = p1;
list3->head = p1;
} else {
tail->next = p1;
tail = p1;
}
}
prev = p1;
p1 = p1->next;
} else if (p1->data > p2->data) {
if (prev == NULL || p2->data != prev->data) {
if (tail == NULL) {
tail = p2;
list3->head = p2;
} else {
tail->next = p2;
tail = p2;
}
}
prev = p2;
p2 = p2->next;
} else {
if (prev == NULL || p1->data != prev->data) {
if (tail == NULL) {
tail = p1;
list3->head = p1;
} else {
tail->next = p1;
tail = p1;
}
}
prev = p1;
p1 = p1->next;
p2 = p2->next;
}
}
while (p1 != NULL) {
if (prev == NULL || p1->data != prev->data) {
if (tail == NULL) {
tail = p1;
list3->head = p1;
} else {
tail->next = p1;
tail = p1;
}
}
prev = p1;
p1 = p1->next;
}
while (p2 != NULL) {
if (prev == NULL || p2->data != prev->data) {
if (tail == NULL) {
tail = p2;
list3->head = p2;
} else {
tail->next = p2;
tail = p2;
}
}
prev = p2;
p2 = p2->next;
}
if (tail != NULL) {
tail->next = NULL;
}
}
// 打印链表的内容
void printLinkedList(const LinkedList *list) {
Node *temp = list->head;
while (temp != NULL) {
printf("%d -> ", temp->data);
temp = temp->next;
}
printf("NULL\n");
}
int main() {
LinkedList list1, list2, list3;
initLinkedList(&list1);
initLinkedList(&list2);
initLinkedList(&list3);
// 用户输入链表1中的元素
int n1;
printf("Enter the number of elements in LIST1: ");
scanf("%d", &n1);
printf("Enter the elements of LIST1:\n");
for (int i = 0; i < n1; i++) {
int value;
scanf("%d", &value);
insertAtTail(&list1, value);
}
// 用户输入链表2中的元素
int n2;
printf("Enter the number of elements in LIST2: ");
scanf("%d", &n2);
printf("Enter the elements of LIST2:\n");
for (int i = 0; i < n2; i++) {
int value;
scanf("%d", &value);
insertAtTail(&list2, value);
}
printf("LIST1: ");
printLinkedList(&list1);
printf("LIST2: ");
printLinkedList(&list2);
mergeLinkedLists(&list1, &list2, &list3);
printf("Merged and deduplicated LIST3: ");
printLinkedList(&list3);
// 清理内存
Node *current = list1.head;
while (current != NULL) {
Node *temp = current;
current = current->next;
free(temp);
}
current = list2.head;
while (current != NULL) {
Node *temp = current;
current = current->next;
free(temp);
}
current = list3.head;
while (current != NULL) {
Node *temp = current;
current = current->next;
free(temp);
}
return 0;
}
以顺序表为例详细分析:
数据结构定义
// 链表节点定义
typedef struct Node {
int data;
struct Node *next;
} Node;
// 链表定义
typedef struct {
Node *head;
} LinkedList;
Node
结构体定义了一个链表节点,包含两个成员:int data
:存储节点的数据。struct Node *next
:指向下一个节点的指针。
LinkedList
结构体定义了一个链表,包含一个成员:Node *head
:指向链表头节点的指针。
初始化链表
// 初始化链表
void initLinkedList(LinkedList *list) {
list->head = NULL;
}
- 将链表的头节点初始化为
NULL
,表示链表为空。
在链表尾部插入节点
// 在链表尾部插入节点
void insertAtTail(LinkedList *list, int value) {
Node *newNode = (Node *)malloc(sizeof(Node));
if (!newNode) {
printf("Memory error\n");
return;
}
newNode->data = value;
newNode->next = NULL;
if (list->head == NULL) {
list->head = newNode;
} else {
Node *temp = list->head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
}
}
- 创建一个新的节点
newNode
,并分配内存。 - 将新节点的数据设置为
value
,并将next
指针设置为NULL
。 - 如果链表为空(即
head
为NULL
),将新节点设置为头节点。 - 否则,遍历链表找到最后一个节点,并将新节点链接到最后一个节点的
next
指针上。
合并两个有序单链表并删除重复节点
// 合并两个有序单链表并删除重复节点
void mergeLinkedLists(LinkedList *list1, LinkedList *list2, LinkedList *list3) {
Node *p1 = list1->head;
Node *p2 = list2->head;
Node *tail = NULL;
Node *prev = NULL;
while (p1 != NULL && p2 != NULL) {
if (p1->data < p2->data) {
if (prev == NULL || p1->data != prev->data) {
if (tail == NULL) {
tail = p1;
list3->head = p1;
} else {
tail->next = p1;
tail = p1;
}
}
prev = p1;
p1 = p1->next;
} else if (p1->data > p2->data) {
if (prev == NULL || p2->data != prev->data) {
if (tail == NULL) {
tail = p2;
list3->head = p2;
} else {
tail->next = p2;
tail = p2;
}
}
prev = p2;
p2 = p2->next;
} else {
if (prev == NULL || p1->data != prev->data) {
if (tail == NULL) {
tail = p1;
list3->head = p1;
} else {
tail->next = p1;
tail = p1;
}
}
prev = p1;
p1 = p1->next;
p2 = p2->next;
}
}
while (p1 != NULL) {
if (prev == NULL || p1->data != prev->data) {
if (tail == NULL) {
tail = p1;
list3->head = p1;
} else {
tail->next = p1;
tail = p1;
}
}
prev = p1;
p1 = p1->next;
}
while (p2 != NULL) {
if (prev == NULL || p2->data != prev->data) {
if (tail == NULL) {
tail = p2;
list3->head = p2;
} else {
tail->next = p2;
tail = p2;
}
}
prev = p2;
p2 = p2->next;
}
if (tail != NULL) {
tail->next = NULL;
}
}
- 初始化三个指针:
p1
:指向链表1的头节点。p2
:指向链表2的头节点。tail
:指向合并后链表的尾节点。prev
:记录上一个插入的节点。
- 使用
while
循环遍历链表1和链表2:- 如果
p1
的数据小于p2
的数据,检查是否需要插入p1
节点。 - 如果
p1
的数据大于p2
的数据,检查是否需要插入p2
节点。 - 如果
p1
和p2
的数据相等,只插入其中一个节点,并移动两个指针。
- 如果
- 遍历完成后,处理剩余的节点:
- 如果
p1
还有剩余节点,继续处理。 - 如果
p2
还有剩余节点,继续处理。
- 如果
- 最后,确保合并后链表的尾节点的
next
指针为NULL
。
打印链表的内容
// 打印链表的内容
void printLinkedList(const LinkedList *list) {
Node *temp = list->head;
while (temp != NULL) {
printf("%d -> ", temp->data);
temp = temp->next;
}
printf("NULL\n");
}
- 从头节点开始遍历链表。
- 逐个打印每个节点的数据。
- 打印完所有节点后,输出一个换行符。
主函数
int main() {
LinkedList list1, list2, list3;
initLinkedList(&list1);
initLinkedList(&list2);
initLinkedList(&list3);
// 用户输入链表1中的元素
int n1;
printf("Enter the number of elements in LIST1: ");
scanf("%d", &n1);
printf("Enter the elements of LIST1:\n");
for (int i = 0; i < n1; i++) {
int value;
scanf("%d", &value);
insertAtTail(&list1, value);
}
// 用户输入链表2中的元素
int n2;
printf("Enter the number of elements in LIST2: ");
scanf("%d", &n2);
printf("Enter the elements of LIST2:\n");
for (int i = 0; i < n2; i++) {
int value;
scanf("%d", &value);
insertAtTail(&list2, value);
}
printf("LIST1: ");
printLinkedList(&list1);
printf("LIST2: ");
printLinkedList(&list2);
mergeLinkedLists(&list1, &list2, &list3);
printf("Merged and deduplicated LIST3: ");
printLinkedList(&list3);
// 清理内存
Node *current = list1.head;
while (current != NULL) {
Node *temp = current;
current = current->next;
free(temp);
}
current = list2.head;
while (current != NULL) {
Node *temp = current;
current = current->next;
free(temp);
}
current = list3.head;
while (current != NULL) {
Node *temp = current;
current = current->next;
free(temp);
}
return 0;
}
- 初始化三个链表
list1
、list2
和list3
。 - 提示用户输入链表1中的节点数量
n1
。 - 提示用户输入链表1中的每个节点的数据,并调用
insertAtTail
函数将其插入到链表1中。 - 提示用户输入链表2中的节点数量
n2
。 - 提示用户输入链表2中的每个节点的数据,并调用
insertAtTail
函数将其插入到链表2中。 - 打印链表1和链表2的内容。
- 调用
mergeLinkedLists
函数合并链表1和链表2,并删除重复节点,结果存储在链表3中。 - 打印合并后的链表3的内容。
- 清理链表1、链表2 和链表3 中所有节点的内存,防止内存泄漏。
- 返回0,表示程序正常结束。
示例运行
假设用户输入以下数据:
Enter the number of elements in LIST1: 5
Enter the elements of LIST1:
1 3 5 7 9
Enter the number of elements in LIST2: 4
Enter the elements of LIST2:
2 4 6 8
LIST1: 1 -> 3 -> 5 -> 7 -> 9 -> NULL
LIST2: 2 -> 4 -> 6 -> 8 -> NULL
Merged and deduplicated LIST3: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> NULL
在这个示例中:
- 用户输入了链表1的5个节点的数据
[1, 3, 5, 7, 9]
。 - 用户输入了链表2的4个节点的数据
[2, 4, 6, 8]
。 - 打印链表1和链表2的内容。
- 合并链表1和链表2,并删除重复节点,结果为
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> NULL
。
4.设双链表中的结点包括4个部分:前驱指针llink、后继指针rlink、数据域data、访问频度freq。初始时将各结点的freq设置为0。当对某结点访问时使该结点的freq增加1,并且将链表按照访问freq递减的顺序进行排序。请编写C语言算法实现以上功能。
#include <stdio.h>
#include <stdlib.h>
// 双链表节点定义
typedef struct Node {
int data;
int freq;
struct Node *llink;
struct Node *rlink;
} Node;
// 双链表定义
typedef struct {
Node *head;
Node *tail;
} DoublyLinkedList;
// 初始化双链表
void initDoublyLinkedList(DoublyLinkedList *list) {
list->head = NULL;
list->tail = NULL;
}
// 在双链表尾部插入节点
void insertAtTail(DoublyLinkedList *list, int value) {
Node *newNode = (Node *)malloc(sizeof(Node));
if (!newNode) {
printf("Memory error\n");
return;
}
newNode->data = value;
newNode->freq = 0;
newNode->llink = NULL;
newNode->rlink = NULL;
if (list->head == NULL) {
list->head = newNode;
list->tail = newNode;
} else {
list->tail->rlink = newNode;
newNode->llink = list->tail;
list->tail = newNode;
}
}
// 更新节点的频度并重新排序链表
void updateFreqAndSort(DoublyLinkedList *list, Node *node) {
node->freq++;
// 如果节点已经是第一个或者没有更高的频度节点,则不需要移动
if (node->llink == NULL || node->freq <= node->llink->freq) {
return;
}
// 从当前位置移除节点
node->llink->rlink = node->rlink;
if (node->rlink != NULL) {
node->rlink->llink = node->llink;
} else {
list->tail = node->llink;
}
// 找到合适的位置插入节点
Node *current = node->llink;
while (current->llink != NULL && current->freq < node->freq) {
current = current->llink;
}
if (current->llink == NULL) {
// 插入到头部
node->rlink = current;
node->llink = NULL;
current->llink = node;
list->head = node;
} else {
// 插入到中间
node->rlink = current;
node->llink = current->llink;
current->llink->rlink = node;
current->llink = node;
}
}
// 查找特定数据的节点
Node *findNode(DoublyLinkedList *list, int value) {
Node *current = list->head;
while (current != NULL) {
if (current->data == value) {
return current;
}
current = current->rlink;
}
return NULL;
}
// 打印双链表的内容
void printDoublyLinkedList(const DoublyLinkedList *list) {
Node *current = list->head;
while (current != NULL) {
printf("Data: %d, Freq: %d -> ", current->data, current->freq);
current = current->rlink;
}
printf("NULL\n");
}
int main() {
DoublyLinkedList list;
initDoublyLinkedList(&list);
// 插入一些节点
int n;
printf("Enter the number of nodes to insert: ");
scanf("%d", &n);
for (int i = 0; i < n; i++) {
int value;
printf("Enter data for node %d: ", i + 1);
scanf("%d", &value);
insertAtTail(&list, value);
}
printf("Initial List: ");
printDoublyLinkedList(&list);
// 访问节点并更新频度
int numAccesses;
printf("Enter the number of accesses: ");
scanf("%d", &numAccesses);
for (int i = 0; i < numAccesses; i++) {
int value;
printf("Enter data to access: ");
scanf("%d", &value);
Node *node = findNode(&list, value);
if (node != NULL) {
updateFreqAndSort(&list, node);
} else {
printf("Node with data %d not found.\n", value);
}
}
printf("Updated List: ");
printDoublyLinkedList(&list);
// 清理内存
Node *current = list.head;
while (current != NULL) {
Node *temp = current;
current = current->rlink;
free(temp);
}
return 0;
}
数据结构定义
// 双链表节点定义
typedef struct Node {
int data;
int freq;
struct Node *llink;
struct Node *rlink;
} Node;
// 双链表定义
typedef struct {
Node *head;
Node *tail;
} DoublyLinkedList;
Node
结构体定义了一个双链表节点,包含四个成员:int data
:存储节点的数据。int freq
:存储节点的访问频度。struct Node *llink
:指向前一个节点的指针。struct Node *rlink
:指向后一个节点的指针。
DoublyLinkedList
结构体定义了一个双链表,包含两个成员:Node *head
:指向双链表头节点的指针。Node *tail
:指向双链表尾节点的指针。
初始化双链表
// 初始化双链表
void initDoublyLinkedList(DoublyLinkedList *list) {
list->head = NULL;
list->tail = NULL;
}
- 将双链表的头节点和尾节点初始化为
NULL
,表示链表为空。
在双链表尾部插入节点
// 在双链表尾部插入节点
void insertAtTail(DoublyLinkedList *list, int value) {
Node *newNode = (Node *)malloc(sizeof(Node));
if (!newNode) {
printf("Memory error\n");
return;
}
newNode->data = value;
newNode->freq = 0;
newNode->llink = NULL;
newNode->rlink = NULL;
if (list->head == NULL) {
list->head = newNode;
list->tail = newNode;
} else {
list->tail->rlink = newNode;
newNode->llink = list->tail;
list->tail = newNode;
}
}
- 创建一个新的节点
newNode
,并分配内存。 - 将新节点的数据设置为
value
,并将频度freq
初始化为0。 - 将新节点的前后指针初始化为
NULL
。 - 如果双链表为空(即
head
为NULL
),将新节点设置为头节点和尾节点。 - 否则,将新节点插入到尾节点的后面,并更新尾节点的指针。
更新节点的频度并重新排序链表
// 更新节点的频度并重新排序链表
void updateFreqAndSort(DoublyLinkedList *list, Node *node) {
node->freq++;
// 如果节点已经是第一个或者没有更高的频度节点,则不需要移动
if (node->llink == NULL || node->freq <= node->llink->freq) {
return;
}
// 从当前位置移除节点
node->llink->rlink = node->rlink;
if (node->rlink != NULL) {
node->rlink->llink = node->llink;
} else {
list->tail = node->llink;
}
// 找到合适的位置插入节点
Node *current = node->llink;
while (current->llink != NULL && current->freq < node->freq) {
current = current->llink;
}
if (current->llink == NULL) {
// 插入到头部
node->rlink = current;
node->llink = NULL;
current->llink = node;
list->head = node;
} else {
// 插入到中间
node->rlink = current;
node->llink = current->llink;
current->llink->rlink = node;
current->llink = node;
}
}
- 增加节点的频度
freq
。 - 如果节点已经是第一个节点或者没有更高的频度节点,则不需要移动。
- 否则,从当前位置移除节点:
- 更新前一个节点的
rlink
指针。 - 如果节点是尾节点,更新尾节点的指针。
- 更新前一个节点的
- 找到合适的位置插入节点:
- 使用
while
循环找到第一个频度小于当前节点频度的节点。 - 如果插入位置在头部,更新头节点的指针。
- 否则,插入到中间位置,更新相关节点的指针。
- 使用
查找特定数据的节点
// 打印双链表的内容
void printDoublyLinkedList(const DoublyLinkedList *list) {
Node *current = list->head;
while (current != NULL) {
printf("Data: %d, Freq: %d -> ", current->data, current->freq);
current = current->rlink;
}
printf("NULL\n");
}
- 从头节点开始遍历双链表。
- 如果找到数据等于
value
的节点,返回该节点。 - 如果遍历完整个链表都没有找到,返回
NULL
。
打印双链表的内容
// 打印双链表的内容
void printDoublyLinkedList(const DoublyLinkedList *list) {
Node *current = list->head;
while (current != NULL) {
printf("Data: %d, Freq: %d -> ", current->data, current->freq);
current = current->rlink;
}
printf("NULL\n");
}
- 从头节点开始遍历双链表。
- 逐个打印每个节点的数据和频度。
- 打印完所有节点后,输出一个换行符。
主函数
int main() {
DoublyLinkedList list;
initDoublyLinkedList(&list);
// 插入一些节点
int n;
printf("Enter the number of nodes to insert: ");
scanf("%d", &n);
for (int i = 0; i < n; i++) {
int value;
printf("Enter data for node %d: ", i + 1);
scanf("%d", &value);
insertAtTail(&list, value);
}
printf("Initial List: ");
printDoublyLinkedList(&list);
// 访问节点并更新频度
int numAccesses;
printf("Enter the number of accesses: ");
scanf("%d", &numAccesses);
for (int i = 0; i < numAccesses; i++) {
int value;
printf("Enter data to access: ");
scanf("%d", &value);
Node *node = findNode(&list, value);
if (node != NULL) {
updateFreqAndSort(&list, node);
} else {
printf("Node with data %d not found.\n", value);
}
}
printf("Updated List: ");
printDoublyLinkedList(&list);
// 清理内存
Node *current = list.head;
while (current != NULL) {
Node *temp = current;
current = current->rlink;
free(temp);
}
return 0;
}
- 初始化一个双链表
list
。 - 提示用户输入要插入的节点数量
n
。 - 提示用户输入每个节点的数据,并调用
insertAtTail
函数将其插入到双链表中。 - 打印初始双链表的内容。
- 提示用户输入要访问的次数
numAccesses
。 - 对于每次访问,提示用户输入要访问的节点数据,调用
findNode
函数查找节点,如果找到则调用updateFreqAndSort
函数更新节点的频度并重新排序链表。 - 打印更新后的双链表的内容。
- 清理双链表中所有节点的内存,防止内存泄漏。
- 返回0,表示程序正常结束。
示例运行
假设用户输入以下数据:
Enter the number of nodes to insert: 5
Enter data for node 1: 3
Enter data for node 2: 1
Enter data for node 3: 4
Enter data for node 4: 1
Enter data for node 5: 5
Initial List: Data: 3, Freq: 0 -> Data: 1, Freq: 0 -> Data: 4, Freq: 0 -> Data: 1, Freq: 0 -> Data: 5, Freq: 0 -> NULL
Enter the number of accesses: 3
Enter data to access: 1
Enter data to access: 4
Enter data to access: 1
Updated List: Data: 1, Freq: 2 -> Data: 4, Freq: 1 -> Data: 1, Freq: 1 -> Data: 3, Freq: 0 -> Data: 5, Freq: 0 -> NULL
在这个示例中:
- 用户输入了5个节点的数据
[3, 1, 4, 1, 5]
。 - 初始双链表为
Data: 3, Freq: 0 -> Data: 1, Freq: 0 -> Data: 4, Freq: 0 -> Data: 1, Freq: 0 -> Data: 5, Freq: 0 -> NULL
。 - 用户进行了3次访问,访问的数据分别为
1
,4
,1
。 - 更新后的双链表为
Data: 1, Freq: 2 -> Data: 4, Freq: 1 -> Data: 1, Freq: 1 -> Data: 3, Freq: 0 -> Data: 5, Freq: 0 -> NULL
。