问题描述:编写三个链表复制函数,第一个是复制出连接顺序相同的链表,第二个是顺序相反的,第三个是按值大小链接。(链表中储存若干数值)
首先,我们来完成一些基本的链表设置函数,包括链表的创建、打印、清空。
①定义链表节点结构体
typedef struct Node { //用typedef将结构体结构体定义为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;
}
③打印链表
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;
//用next记录下一位置,才能用free释放当前位置内存
while (current != NULL) {
next = current->next;
free(current);
current = next;
}
}
第一个函数:相同顺序,相当于直接复制链表。
Node* copyList(Node* head) {
if (NULL == head) {
return NULL;
}
Node* newHead = createNode(head->value);//先存入首节点元素
Node* current = head->next;//原链表
Node* newCurrent = newHead;//新链表
while (current != NULL) {
//尾插法
Node* newNode = createNode(current->value);
newCurrent->next = newNode;//新节点插入
newCurrent = newCurrent->next;//新链表后移
current = current->next;//顺序历遍原链表
}
return newHead;
}
第二个函数:复制出顺序相反的链表,由于我们不能从链表的尾元素开始传入数据,要实现这一功能,可以将原链表读取出来的每一项插到新链表的头部。
Node* reverseCopyList(Node* head) {
if (NULL == head) {
return NULL;
}
Node* newHead = createNode(head->value);
Node* current = head->next;
while (current != NULL) {
//头插法
Node* newNode = createNode(current->value);
newNode->next = newHead;//新节点的后继为新链表当前位置
newHead = newNode;//新链表前移
current = current->next;
}
return newHead;
}
第三个函数:按值大小的顺序复制,这就要求找到新读入的原链表元素在新链表中的位置。
Node* sortedCopyList(Node* head) {
if (NULL == head) {
return NULL;
}
Node* newHead = createNode(head->value);
Node* current = head->next;
Node* newCurrent = newHead;
while (current != NULL) {
Node* newNode = createNode(current->value);
//对每个新插入的节点
if (newNode->value < newHead->value) {
//新插入的节点比头节点值还要小,成为新的头节点
newNode->next = newHead;
newHead = newNode;
}
else {
//利用temp找到节点应该插入的位置
Node* temp = newHead;
//这里已经插入的部分都将是已经排好序的
while (temp->next != NULL && newNode->value > temp->next->value) {
temp = temp->next;
}
//找到的temp应该是新表元的前一个表元,将newNode插入temp和temp->next中间
newNode->next = temp->next;
temp->next = newNode;
}
current = current->next;
}
return newHead;
}
这样就完成了所有的函数,以下是完整程序代码和样例演示:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
// 定义链表节点结构体
typedef struct Node { //用typedef将结构体结构体定义为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* copyList(Node* head) {
if (NULL == head) {
return NULL;
}
Node* newHead = createNode(head->value);//先存入首节点元素
Node* current = head->next;//原链表
Node* newCurrent = newHead;//新链表
while (current != NULL) {
//尾插法
Node* newNode = createNode(current->value);
newCurrent->next = newNode;//新节点插入
newCurrent = newCurrent->next;//新链表后移
current = current->next;//顺序历遍原链表
}
return newHead;
}
// 复制出链接顺序相反的链表
Node* reverseCopyList(Node* head) {
if (NULL == head) {
return NULL;
}
Node* newHead = createNode(head->value);
Node* current = head->next;
while (current != NULL) {
//头插法
Node* newNode = createNode(current->value);
newNode->next = newHead;//新节点的后继为新链表当前位置
newHead = newNode;//新链表前移
current = current->next;
}
return newHead;
}
// 复制出有序链表
Node* sortedCopyList(Node* head) {
if (NULL == head) {
return NULL;
}
Node* newHead = createNode(head->value);
Node* current = head->next;
Node* newCurrent = newHead;
while (current != NULL) {
Node* newNode = createNode(current->value);
//对每个新插入的节点
if (newNode->value < newHead->value) {
//新插入的节点比头节点值还要小,成为新的头节点
newNode->next = newHead;
newHead = newNode;
}
else {
//利用temp找到节点应该插入的位置
Node* temp = newHead;
//这里已经插入的部分都将是已经排好序的
while (temp->next != NULL && newNode->value > temp->next->value) {
temp = temp->next;
}
//找到的temp应该是新表元的前一个表元,将newNode插入temp和temp->next中间
newNode->next = temp->next;
temp->next = newNode;
}
current = current->next;
}
return newHead;
}
// 打印链表
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;
//用next记录下一位置,才能用free释放当前位置内存
while (current != NULL) {
next = current->next;
free(current);
current = next;
}
}
int main() {
// 创建原始链表
Node* head = createOriginalList();
// 复制出相同链接顺序的链表
Node* copy1 = copyList(head);
printf("Copy with same order: ");
printList(copy1);
// 复制出链接顺序相反的链表
Node* copy2 = reverseCopyList(head);
printf("Copy with reverse order: ");
printList(copy2);
// 复制出有序链表
Node* copy3 = sortedCopyList(head);
printf("Copy with sorted order: ");
printList(copy3);
// 释放链表内存
freeList(copy3);
freeList(copy2);
freeList(copy1);
freeList(head);
return 0;
}