链表的企业级应用案例

简介: 链表的企业级应用案例

Linux 内核“共享双向链表

在 linux 内核中,有大量的数据结构需要用到双向链表,例如进程、文件、模块、页面等。若采用双向链表的传统实现方式,需要为这些数据结构维护各自的链表,并且为每个链表都要设计插入、删除等操作函数。因为用来维持链表的 next 和 prev 指针指向对应类型的对象,因此一种数据结构的链表操作函数不能用于操作其它数据结构的链表。比如,我们需要分别定义星星和 web 服务器超时的链表结构 :


一. web服务器超时的链表结构

typedef struct { 
int fd ;
time_t timeout; // 使用超时时刻的时间戳表示
}ConnTimeout;
struct Link_Node{ 
ConnTimeout conn; 
struct Link_Node *next;
}

二.璀璨星空的链表结构

typedef struct {
    int x;  //星星的x坐标 
    int y;  //星星的y坐标
    enum STATUS stat; //状态 
    unsigned radius;  //星星的半径
    int step; //每次跳跃的间隔
    int color;  //星星的颜色
}STAR;
struct Link_Node{ 
STAR  star;
struct Link_Node *next;
}

有没有一种方式,可以让多个链表共享同一套链表的操作?请看下图:

361cfb1fe1524f96acadfecb9e5dcb3f.png


b32fdbc8eb4e46e89bd94c11dc0fed5d.png

typedef struct _DoubleLinkNode {
struct _DoubleLinkNode *next; //下一个节点的指针域 
struct _DoubleLinkNode *prev; //上一个结点的指针域
}DbLinkNode;
typedef struct {
int fd ;
time_t timeout; // 使用超时时刻的时间戳表示 DbLinkNode node; // 双向链表节点“挂件”
}ConnTimeout;


0b1716ad4d86499588166c4852a715d8.png

typedef struct {
int x;  //星星的x坐标 
int y;  //星星的y坐标
enum STATUS stat; //状态 
unsigned radius;  //星星的半径
int step; //每次跳跃的间隔
int color; //星星的颜色
DbLinkNode node; // 双向链表节点“挂件”
}STAR;

实现要点

使用 offsetof 可以根据链表节点在结构体中的地址逆推出结构体变量的位置.

如:

typedef struct {
int fd ;
time_t timeout; // 使用超时时刻的时间戳表示 
DbLinkNode node; // 双向链表节点“挂件”
}ConnTimeout;
//通过节点访问到节点承载的数据
ConnTimeout *ct = new ConnTimeout; 
DbLinkNode  *p = &(ct->node);
cout<<"请输入超时节点对应的fd: "; 
cin>>ct->fd;
cout<<"\n通过链表中的节点访问节点上承载的数据:"<<endl;
int offset = offsetof(ConnTimeout, node);
ConnTimeout *tmp = (ConnTimeout *)((size_t)p-offset); 
printf("offset: %d\n", offset);
printf("通过链表节点node访问到的数据:%d\n", tmp->fd);

源码实现:

#include <iostream>
#include <Windows.h>
using namespace std;
typedef struct _DoubleLinkNode
{
  //int data;//结点的数据域
  struct _DoubleLinkNode* next; //下一个结点的指针域
  struct _DoubleLinkNode* prev;
}DbLinkNode, DbLinkList; //LinkList为指向结构体LNode的指针类型
typedef struct
{
  int fd;
  time_t timeout; //使用超时时刻的时间戳表示
  DbLinkNode node; //双向链表结点“挂件”
}ConnTimeout;
typedef struct
{
  int x;
  int y;
  enum STATUS stat;
  unsigned radius;
  int step;
  int color;
  DbLinkNode node;
}STAR;
bool DbList_Init(DbLinkList &L)
{
  L.next = NULL;
  L.prev = NULL;
  return true;
}
bool DbListInsert_back(DbLinkList &L, DbLinkNode &node)
{
  DbLinkNode* last = NULL;
  last = &L;
  while (last->next)
  {
    last = last->next;
  }
  node.next = NULL;
  last->next = &node;
  node.prev = last;
  return true;
}
int main(void)
{
  ConnTimeout* cl = NULL, * s = NULL;
  STAR* sl = NULL;
  int n = 0;
  //1.初始化一个空的双向链表
  cl = new ConnTimeout;//因为这已经生成了(DbLinkNode node不是生成的指针),所以init不用初始化
  cl->fd = -1;
  sl = new STAR;
  sl->x = -1;
  DbList_Init(cl->node);
  DbList_Init(sl->node);
  //2.尾插法
  cout << "尾插法创建双向链表" << endl;
  cout << "请输入元素个数n:";
  cin >> n;
  cout << "\n请依次输入n个元素的文件句柄:" << endl;
  while (n > 0)
  {
    s = new ConnTimeout; //生成新节点s
    cin >> s->fd;
    printf("s  的地址:%p  node:%p\n0", s, &(s->node));
    DbListInsert_back(cl->node, s->node);
    n--;
  }
  //3.根据链表节点访问数据
  DbLinkNode* p = NULL;
  p = &(cl->node);
  cout << "遍历链接超时链表中的节点:" << endl;
  while (p)
  {
    int offset = offsetof(ConnTimeout, node);
    ConnTimeout* ct = (ConnTimeout*)((size_t)p - offset);
  }
  //4.销毁
  DbLinkNode* tmp = NULL;
  p = &(cl->node);
  cout << "销毁连接超时链表中的节点:" << endl;
  while (p)
  {
    int offset = offsetof(ConnTimeout, node);
    ConnTimeout* ct = (ConnTimeout*)((size_t)p - offset);
    printf("offset:%u  ct:%p  p:%p\n", offset, ct, p);
    cout << ct->fd << endl;
    p = p->next;
    delete ct;
  }
  //通过节点访问到节点访问到节点承载的数据
  //ConnTimeout* ct = new ConnTimeout;
  //DbLinkNode* p = &(ct->node);
  //cout << "请输入超时节点对应的fd:";
  //cin >> ct->fd;
  //cout << "\n通过链表中的节点访问节点上承载的数据:" << endl;
  //int offset = offsetof(ConnTimeout, node);
  //ConnTimeout* tmp = (ConnTimeout*)((size_t)p - offset);
  //printf("offset:%d\n", offset);
  //printf("通过链表节点node访问到的数据:%d\n", tmp->fd);
  system("pause");
  return 0;
}
相关文章
|
3月前
|
存储 缓存 NoSQL
作者推荐 |【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(链表)(一)
作者推荐 |【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(链表)
50 0
|
3月前
|
存储 机器学习/深度学习 NoSQL
作者推荐 |【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(链表)(二)
作者推荐 |【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(链表)
55 0
|
3月前
|
存储 编译器 测试技术
速学数据结构 | 手把手教你会单链表的构建方式
速学数据结构 | 手把手教你会单链表的构建方式
46 0
|
10月前
|
存储
数据结构入门指南:链表(新手避坑指南)
数据结构入门指南:链表(新手避坑指南)
44 0
队列的企业级应用案例
队列的企业级应用案例
|
前端开发
前端学习案例3-链表的使用3
前端学习案例3-链表的使用3
42 0
前端学习案例3-链表的使用3
|
前端开发
前端学习案例6-链表的使用6
前端学习案例6-链表的使用6
66 0
前端学习案例6-链表的使用6
|
前端开发
前端学习案例4-链表的使用4
前端学习案例4-链表的使用4
48 0
前端学习案例4-链表的使用4
|
前端开发
前端学习案例2-链表的使用2
前端学习案例2-链表的使用2
46 0
前端学习案例2-链表的使用2
|
前端开发
前端学习案例5-链表的使用5
前端学习案例5-链表的使用5
49 0
前端学习案例5-链表的使用5