c语言链表,单项链表,双向链表

本文介绍了C语言中的链表数据结构,包括单向链表的节点结构、插入操作,以及双向链表的扩展。还展示了如何使用冒泡排序算法对链表进行排序,并提供了示例代码实现。
摘要由CSDN通过智能技术生成

  定制魏:QTWZPW,获取更多源码等

目录

 

基础知识

单向链表实现  

 代码储存初始链表

 自己输入初始链表

 双向链表实现


基础知识

在C语言中,链表是一种常见的数据结构,用于存储一系列元素。链表由一系列节点组成,每个节点包含数据以及一个指向下一个节点的指针。以下是关于C语言链表的基础知识:
节点结构体定义:链表中的每个节点通常通过结构体来表示,结构体包含数据成员和指向下一个节点的指针成员。例如:
typedef struct Node {
    int data;
    struct Node* next;
} Node;
链表的概念:链表是一种线性数据结构,由一系列节点组成,每个节点包含数据和指向下一个节点的指针。与数组不同,链表的内存分配是动态的,节点可以在内存中的任何地方分配,通过指针进行连接。

单向链表:最基本的链表形式是单向链表,其中每个节点包含数据和指向下一个节点的指针。单向链表只能从头节点开始沿着指针方向遍历,无法反向遍历。

双向链表:双向链表的节点除了包含数据和指向下一个节点的指针外,还包含指向前一个节点的指针。这样的设计使得双向链表可以双向遍历,灵活性更高。

循环链表:循环链表是一种特殊的链表,最后一个节点的指针指向第一个节点,形成一个闭环。循环链表可以很方便地实现循环操作。

链表的优缺点:链表的优点包括插入和删除节点方便快捷,不需要提前知道存储空间大小。缺点包括访问元素时需要遍历,无法像数组那样通过索引直接访问元素,而且消耗一定的额外存储空间来存储指针。
 

单向链表实现  

//单向链表实现 
#include <stdio.h>  
#include <stdlib.h> 
// 定义链表节点结构体
//定义了一个名为Node的结构体,包含一个整型数据成员data和一个指向下一个Node结构体的指针next。 
typedef struct Node {  // 定义名为Node的结构体
    int data;  // 整型数据成员
    struct Node* next;  // 指向下一个Node结构体的指针
} Node;


// 创建新节点
//定义了一个函数createNode,用于创建一个新的链表节点,参数data表示新节点的数据值,函数返回指向新节点的指针。 
Node* createNode(int data) {  // 创建新节点的函数,传入一个整型参数data
    Node* newNode = (Node*)malloc(sizeof(Node));  // 使用malloc函数分配内存空间
    newNode->data = data;  // 将data赋值给新节点的data成员
    newNode->next = NULL;  // 将新节点的next指针设为NULL
    return newNode;  // 返回新创建的节点指针
}


// 插入节点到链表尾部
//定义了一个函数insertNode,用于向链表尾部插入一个新节点,参数head是指向链表头指针的指针,参数data是新节点的数据值。 
void insertNode(Node** head, int data) {  // 向链表尾部插入节点的函数,传入指向头指针的指针和整型参数data
    Node* newNode = createNode(data);  // 调用createNode函数创建新节点
    if (*head == NULL) {  // 如果链表为空
        *head = newNode;  // 将头指针指向新节点
    } else {  // 如果链表不为空
        Node* current = *head;  // 创建临时指针指向头指针
        while (current->next != NULL) {  // 遍历链表直到最后一个节点
            current = current->next;  // 移动当前指针到下一个节点
        }
        current->next = newNode;  // 将新节点连接到当前节点的next指针
    }
}


// 冒泡排序函数
//用于对链表进行冒泡排序,参数head是指向链表头节点的指针。 
void bubbleSort(Node* head) {  // 冒泡排序函数,传入链表头指针
    int swapped, temp;  // 定义交换标志和临时变量
    Node* ptr1;  // 定义指向节点的指针
    Node* lptr = NULL;  // 定义最后交换位置的节点指针

    // 如果链表为空或只有一个节点,则无需排序
    if (head == NULL)
        return;

    do {
        swapped = 0;  // 重置交换标志
        ptr1 = head;  // 将指针指向链表头部

        while (ptr1->next != lptr) {  // 遍历链表直到最后交换位置的前一个节点
            if (ptr1->data > ptr1->next->data) {  // 如果当前节点的值大于下一个节点的值
                temp = ptr1->data;  // 交换两个节点的值
                ptr1->data = ptr1->next->data;
                ptr1->next->data = temp;
                swapped = 1;  // 设置交换标志
            }
            ptr1 = ptr1->next;  // 移动当前指针到下一个节点
        }
        lptr = ptr1;  // 更新最后交换位置的节点指针
    } while (swapped);  // 如果发生过交换则继续循环

}


// 打印链表
//用于打印链表的所有节点数据值,参数node是指向链表头节点的指针。 
void printList(Node* node) {  // 打印链表的函数,传入链表头指针
    while (node != NULL) {  // 遍历链表
        printf("%d ", node->data);  // 打印当前节点的值
        node = node->next;  // 移动到下一个节点
    }
    printf("\n");  // 打印换行
}

 代码储存初始链表

//主函数main,首先创建了一个头指针head并初始化为空,然后调用insertNode函数向链表插入了一些节点,
//接着打印原始链表,调用bubbleSort函数对链表进行排序,最后打印排序后的链表。 
int main() {
    Node* head = NULL;  // 定义头指针并初始化为空

    // 插入节点到链表
    insertNode(&head, 5);  // 插入数值为5的节点
    insertNode(&head, 2);  // 插入数值为2的节点
    insertNode(&head, 8);  // 插入数值为8的节点
    insertNode(&head, 1);  // 插入数值为1的节点
    insertNode(&head, 6);  // 插入数值为6的节点

    printf("原始链表:\n");
    printList(head);  // 打印原始链表

    // 调用冒泡排序函数进行排序
    bubbleSort(head);  // 对链表进行排序

    printf("排序后的链表:\n");
    printList(head);  // 打印排序后的链表

    return 0;  // 返回0表示程序成功执行
}

 自己输入初始链表

//在主函数中,首先初始化一个头指针head为空,并定义变量data和inputFlag。
//使用do-while循环,循环提示用户输入节点的数值,将数值插入到链表中,然后询问用户是否继续添加节点,根据用户输入的选择决定是否继续循环。
int main() { 
    Node* head = NULL; // 头指针初始化为空
    int data;
    char inputFlag;

    do {
        printf("请输入节点的数值:");
        scanf("%d", &data);
        insertNode(&head, data);
        printf("是否继续添加节点?(y/n): ");
        scanf(" %c", &inputFlag);
    } while (inputFlag == 'y');

    printf("原始链表:\n");
    printList(head); // 输出原始链表

    // 调用冒泡排序函数进行排序
    bubbleSort(head);

    printf("排序后的链表:\n");
    printList(head); // 输出排序后的链表

    return 0; // 返回值0,表示程序正常结束
}

 双向链表实现

#include <stdio.h> 
#include <stdlib.h> 

// 定义双向链表节点结构体
typedef struct Node {  // 定义名为Node的结构体
    int data;  // 整型数据成员
    struct Node* prev;  // 指向前一个Node结构体的指针
    struct Node* next;  // 指向下一个Node结构体的指针
} Node;

// 创建新节点
Node* createNode(int data) {  // 创建新节点的函数,传入一个整型参数data
    Node* newNode = (Node*)malloc(sizeof(Node));  // 使用malloc函数分配内存空间
    newNode->data = data;  // 将data赋值给新节点的data成员
    newNode->prev = NULL;  // 将新节点的prev指针设为NULL
    newNode->next = NULL;  // 将新节点的next指针设为NULL
    return newNode;  // 返回新创建的节点指针
}

// 插入节点到双向链表尾部
void insertNode(Node** head, int data) {  // 向双向链表尾部插入节点的函数,传入指向头指针的指针和整型参数data
    Node* newNode = createNode(data);  // 调用createNode函数创建新节点
    if (*head == NULL) {  // 如果链表为空
        *head = newNode;  // 将头指针指向新节点
    } else {  // 如果链表不为空
        Node* current = *head;  // 创建临时指针指向头指针
        while (current->next != NULL) {  // 遍历链表直到最后一个节点
            current = current->next;  // 移动当前指针到下一个节点
        }
        current->next = newNode;  // 将新节点连接到当前节点的next指针
        newNode->prev = current;  // 将当前节点连接到新节点的prev指针
    }
}

// 冒泡排序函数
void bubbleSort(Node* head) {  // 冒泡排序函数,传入双向链表头指针
    int swapped, temp;  // 定义交换标志和临时变量
    Node* ptr1;  // 定义指向节点的指针
    Node* lptr = NULL;  // 定义最后交换位置的节点指针

    // 如果链表为空或只有一个节点,则无需排序
    if (head == NULL)
        return;

    do {
        swapped = 0;  // 重置交换标志
        ptr1 = head;  // 将指针指向链表头部

        while (ptr1->next != lptr) {  // 遍历链表直到最后交换位置的前一个节点
            if (ptr1->data > ptr1->next->data) {  // 如果当前节点的值大于下一个节点的值
                temp = ptr1->data;  // 交换两个节点的值
                ptr1->data = ptr1->next->data;
                ptr1->next->data = temp;
                swapped = 1;  // 设置交换标志
            }
            ptr1 = ptr1->next;  // 移动当前指针到下一个节点
        }
        lptr = ptr1;  // 更新最后交换位置的节点指针
    } while (swapped);  // 如果发生过交换则继续循环

}

// 打印双向链表
void printList(Node* node) {  // 打印双向链表的函数,传入链表头指针
    while (node != NULL) {  // 遍历链表
        printf("%d ", node->data);  // 打印当前节点的值
        node = node->next;  // 移动到下一个节点
    }
    printf("\n");  // 打印换行
}

int main() {
    Node* head = NULL;  // 定义头指针并初始化为空

    // 插入节点到双向链表
    insertNode(&head, 5);  // 插入数值为5的节点
    insertNode(&head, 2);  // 插入数值为2的节点
    insertNode(&head, 8);  // 插入数值为8的节点
    insertNode(&head, 1);  // 插入数值为1的节点
    insertNode(&head, 6);  // 插入数值为6的节点

    printf("原始双向链表:\n");
    printList(head);  // 打印原始双向链表

    // 调用冒泡排序函数进行排序
    bubbleSort(head);  // 对双向链表进行排序

    printf("排序后的双向链表:\n");
    printList(head);  // 打印排序后的双向链表

    return 0;  // 返回0表示程序成功执行
}

 

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值