链表
本质上是一个结构体指向下一个结构体,第一个结构体为链头,重点是指向下一个(next)结构体
代码实现
创建链表
struct Element //链表元素 { char *name; struct Element *next; //名为next的结构体的指针 }; struct List //链头 { char *name; struct Element *next; //名为next的结构体的指针 }; //分别创建结构体对象L1,A1 struct List L1; struct Element A1; L1.name = "L1"; L1.next = NULL; //此时没有链表元素,链头下一个结构体对象不存在 A1.name = "A1"; A1.next = NULL; //A1的下一个结构体对象不存在 L1.next = &A1; //链头的下一个结构体对象为A1
删除链表
当需要在List中删除A项,执行以下判断
先令指针pre = NULL,p = A。进行循环判断。当p不为NULL和不为A时,pre=p,p=p->next,进下一次循环。当p为NULL时直接返回,表示List没有A项;当p为A时即找到需要删除的元素,则pre从指向p改成指向NULL,表示pre已是队尾,p踢出链表;当循环结束pre仍为NULL时表示A是链表第一个元素,则pre指向A后面的元素,即pre = p->next。
通用链表
很容易看出来,当结构体不同时,链表操作函数需要跟着多一套出来。所以需要一个通用链表
原理:
之前的普通链表使用的是对应结构体的下一个结构体的指针next,next指向结构体的头部,于是next指针本身具有针对性(针对特定个结构体),如下图
而通用链表,是先定义一个节点结构体node,嵌入每个结构体owner,类似于结构体身上带着一块牌子,通过节点结构体之间的联系找到对应的结构体,node结构体内部只有一个元素,就是下一个node的指针next。如此一来链表也一样使用node节点,无视结构体差异如下图
那么,如何由node找出其owner?有以下三种方式
1. node节点放在owner结构体的第一位,则node节点地址本身等于owner地址
2. node节点放在owner结构体的固定偏移位,通过计算推断
3. node节点内部设置一个指针,指向owner结构体,所以在初始化node节点时也需要一并传入owner地址
而node所在的链表称之为其container
标签:node,A1,笔记,next,链表,owner,整理,数据结构,结构 From: https://www.cnblogs.com/toriyung/p/16797263.html