C language, implementation of singly linked list

  1. Linked list related knowledge

1.1 The concept of linked list:

The linked list is a non-sequential and non-sequential storage structure in the physical storage structure . The logical order of the data elements is through the linked list

The pointer link order in is implemented.

1.2 Advantages and disadvantages of linked list

Advantages of linked list :

Since the memory addresses of the elements on the linked list are not continuous in the space storage, there will not be a large number of element displacements when randomly adding or deleting elements, so the random addition and deletion is more efficient .

In future development, if there are many businesses that randomly add or delete elements in the collection, it is recommended to use LinkedList.

Disadvantages of linked list:

The memory address of the searched element cannot be calculated through mathematical expressions, and each search starts from the beginning

Nodes are traversed until found. So the efficiency of LinkedList collection retrieval/lookup

lower.

2. Classification of linked lists

2.1 One-way and two-way:

2.2 Leading and not leading:

2.3 Non-circular linked list and circular linked list

There are many types of linked lists, but we usually only have headless one-way non-circular linked lists and headed two-way circular linked lists

1. Headless one-way non-circular linked list : the structure is simple , and it is generally not used to store data alone. In practice, it is more used as other data structures

Structured substructures , such as hash buckets, adjacency lists of graphs, and so on.

2. 带头双向循环链表结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带

来很多优势,实现反而简单了。

3.单链表的实现

今天讲无头单向非循环链表的实现,后续会补充带头双向循环链表

下图链表的基本接口

这里可以发现多个接口都用了二级指针,为什么这里会用到二级指针呢,

原因很简单,因为尾插,尾删,头插,头删都有可能改变头指针指向的位置(即头指针plist存放的内容)

3.1 单链表的实现

链表是由多个节点相互连接形成的一种数据结构,总的来说链表的基本单位是节点

3.2第一步需要先创建一个节点(结构体)

其成员有两个:

其一 SLDataType类型的结构体变量data用来存放数据

其二next指针用来存放下一个节点的地址,以便节点间连接

现在来说说链表是怎么相连接起来的吧,链表中每个节点都有一个next指针用来存放下一个节点的地址,这样就可以把每个节点连接起来了

上表相当于链表的示意图,方便我们了解,实际上它们之间是没有箭头相连的

对于一个空链表内部是不会有任何数据的,所以我们用来指向链表的头指针plist此时是指向NULL的

3.3节点的申请

申请一个节点,然后给data赋值,最后返回这个节点的地址

3.4链表的尾插

申请玩节点以后就可以进行数据的插入了

尾插就是在链表的最后一个节点后面插入一个节点,考虑到如果此时链表为空的话,则直接让头指针指向该节点,不为空那么就找链表的尾(最后一个节点)让其指向新的节点即可

3.5链表的尾删

在删除一个数据的时候都会判断1.该链表为不为空,就像在顺序表中删除一个数据一样,如果为空就没有数据可以删了,所以报出该错误。

2.当链表只有一个元素的时候,且该元素被删除了,需要把头指针plist置空

3.以上两种情况都没有的话,直接找链表的尾,此时需要保存倒数第二个节点的地址,所以用到了pvr指针,当把最后一个节点删除后,此时pvr指针就为指向最后一个节点的指针了,让pvr->next==NULL

3.6链表的打印

这就是遍历一遍链表,打印出存进去的内容

3.7检查接口的准确性

由上图发现目前实现的接口没有问题

3.8链表的头插

这里并不需要判断链表是否为空,因为就算链表为空也没有影响

3.9链表的头删

删除判断链表是否为空应该是不用多说了的

这个相对与尾删是比较简单的,首先让一个指针保存头节点的地址,然后让头指针指向第二的节点

最后释放掉第一个节点就ok了

4.0数据的查找

传入需要查找的值X,如果找到了就返回该值所在节点的地址,如果找不到就返回NULL;

这也是比较简单的,就直接上代码了,不过多说了

4.1任意位置的插入(指定位置的插入)

在指定位置插入一个数据的时候肯定是不许pos为空的,

  1. *pphead(plist)头指针的值和pos相等的时候就相当于头插,直接调用头插函数就行

  1. 其他情况,找到pos节点前面的一个节点的地址存在prev中,然后让新节点连接pos节点,最后让prev节点连接新节点

4.2任意位置的删除(指定位置删除)

  1. 当需要删除一个数据的时候判断链表是否为空(*pphead==NULL)就不多说了,上面已经提过了

  1. 当pos等于*pphead时,此时就相当于头删,头删的原理上文也已经阐述过了,就不过多解释了

  1. 其他情况,找到pos节点前面的一个节点的地址存在prev中,然后让prev节点连接pos后面的节点,最后把pos这个节点释放掉

4.3任意位置后面插入数据(指定位置后面插入数据)

这不会改变头指针,所以用一级指针就OK了

4.4删除任意位置后面的数据(删除指定位置后面的数据)

4.5链表的销毁

最后面这三个接口比较简单不再过多阐述

单链表就介绍到这了,如果有错误的地方还望能指出,以便我们共同进步

最后在不同文件中定义接口的时候可不要忘了声明这个接口的函数哈,

今天的分享就到这吧(886!!!),路过的小伙伴们给个关注吧,感谢支持

Guess you like

Origin blog.csdn.net/m0_72532428/article/details/129326059