ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

C语言 单链表 实现存储删除任意类型数据(高扩展性)

2022-01-19 12:02:39  阅读:152  来源: 互联网

标签:Node 单链 data list 扩展性 next C语言 pointer 节点


企业开发中,C语言链表不仅仅存储基本数据类型,应对任意的void data均可实现增删改查。在前面的一篇文章中,已经分享了单向链表、双向链表、有头节点和无头节点等链表对基本数据的处理。以下主要分析对复杂类型数据的处理,是以无有效头节点的单向链表为例。

1 结构体构建Node节点

typedef struct Node //链表节点定义
{
    void *data;        //节点的数据域,存址
    struct Node *next; //指针域,保存下一个节点的地址,指向下一个节点
} Node;

2 结构体构建链表

typedef struct LinkList //链表
{
    Node firstNode; //链表的首个节点
    int size;       //链表长度
} List;

3 链表初始化

List *initLinkList() //链表初始化
{
    List *list = (List *)malloc(sizeof(List));//向堆区申请内存
    if (list == NULL)
        return NULL;
    list->firstNode.data = NULL;//初始化
    list->firstNode.next = NULL;
    list->size = 0;
    return list;
}

4 创建单个数据节点

Node *createSingleNode(void *data) //创建节点
{
    Node *node = (Node *)malloc(sizeof(Node));
    node->data = data;
    node->next = NULL;
    return node;
}

5.1 头插数据到链表


Node *insertSingleNodeByHead(void *data, List *list) //单链表有表头头插法
{
    if (data == NULL || list == NULL)//空指针判断
        return NULL;
    Node *node = createSingleNode(data);
    node->next = list->firstNode.next;
    list->firstNode.next = node;
    list->size++;//链表容量+1
    return node;
}

5.2 尾插数据到链表

Node *insertSingleNodeByTail(void *data, List *list) //单链表尾插法
{
    if (data == NULL || list == NULL)
        return NULL;
    Node *node = createSingleNode(data);
    Node *pointer = &(list->firstNode);//拿到首节点的地址
    while (pointer->next)
        pointer = pointer->next;
    pointer->next = node;//此时pointer是最后一个节点
    node->next = NULL;//node成为最后一个节点
    list->size++;
    return node;
}

5.3 根据索引插入数据到链表

Node *insertSingleNodeByIndex(void *data, int index, List *list)//根据索引index插入数据data至链表中
{
    if (data == NULL || list == NULL)
        return NULL;
    if (index < 0 || index > list->size) // 0索引为无有效数据的firstNode
        index = list->size;              //非法索引时,统一尾插处理
    Node *node = createSingleNode(data);
    Node *firstN = &list->firstNode;//拿到首节点地址
    for (int i = 0; i < index; i++)
        firstN = firstN->next;
    node->next = firstN->next;
    firstN->next = node;
    list->size++;
    return node;
}

6 删除指定节点


typedef struct Student//后续的测试用例,假定链表存储该数据类型
{
    int id;
    char name[20];
} Student;

int compare(void *s1, void *s2) //为Student类型数据设计compare比较函数
{
    Student *stu1 = (Student *)s1;
    Student *stu2 = (Student *)s2;
    if (strcmp(stu1->name, stu2->name) == 0 && stu1->id == stu2->id)
        return 1;
    return 0;
}
int deleteSingleNode(void *deleteData, List *list, int (*compare)(void *, void *)) //单链表删除节点
{
    Node *pointer = &(list->firstNode);
    while (pointer->next)
    {
        if (compare(pointer->next->data, deleteData)) // pointer->next->data而不是pointer->next
        {//pointer->next即为需要删除节点
            Node *deleteNode = pointer->next;
            pointer->next = pointer->next->next;
            free(deleteNode); //释放删除节点占用的堆内存
            list->size--;
            return 1;
        }
        pointer = pointer->next;
    }
    return 0; //删除失败返回0
}

7 遍历链表节点

void printfList(void *data) //为方便函数回调,写此函数方便提供程序的可扩展性
{
    Student *stu = (Student *)data;
    printf("name:%s-id:%d--->\t", stu->name, stu->id );
}
void listNode(List *list, void (*printfList)(void *)) //节点遍历
{
    if (list == NULL)
        return;
    Node *pointer = list->firstNode.next; //默认头节点未保留有效数据,list->firstNode.next为第一个有效节点
    while (pointer)
    {
        printfList(pointer->data);//传入的是pointer->data,不是pointer
        pointer = pointer->next;
    }
    puts("\n");
}

8 程序测试与运行结果

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    Student stu[] = {
        {1, "jakes1"},
        {2, "jakes2"},
        {3, "jakes3"},
        {4, "jakes4"},
        {5, "jakes5"},
        {6, "jakes6"},
        {7, "jakes7"},
        {8, "jakes8"},
    };
    Student ss = {6, "sd"};
    List *list = initLinkList();
    for (int i = 0; i < 3; i++)
        insertSingleNodeByHead(&stu[i], list); //头插节点
    listNode(list, printfList);
    for (int i = 3; i < 6; i++)
        insertSingleNodeByTail(&stu[i], list); //尾插节点
    listNode(list, printfList);
    for (int i = 6; i < 8; i++)
        insertSingleNodeByIndex(&stu[i],2,list); //根据索引插入
    listNode(list, printfList);
    for (int i = 2; i < 4; i++)
        deleteSingleNode(&stu[i], list, compare); //删除节点
    listNode(list, printfList);                   //遍历节点
    return 0;
}

运行结果如下:

标签:Node,单链,data,list,扩展性,next,C语言,pointer,节点
来源: https://blog.csdn.net/jakercl/article/details/122562245

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有