链表的基础概念这里就不讲了,随便一个搜索引擎就能找到无数答案,我这里想讲点别人不会讲的东西,以及尝试如何让一窍不通于链表的同学快速理解和入门。
我们知道链表是由一个个结点串联而成的,而每个结点分为两块区域,一块是数据域,相当于数组中存储的那个数据;另一块是指针域,这里存放的是指向下一个结点的地址。在链表遍历的过程中,我们根据前一个结点的指针域中的那个地址找到下一个结点,就这样一个接一个往下遍历,进行增删改查等一系列基础操作。
知道了结点的基础结构就可以来进行创建了。
这里使用typedef是为了重命名,省的以后创建指针时还要连带着 struct lint*。之后创建指针就可以直接Lint* p而不是struct lint* p
链表中有一个特殊的结点–头结点。头结点的数据域一般不用来存放和其他节点同类的数据,它的诞生是为了在实际应用过程中存放一些数据(下面会演示到)。
再来看有头结点的初始化方式(由于存在头结点稍微有些复杂,因此后续的演示会采用有头结点的链表):
现在我们已经完成了整条链表的手动赋值初始化,最基础的当然就是输出链表了。
基本的思想非常简单,头指针已经指明了链表的头,利用指针输出结点的数据,然后根据指针域中的地址移到下一个结点,循环往复,一直到指针域为空就停止输出。
增加结点的逻辑是:将新增结点的指针域指向后一个结点,然后将原链表中的前一个结点的指针域指向新增的结点。(注意顺序不能颠倒,否则会导致插入位置后面的结点全部丢失)
逻辑和增差不多,将temp指针指向要删除结点的直接前驱,将指针域指向下下个结点,然后释放删除结点的内存即可。
查的基本思想是指针进行遍历链表,对每个节点的数据域进行对比,如果相同就可以直接退出返回结果了。如果一直到链表结束还没有匹配成功就说明没有找到。
当然也可以将头结点的数据域用于存储位置,而无需单独创建一个i用于记录位置。