KM的博客.

数据结构思想

字数统计: 1.4k阅读时长: 4 min
2019/06/22

第一篇数据结构

数组和链表


数组和链表对比

思考题: 1.如何分别用链表和数组实现LRU缓冲淘汰策略?

1)什么是缓存?

  • 缓存是一种提高数据读取性能的技术,在硬件设计、软件开发中都有着非广泛的应用,比如常见的CPU缓存、数据库缓存、浏览器缓存等等。

什么是C CPU在从内存读取数据的时候,会先把读取到的数据加载到CPU的缓存中。而CPU每次从内存读取数据并不是只读取那个特定要访问的地址,而是读取一个数据块(这个大小我不太确定。。)并保存到CPU缓存中,然后下次访问内存数据的时候就会先从CPU缓存开始查找,如果找到就不需要再从内存中取。这样就实现了比内存访问速度更快的机制,也就是CPU缓存存在的意义:为了弥补内存访问速度过慢与CPU执行速度快之间的差异而引入。

2)为什么使用缓存?即缓存的特点

  • 缓存的大小是有限的,当缓存被用满时,哪些数据应该被清理出去,哪些数据应该被保留?就需要用到缓存淘汰策略。

3)什么是缓存淘汰策略?

  • 指的是当缓存被用满时清理数据的优先顺序。

4)有哪些缓存淘汰策略?

  • 先进先出策略FIFO(First In,First Out)
  • 最少使用策略LFU(Least Frenquently Used)
  • 最近最少使用策略LRU(Least Recently Used)。

5)链表实现LRU缓存淘汰策略

我们维护一个有序单链表,越靠近链表尾部的结点是越早之前访问的。当有一个新的数据被访问时,我们从链表头开始顺序遍历链表。

    1. 如果此数据之前已经被缓存在链表中了,我们遍历得到这个数据对应的结点,并将其从原来的位置删除,然后再插入到链表的头部。
    1. 如果此数据没有在缓存链表中,又可以分为两种情况:
  • 如果此时缓存未满,则将此结点直接插入到链表的头部;
  • 如果此时缓存已满,则链表尾结点删除,将新的数据结点插入链表的头部。

6)数组实现LRU缓存淘汰策略

方式一

  • 首位置保存最新访问数据,末尾位置优先清理
  • 当访问的数据未存在于缓存的数组中时,直接将数据插入数组第一个元素位置,此时数组所有元素需要向后移动1个位置,时间复杂度为O(n);
  • 当访问的数据存在于缓存的数组中时,查找到数据并将其插入数组的第一个位置,此时亦需移动数组元素,时间复杂度为O(n)。
  • 缓存用满时,则清理掉末尾的数据,时间复杂度为O(1)。

方式二

  • 首位置优先清理,末尾位置保存最新访问数据

  • 当访问的数据未存在于缓存的数组中时,直接将数据添加进数组作为当前最有一个元素时间复杂度为O(1);

  • 当访问的数据存在于缓存的数组中时,查找到数据并将其插入当前数组最后一个元素的位置,此时亦需移动数组元素,时间复杂度为O(n)。

  • 缓存用满时,则清理掉数组首位置的元素,且剩余数组元素需整体前移一位,时间复杂度为O(n)。(优化:清理的时候可以考虑一次性清理一定数量,从而降低清理次数,提高性能。)

2.如何通过单链表实现“判断某个字符串是否为回文字符串”?

方法一:半栈法

  • 1.用快慢两个指针遍历,同时用栈copy慢指针指向的data。
  • 2.完成后,慢指针指向中间节点,耗时为N/2.
  • 3.最后用pop栈中的data和慢指针指向的data比较,耗时也是N/2.
  • 所以时间复杂度为:O(N),空间复杂度因栈额外存储了一半的data,故为O(N/2)

方法二:全栈法

  • 1)前提:字符串以单个字符的形式存储在单链表中。
  • 2)遍历链表,判断字符个数是否为奇数,若为偶数,则不是。
  • 3)将链表中的字符倒序存储一份在另一个链表中。
  • 4)同步遍历2个链表,比较对应的字符是否相等,若相等,则是回文字串,否则,不是。

方法三:硬干法

    1. 一个指针从头取data,另一个指针遍历到底取data,比较二者
  • 2.删除尾部节点,重复1.
  • 时间复杂度高达 O(N^2),空间复杂度却最低O(1)

数据结构

算法思想

算法题目推荐

CATALOG
  1. 1. 第一篇数据结构
    1. 1.1. 数组和链表
    2. 1.2. 思考题: 1.如何分别用链表和数组实现LRU缓冲淘汰策略?
    3. 1.3. 2.如何通过单链表实现“判断某个字符串是否为回文字符串”?
    4. 1.4. 方法一:半栈法
    5. 1.5. 方法二:全栈法
    6. 1.6. 方法三:硬干法
  • 数据结构
  • 算法思想
  • 算法题目推荐