C语言链表复制函数(顺序相同、顺序相反、按值大小链接)

问题描述:编写三个链表复制函数,第一个是复制出连接顺序相同的链表,第二个是顺序相反的,第三个是按值大小链接。(链表中储存若干数值)

首先,我们来完成一些基本的链表设置函数,包括链表的创建、打印、清空。

①定义链表节点结构体

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;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值