ICode9

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

[数据结构10分钟入门] 面向初学者从零实现(基于C语言)-- 单链表

2022-09-04 10:00:51  阅读:173  来源: 互联网

标签:node 10 -- list C语言 链表 next 节点 指针


一、链表是什么

    链表是一种通过指针串联在一起的线性结构,在内存中是分散存储的(数组在内存中连续分布),链表由一系列节点组成,每个节点都由数据域和指针域组成。主要有三种类型的链表:

        1、单链表(本章介绍内容)

        2、双链表

        3、循环链表 

链表与数组对比:

  插入/删除 时间复杂度 查询 时间复杂度 适用场景
数组 O(n) O(1) 内容固定,查询较为频繁
链表 O(1) O(n) 内容不固定,较少查询

二、单链表定义

1、一个单链表的节点:

c9d8a72482148df806626a6c32dfa153.png​编辑

  • 数据域data:存放数据的地方
  • 指针域*next:指向下一个节点的地址

2、将节点链接起来,每个节点的*next指针指向下一节点,最后一个节点的指针指向NULL,就形成了单链表。

d3a3aff337f130ec2b526390bf7bae21.png​编辑

3、头指针的作用

    设置一个头指针指向整条链表的首节点,这样对首节点的操作将和其余节点一致,无需使用两套处理逻辑。

三、节点结构体

typedef struct node {

    int data;   /**数据域*/

    struct node *next;    /**指向下一个节点*/      

}list_node;

因为每个节点的数据结构都是一样的,都为struct node,所以指针域*next的类型也是struct node。

四、创建链表

list_node* list_init()

{

    /**从内存动态申请 #1*/

    list_node *head = (list_node *)malloc(sizeof(list_node));

    /** #2*/

    if(head == NULL) {

        return NULL;

    }

    /**初始化头指针 #3*/

    head->data = 0;

    head->next = NULL;  //链表暂无节点,指针赋为NULL

    /** #4*/

    return head;

}

1、malloc动态申请list_node大小(8个字节)的内存,作为链表的头指针;

2、if(head == NULL)   对malloc的返回值进行判断;

3、初始化头指针,头指针的数据域data没有什么作用,可以用来代表链表的节点数量;

4、返回头指针。

五、插入节点

int list_insert(list_node *head, int data, int pos/** #1*/)

{

    list_node *p = head;



    /**如果要插入的位置比链表长,则属于非法操作 #2*/

    if (pos > p->data) {

        return -1;

    }



    /**动态申请一个节点*/

    list_node *node = (list_node *)malloc(sizeof(list_node));

    if (node == NULL) {

        return -1;

    }

    node->data = data;

    node->next = NULL;



    /**遍历链表,找到要插入的位置 #3*/

    for (int i=0; i<pos; i++) {

        p = p->next;

    }



    /**插入节点 #4*/

    node->next = p->next;

    p->next = node;



    /**链表长度加1*/

    head->data++;

   

    return 0;

}

1、参数pos代表节点插入的位置,首节点的位置为0;

2、对插入位置进行判断,不能大于链表长度,异常返回-1;

3、遍历链表找到新节点要插在哪个节点之后,p指向这个节点;

4、如下图假设node4要插入到node1与node2之间,此时的p指针指向节点为node1,新创建的节点指针node指向node4;

node->next = p->next;   即为 node4->next=node1->next=node2

​p->next = node;   即为 node1->next=node4

d6c2667cd7007e47f47d3ce5b00b6a0c.png​编辑

六、删除节点

int list_delete_node(list_node *head, int pos)

{

    list_node *p = head;



    /**删除的位置比链表长,则属于非法操作*/

    if (pos > p->data) {

        return -1;      

    }

    /**遍历链表,找到要删除的节点的前一个节点的指针*/

    for (int i=0; i<pos; i++) {

        p = p->next;

    }

    /**记录将被删除的节点, 用于最后释放该节点内存 #1*/

    list_node *p2 = p->next;

   

    /**跳过被删除的节点,释放内存,完成删除 #2*/

    p->next = p->next->next;

    free(p2);

   

    head->data--;

    return 0;

}

1、被删除的节点的内存需要进行释放,避免内存泄漏;

2、如下图,假设要删除node2,则只需直接将node1的next指针指向node3

871ce07718f5cdc475ede2933ac4ec3f.png

七、测试

目录结构

./

├── build                    //编译目录

├── CMakeLists.txt    //cmake 配置文件

├── list_01.c             //源码

├── list_01.h

└── test.c                   //测试文件

工程采用cmake构建,文件均经过测试,编译步骤如下:

1、mkdir build && cd build

2、cmake ../ && make

3、./list_test

源码路径在公众号(Linux杂记)同标题的文章里哈!!

 

标签:node,10,--,list,C语言,链表,next,节点,指针
来源: https://www.cnblogs.com/linux-misc/p/16654317.html

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

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

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

ICode9版权所有