算法网课笔记(三)——链表

常用缓存策略

FIFO、LFU、LRU
如何用链表实现LRU?

链表相关知识

结点后继指针(next)头结点尾结点前驱结点
循环链表双向链表(next、pre)

PS:在“删除某个指针指定的节点”或者“在某个指定节点前插入”这种操作中,双向链表复杂度是O(1),而单链表是O(n); 在“删除特定值的节点”的操作中,二者复杂度都是O(n)

链表在插入删除上,比数组优秀;而在随机访问上,数组为O(1),链表为O(n)
链表的内存相比数组会翻倍
此外,数组的连续内存机制,可以利用CPU的缓存机制,预读数据,而链表做不到
此外,数组需要占用一整块空间,所以申请时过大,可能导致内存不足;过小可能后续开辟新空间时,需要拷贝原数组,很耗时。

用链表实现LRU

思路,维护一个有序单链表,越靠近尾部的节点,是越久之前访问的,当有新的数据被访问,从链表头开始顺序遍历。
1.如果此数据存在,则读取,然后删除原位置节点,在插入到头部
2.如果不存在
2.1 如果缓存未满,则将此节点直接插入链表头部
2.2 如果缓存已满,则删除尾结点,插入头结点
由于必定会遍历链表,所以缓存访问的时间复杂度为O(n)

// 链表节点的C++定义法
struct ListNode
{
	int data;
	struct ListNode *next;
};

通过引入**散列表(Hash table)**可以将复杂度降到O(1)

如何写链表

一、理解指针/引用的含义
将变量赋值给指针,就是将变量的地址赋值给指针,即,指针中保存的是变量的内存地址,通过该指针能够找到变量。

二、警惕指针丢失和内存泄漏
合理安排指针改变的顺序,防止指针丢失
删除链表节点时,手动释放内存空间

三、利用哨兵减缓实现难度
此处的哨兵指的就是“头指针”,即不参与数据保存一个的一个头结点

四、多检查边界
链表为空/仅一个节点/仅两个节点时能否正常工作?
代码能否正常处理头尾节点?

五、画图辅助

课后练习

单链表翻转
链表中环检测
有序链表合并
删除倒数第n个节点
求链表中间节点

PS:typedef关键字在C和eC++中的区别

C++中可以不用typedef定义结构体,C中可能会编译不通过
https://blog.csdn.net/sjxbf/article/details/6330177

PS:解引用、引用、取地址运算

https://blog.csdn.net/qq_38556370/article/details/80631725
(*p).成员名
p->成员名

PS:算法题——判断回文串

PS:如何使用数组实现LRU策略

PS:约瑟夫问题

PS:java的LinkHashMap原理

PS:用时间换空间(或空间换时间)的例子

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值