数据结构基础之链表(一)

线性表是一类很常用的数据结构,分为顺序表和链表。其中顺序表可以简单地理解成前面介绍的“数组”这个概念,接下来我们讲解一下链表。
按照正常方式定义一个数组时,计算机会从内存中取出一块连续的地址来存放给定长度的数组;而链表则是由若干个结点组成(每个结点代表一个元素),而且结点在内存中的存储位置通常是不连续的。除此之外,链表的两个结点之间一般通过一个指针来从一个结点指向另一个结点,因此链表的结点一般由两部分组成,即数据域和指针域:

struct node{
	typename data ;//数据域
	node* next; / /指针域
}
//补充一点小知识:很多同学老说这个“*”号到底放在哪呢,
//其实放哪都行,放在typename后面挨着也行,放在变量名前面挨着也行。

数据域存放结点要存储的数据,指针域指向下一个结点的地址,这样就会产生从某个结点开始的、由指针链接的一条链式结构,即链表。而以链表是否存在头结点,又可以把链表分为带头结点的链表和不带头结点的链表。头结点一般称为head,其数据域data不存放任何内容,而指针域next指向第一个数据域有内容的结点(一般称其为第一个结点)。大部分情况都会采用有头结点的写法。
在这里插入图片描述
在这里插入图片描述

使用malloc函数或者new运算符来为链表结点分配内存空间

上面我们已经知道如何定义链表的结点类型,接下来我们将如何在每次需要使用新结点时候临时分配相应大小的内存空间给新结点。C语言采用malloc函数,C++采用new运算符。

malloc函数

malloc函数是C语言中stdlib.h头文件下用于申请动态内存的函数,其返回类型申请的同变量类型的指针,基本用法如下:

typename* p = (typename*)malloc(sizeof(typename));
//以下是申请一个int型变量和一个node型结构体变量为例:
int *p = (int*)malloc(sizeof(int));
node *p = (node*)malloc(sizeof(node));

这个写法的逻辑是:以需要申请的内存空间的大小(即sizeof(int))为malloc函数的参数,这样malloc函数就会向内存申请一块大小为sizeof(int)的空间,并且返回指向这空间的指针。但是此时这个指针是一个未确定类型的指针void*,因此需要把它强制转换为int型指针,因此malloc之前加上(node)。这样等号右边就得到一个int型的指针,并通过赋值等号把这个指针赋给node型的指针变量p,就成功申请了一块node类型大小的内存空间,即一个node型的结构体变量,并通过指针p来访问它,如果申请失败了,则会返回空指针NULL。
一般来说,只是申请一个链表的结点是不会失败的,失败一般发生在使用malloc申请了较大的动态数组,即
在这里插入图片描述
这种情况malloc会返回空指针NULL并赋值给p。
在这里插入图片描述

内存泄漏问题

内存泄露是指使用malloc与new开辟出来的内存空间在使用过后没有释放,导致其在程序结束之前始终占据该内存空间,这在一些大的程序中很容易导致内存消耗过快以至于最后无内存可分配。在使用完malloc与new开辟出来的空间后必须将其释放。
(1)free函数
free函数是对应malloc函数的,同样是在stdlib.h下。只需要在free的参数中填写需要释放的内存空间的指针变量(假设为p)即可:

free(p);

free函数主要实现了两个效果:释放指针变量p所指向的内存空间:将指针变量p指向空地址NULL。由此可见,在free函数执行之后,指针变量p本身并没有消失,只不过让他指向了空地址NULL,但是他原来指向的内存确实是被释放了的。
在这里插入图片描述

发布了19 篇原创文章 · 获赞 2 · 访问量 735

猜你喜欢

转载自blog.csdn.net/zan1763921822/article/details/105599239