C语言链表详解及代码分析

C语言链表详解及代码分析

简介

链表是一种常见的数据结构,它主要用于存储线性数据结构,可以动态地进行添加和删除操作。在C语言中,链表可以通过链式存储结构来实现。本篇攻略将详细讲解C语言链表的实现,包括定义链表、节点、添加节点、删除节点等操作。

链表的定义

链表由一个个节点组成,每个节点包含两个信息:数据和指向下一个节点的指针。在C语言中,可以通过结构体实现每个节点的定义。

struct Node {
    int data;           // 存储节点数据
    struct Node *next;  // 存储指向下一个节点的指针
};

这里定义了一个名为Node的结构体,包含了一个用于存储节点数据的整型变量data和一个用于存储指向下一个节点的指针的结构体类型Node*。其中,Node*是指向该类型结构体的指针类型,因此可以指向该类型的某个节点。

添加节点

链表的添加操作主要有两个:在链表头部添加新节点和在链表尾部添加新节点。以下代码分别实现这两个操作:

在链表头部添加新节点:

struct Node* addNodeAtHead(struct Node* head, int data) {
    // 创建新节点
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = data;
    // 把原先的头节点作为新节点的next指针
    newNode->next = head;
    // 把新节点设置为新的头节点
    head = newNode;
    return head;
}

在链表尾部添加新节点:

struct Node* addNodeAtTail(struct Node* head, int data) {
    // 创建新节点
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = data;
    newNode->next = NULL;
    // 如果链表为空,把新节点作为头节点
    if (head == NULL) {
        head = newNode;
        return head;
    }
    // 找到链表尾部
    struct Node* curNode = head;
    while (curNode->next != NULL) {
        curNode = curNode->next;
    }
    // 把新节点作为链表的最后一个节点
    curNode->next = newNode;
    return head;
}

两个函数都接收一个Node*类型的参数表示链表头节点,返回一个指向头节点的指针。其中,使用了动态内存分配函数malloc来分配一个新节点,并将节点的两个信息进行初始化。

删除节点

链表的删除操作通常通过找到要删除的节点,然后将其上一个节点的next指针指向其下一个节点,进而将其从链表中移除。以下是找到对应节点并删除的代码:

struct Node* deleteNode(struct Node* head, int data) {
    struct Node* curNode = head;
    struct Node* prevNode = NULL;
    // 找到节点
    while (curNode != NULL && curNode->data != data) {
        prevNode = curNode;
        curNode = curNode->next;
    }
    // 如果链表中不存在要删除的节点
    if (curNode == NULL) {
        return head;
    }
    // 如果要删除的节点是头节点
    if (curNode == head) {
        head = head->next;
    } else {
        prevNode->next = curNode->next;
    }
    free(curNode);
    return head;
}

函数接收一个指向头节点的指针和一个要删除的节点的数据,返回一个指向头节点的指针。在找到要删除的节点后,需要保存其上一个节点的指针,否则无法将其从链表中删除。如果要删除的节点是头节点,则需要特殊处理。

示例说明

以下是一个使用链表实现求平均数的示例。

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

struct Node {
    int data;
    struct Node* next;
};

double getAverage(struct Node* head) {
    int sum = 0;
    int count = 0;
    struct Node* curNode = head;
    while (curNode != NULL) {
        sum += curNode->data;
        count++;
        curNode = curNode->next;
    }
    return (double)sum / (double)count;
}

int main() {
    int arr[] = { 1,2,3,4,5 };
    int len = sizeof(arr) / sizeof(int);

    struct Node* head = NULL;

    for (int i = 0; i < len; i++) {
        head = addNodeAtTail(head, arr[i]);
    }

    double avg = getAverage(head);
    printf("平均数为:%.2f", avg);

    // 释放链表内存
    struct Node* curNode = head;
    while (curNode != NULL) {
        struct Node* temp = curNode;
        curNode = curNode->next;
        free(temp);
    }

    return 0;
}

该程序首先定义了一个名为Node的结构体,用于表示链表节点。接着定义了一个计算平均数的函数getAverage,该函数接收一个指向头节点的指针并返回一个浮点型平均数。函数中使用了链表遍历的方法来计算总和,并统计链表中元素的个数。

在主函数中,将一组数据存储于数组arr中,并使用addNodeAtTail函数将元素添加到链表中,最后调用getAverage函数计算平均数并输出。程序结束后需要手动释放链表内存。

另一个示例是使用链表来实现红包扫雷游戏的。游戏规则:共有$n$个红包,每个红包的金额是随机生成的,并且保证总金额为$m$元。每轮游戏中,用户需要猜测剩余红包的总金额,如果猜对则获得该金额,并继续下一轮游戏,否则游戏结束。以下是一个使用链表实现游戏的示例。

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

struct Node {
    int money;
    struct Node* next;
};

int getRemainMoney(struct Node* head) {
    int sum = 0;
    struct Node* curNode = head;
    while (curNode != NULL) {
        sum += curNode->money;
        curNode = curNode->next;
    }
    return sum;
}

int main() {
    srand((unsigned int)time(NULL));

    int n = 10;
    int m = 100;

    // 初始化红包
    struct Node* head = NULL;
    struct Node* curNode = NULL;
    for (int i = 0; i < n; i++) {
        int money = rand() % (m - n + 1) + 1;
        curNode = (struct Node*)malloc(sizeof(struct Node));
        curNode->money = money;
        curNode->next = NULL;
        if (head == NULL) {
            head = curNode;
        } else {
            struct Node* tail = head;
            while (tail->next != NULL) {
                tail = tail->next;
            }
            tail->next = curNode;
        }
    }

    // 游戏开始
    int remainMoney = getRemainMoney(head);
    int count = 0;
    int guess;
    printf("红包总金额为:%d元\n", m);
    while (remainMoney > 0) {
        printf("剩余红包总金额为:%d元,请猜测总金额:", remainMoney);
        scanf("%d", &guess);
        if (guess == remainMoney) {
            int money = curNode->money;
            printf("恭喜你,猜对了,红包金额为:%d元\n", money);
            head = head->next;
            free(curNode);
            curNode = head;
            count++;
            remainMoney = getRemainMoney(head);
        } else {
            printf("猜错了,游戏结束。");
            break;
        }
    }
    printf("游戏结束,你猜了%d次。", count);

    // 释放链表内存
    curNode = head;
    while (curNode != NULL) {
        struct Node* temp = curNode;
        curNode = curNode->next;
        free(temp);
    }

    return 0;
}

该程序首先定义了一个名为Node的结构体,用于表示红包。接着使用函数srand随机设置种子,生成每个红包的金额,并将其添加到链表中。在游戏开始后,程序每轮接受用户的猜测并将其与剩余金额进行比较,如果猜对则移除当前红包节点并将游戏次数加1,否则游戏结束。程序结束后需要手动释放链表内存。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言链表详解及代码分析 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • 多维度深入分析Redis的5种基本数据结构

    多维度深入分析Redis的5种基本数据结构 Redis是一种高性能、内存数据存储系统,它支持多种数据结构,包括字符串、哈希表、列表、集合和有序集合。其中,每种数据结构都具有不同的特性和用途,本文将对这五种基本数据结构进行深入分析。 1. 字符串(string) 字符串是最基本的数据结构,一个字符串可以存储任意二进制数据,例如一个jpg图片或者一个序列化的对象…

    数据结构 2023年5月17日
    00
  • C++数据结构之双向链表

    C++数据结构之双向链表完整攻略 1. 什么是双向链表 双向链表是一种特殊的链表结构,每个节点拥有两个指针域,分别指向前继和后继节点。 双向链表不需要像单向链表那样从头到尾遍历整个链表,可以通过前后指针直接访问前后节点,提高了查找、删除、插入等操作的效率。 双向链表有一些常用的操作,如插入节点、删除节点、查找节点等。 2. 双向链表的实现 2.1 节点定义 …

    数据结构 2023年5月17日
    00
  • Python 数据结构之旋转链表

    Python 数据结构之旋转链表 简介 在进行链表操作时,有时需要旋转链表的一部分,即将链表的最后几个节点移到链表的头部。本文将讲解 Python 实现旋转链表的方法。 方法 我们需要了解两个概念:旋转链表、链表反转。 旋转链表 假设链表为1-2-3-4-5,k=2,将链表后两个节点移动到链表头部,即转化为4-5-1-2-3。 做法如下: 先遍历链表,得出链…

    数据结构 2023年5月17日
    00
  • Java数据结构BFS广搜法解决迷宫问题

    Java数据结构BFS广搜法解决迷宫问题 什么是BFS广搜法? 广度优先搜索(BFS)是一种遍历或搜索数据结构(例如树或图)的算法经典方法之一,也是解决迷宫问题的有效解法之一。BFS方法是从图的某个节点出发,以广度优先的方式依次访问与该节点相通的各节点,直到访问所有节点。BFS算法主要借助队列的数据结构来实现。 解决迷宫问题的具体实现 数据准备: 在解决迷宫…

    数据结构 2023年5月17日
    00
  • 一些常见的字符串匹配算法

    作者:京东零售 李文涛 一、简介 1.1 Background 字符串匹配在文本处理的广泛领域中是一个非常重要的主题。字符串匹配包括在文本中找到一个,或者更一般地说,所有字符串(通常来讲称其为模式)的出现。该模式表示为p=p[0..m-1];它的长度等于m。文本表示为t=t[0..n-1],它的长度等于n。两个字符串都建立在一个有限的字符集上。 一个比较常见…

    算法与数据结构 2023年4月25日
    00
  • 2020滴滴最新PHP试题(附答案及解析)

    题目链接:https://www.fibar.cn/newsDetail/18216.html 本文主要是对“2020滴滴最新PHP试题(附答案及解析)”的解题思路和过程进行详细讲解。 题目难度 此题属于中等难度,需要考生具备 PHP 基础知识和算法基础。 题目要求 题目要求我们编写一个程序,实现多个字符串的排序输出。程序需要满足以下要求: 输入:多个字符串…

    数据结构 2023年5月17日
    00
  • C语言 超详细总结讲解二叉树的概念与使用

    C语言 超详细总结讲解二叉树的概念与使用 1. 什么是二叉树? 二叉树是一种树状数据结构,其中每个节点最多有两个子节点,被称为左子节点和右子节点。具有以下几个特点: 每个节点最多有两个子节点; 左子节点可以为空,右子节点也可以为空; 二叉树的每个节点最多有一个父节点; 二叉树通常定义为递归模式定义,即每个节点都可以看做一棵新的二叉树。 2. 二叉树的遍历方式…

    数据结构 2023年5月17日
    00
  • 浅谈iOS 数据结构之链表

    浅谈iOS 数据结构之链表 在计算机科学中,链表是一种数据结构,用于存储一系列按顺序排列的元素。链表的一个关键点是它不需要连续的内存空间来存储元素,相反,每个元素由一个指向下一个元素的指针组成。在iOS开发中,链表在各种场景下都有所应用,如UITableView和UICollectionView的数据源等。本文将详细讲解链表的基本知识和使用技巧。 链表的基本…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部