浅谈Go与习题(三十七)

38 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 27 天,点击查看活动详情

今天来学习下Go常见的习题问题(三十七),也是面试中可能会遇到的,让我们来一起学习吧~

链表

redis中的链表底层数据结构如下所示:

typedef struct listNode {
    // 前置节点
    struct listNode *prev;
    // 后置节点
    struct listNode *next;
    // 节点的值
    void *value;
} listNode;

紧接着会使用adlist.h/list中的list来持有listNode节点,这样方便统计长度,以及匹配,释放等操作,相应的结构体如下所示:

typedef struct list {
    // 表头节点
    listNode *head;
    // 表尾节点
    listNode *tail;
    // 链表所包含的节点数量
    unsigned long len;
    // 节点值复制函数
    void *(*dup)(void *ptr);
    // 节点值释放函数
    void (*free)(void *ptr);
    // 节点值对比函数
    int (*match)(void *ptr, void *key);
} list;
  • dup 函数: 复制链表节点所保存的值
  • free 函数: 释放链表节点所保存的值
  • match 函数: 对比链表节点中的保存的值与传入的key值是否一致

image.png

redis的链表是一个双向链表,其中的特性如下:

  1. 双端队列: 因为链表节点有 prev 和 next 指针, 获取当前某个链表节点的前置或者后置节点的复杂度为O(1)
  2. 无环链表: 因为链表的头节点的 prev 指针和表尾节点的 next 指针都指向 NULL,所以遍历链表只要碰到NULL即可结束
  3. 头指针和尾指针:通过链表中的head 指针和 tail 指针, 获取到链表的头结点或者尾结点的复杂度为O(1)
  4. 链表长度: 通过链表中的 len属性,就可以轻松获取当前链表中的节点数量,复杂度为O(1)
  5. 多态属性: 链表中存在 void* 指针来保存节点值, 并且可以通过dup 、 free 、 match 三个方法来为节点设置特定的函数,这样就可以处理不同类型的值

总结

今天浅谈了Go的习题(三十七),参考资料《redis设计与实现》,接下来会继续分享其他的习题的相关知识,对于一个刚入门的我来说,还有许多地方需要学习,有错误的地方欢迎大家指出,共同进步!!