六、封装链表
尾添加的效率低,非法下标的判断效率非常低
1.单链表
结点:
数据域
指针域
单链表数据项:
头结点:
尾结点:
结点数量:
2.静态链表
结点:
数据域
游标
静态链表的结点存储在连续的内存中,通过游标来访问下一个结点
牲了随机访问的功能,也没达到链表动态申请内存的效果,只是给没有指针的编程语言实现链表的一种方式,适用范围不大
3.循环链表
结点:
链表的最后一个结点的next不再指向NULL,而是指向头结点,这种链表称为单向链表,简称循环链表
可以通过任意结点来遍历整个链表
4.双向链表
结点:
前驱指针: prev
数据域
后继指针: next
数据项
头结点:
结点数量:
特点:
1.在任意结点都可以遍历整个链表
2.相比单链表,删除、插入更直接
3.已知结点位置,可以选择从前往后或者从后往前遍历,提高链表访问效率
5. Linux内核通用链表
链表的结点不能包含万物,就让万物包含结点
例如:
typedef struct Student
{
char name[20];
char sex;
char age;
Node node; //
float score;
int id;
}Student;
//计算结构成员member 所在结构中距离第一个成员地址编号的差值
#define offset(type,member) ((int)&((type*)0->member))
//计算返回实际的结构成员指针所在的结构变量首地址
#define node_to_obj(node,type,member) ((type*)((void*)node-offset(type,member)))
//遍历链表
#define list_for_each(n,head)\
for(n=head->next;head!=n;n=n->next)
//遍历2
#define list_for_each_entry(obj ,head,member)\
for (obj = node_to_obj(head->next,typeof(*obj),member);\
head!= &(obj->member);\
obj=node_to_obj(obj->member.next,typeof(*obj),member))
6.通用链表
结点:
void* ptr;
指针域:
运算:
常规功能 + 回调函数
关于链表的常考题(牛课(算法里))
1.单链表逆序
2.找出单链表倒数第n个结点
3.判断链表中是否有环
4.找到环形入口
5.合并两个有序链表,依然有序
6.判断两个链表是否有y型,找出相交点