0


猿创征文 | 内存管理实现单链表的插入和删除

内存管理实现单链表的插入和删除

1.收获

进一步理解动态内存,指针,和结构体

2. 什么是单链表?

在数据结构中,存储结构有一种是链式存储结构。单链表就是链式存储的一种实现方式。

​​ ​​它与顺序结构存储不同,顺序结构在内存中开辟的空间一定是连续的,例如我们的数组就是顺序存储。

单链表中每个节点(矩形)在内存中的地址不一定是连续的,通过指针来找到下一个节点。
每一个节点中存放两个内容,一个是数据,一个是指针。指针是用来找到下一个节点。
也就是说,下一个节点,只能通过它上一个节点去访问它。

这里介绍单链表的头插入和头删除

这里讲的动态内存函数是malloc和free
简单介绍一下这两个函数。
malloc()
向堆区申请一块空间,返回值是地址,地址的类型是void*因此在接收这个地址的时候,需要强制类型转换。
()内部是你需要申请多大的空间单位是字节。
一般可以这样malloc( sizeof( 类型 )*常数 )使用 。
int * p = (int * ) malloc ( sizeof(int) * 10);
free()
释放在堆区开辟的空间,即释放malloc,realloc,calloc开辟的空间
()内部是 要释放空间的起始地址。

3.节点的创建

typedefstructNode{int data;//存数据structNode* next;//指向下一个节点(存地址)}Node_t;//将类型 struct Node 重命名为 Node_t

这里要注意的是,typedef重命名结构体类型名,修改后名字的位置在’ ; '的前面,即Node_t == struct Node

4.主函数的实现

intmain(){//头节点
    Node_t* head =AollocNode(0);//该函数用来申请空间,和存数据int i =0;printf("头插入...\n");for(i =1; i <10; i++){//插入节点//我们需要知道地址才能插入,所以要传入头节点。//i 表示我们插入的数据。HeadInsertNode(head, i);//展示插入的效果ShowNode(head);}printf("头删除...\n");for(i =1; i <10; i++){//同样的我们要删除节点需要知道位置HeadDeleteNode(head);//展示删除的效果ShowNode(head);}//堆区申请的空间需要释放回去//避免内存泄露free(head);//避免野指针,将指针置为NULL
    head =NULL;return0;}

头节点就相当于火车头,其他节点相当于车厢。头节点是链表的起始部位,(给你一个地址)要通过头节点才能对单链表进行操作。

5.子函数的实现

5.1 AollocNode的实现

功能:在堆区开辟空间,存储数据(赋值)
在初始化的时候一般默认下一个节点指向NULL(避免野指针)

Node_t*AollocNode(int x){
    Node_t* newnode =(Node_t*)malloc(sizeof(Node_t));
    newnode->data = x;//存数据
    newnode->next =NULL;//指向下一个节点(最后一个节点指向NULL)return newnode;}

5.2 HeadInsertNode的实现

如何做到头插入?一定是改变指针的指向来实现的,看图理解。

第一次头插入

第二次头插入

第三次头插入

看了这三张图,相信你一定有所发现。头插入,是通过头节点和新节点的指向来达到能够连续访问节点的目的。
我们来看代码:

voidHeadInsertNode(Node_t* head,int x){
    Node_t* new =AollocNode(x);//新增节点,x为存储的数据。
    new->next = head->next;
    head->next = new;}

5.3 ShowNode的实现

功能:打印节点中存放的数据。

ShowNode(Node_t* head){
    Node_t* p = head->next;//指向第一节点while(p)//直到指向NULL循环结束{printf("%d->", p->data);//打印数据Sleep(1000);//停屏1s 看打印效果 图片看不出打印效果,可以自行尝试,更加理解头插入是什么样的。
        
        p = p->next;//指向下一个节点}printf("NULL\n");//为了更了解单链表的样子才如此设计。}

运行结果:

5.4 HeadDeleteNode的实现

这个头删除是最简单的。只要将头节点指向的第一个节点释放,并且头节点指向第二个节点,就完成了删除。

为什么可以这么做呢?我们使用的是内存管理的函数,开辟的空间,是可以free。释放之后就把原有所属的空间归还给操作系统了。

我们来看看图。

假设插入三次。

先看原图

第一次头删除

第二次头删除

第三次头删除

voidHeadDeleteNode(Node_t* head){
    Node_t* p = head->next;//新增指针p指向头节点指向的第一个节点

    head->next = p->next;//改变头节点的指向,指向第一个节点的下一个节点//即头节点指向第二个节点free(p);//p已经指向了第一个节点的起始地址,free(p)就是释放第一个节点}

运行结果:

在这里插入图片描述

6.源代码

#include<stdio.h>#include<stdlib.h>#include<Windows.h>typedefstructNode{int data;structNode* next;}Node_t;//将类型 struct Node 重命名为 Node_t//向堆区开辟空间给节点,并赋值
Node_t*AollocNode(int x){
    Node_t* newnode =(Node_t*)malloc(sizeof(Node_t));
    newnode->data = x;//存数据
    newnode->next =NULL;//指向下一个节点(最后一个节点指向NULL)return newnode;}voidHeadInsertNode(Node_t* head,int x){
    Node_t* new =AollocNode(x);//新增节点,x为存储的数据。
    new->next = head->next;
    head->next = new;}ShowNode(Node_t* head){
    Node_t* p = head->next;while(p){printf("%d->", p->data);Sleep(100);
        p = p->next;}printf("NULL\n");}voidHeadDeleteNode(Node_t* head){
    Node_t* p = head->next;//新增指针p指向头节点指向的第一个节点

    head->next = p->next;//改变头节点的指向,指向第一个节点的下一个节点//即头节点指向第二个节点free(p);//p已经指向了第一个节点的起始地址,free(p)就是释放第一个节点}intmain(){//头节点(第一个节点)
    Node_t* head =AollocNode(0);//int i =0;printf("头插入...\n");for(i =1; i <10; i++){//插入节点//我们需要知道地址才能插入,所以要传头节点。//i 表示我们插入的数据。HeadInsertNode(head, i);//展示插入的效果ShowNode(head);}printf("头删除...\n");for(i =1; i <10; i++){//同样的我们要删除节点需要知道位置HeadDeleteNode(head);//展示插入的效果ShowNode(head);}//堆区申请的空间需要释放回去//避免内存泄露free(head);//避免野指针,将指针置为NULL
    head =NULL;return0;}

7.结束语

可以自己尝试去写写,图片也自己画画,加深印象。
希望对你有所帮助。


本文转载自: https://blog.csdn.net/m0_64212811/article/details/126669860
版权归原作者 日向晚,声声慢 所有, 如有侵权,请联系我们删除。

“猿创征文 | 内存管理实现单链表的插入和删除”的评论:

还没有评论