链表的企业级应用案例

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

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月前
|
消息中间件 存储 Java
数据结构之 - 深入探析队列数据结构: 助你理解其原理与应用
数据结构之 - 深入探析队列数据结构: 助你理解其原理与应用
67 4
|
3月前
|
存储
【数据结构】二叉树零基础无压力上手,超详解
【数据结构】二叉树零基础无压力上手,超详解
38 0
|
7月前
|
存储 算法 调度
【数据结构与算法】详解循环队列:基于数组实现高效存储与访问
【数据结构与算法】详解循环队列:基于数组实现高效存储与访问
深度剖析数据结构之链表(引言)
深度剖析数据结构之链表(引言)
56 0
|
8月前
|
缓存 Go 调度
掌握Go语言:Go语言链表精解,揭秘高效数据结构,应用场景全揭秘(17)
掌握Go语言:Go语言链表精解,揭秘高效数据结构,应用场景全揭秘(17)
|
8月前
|
机器学习/深度学习 存储 Java
揭秘数组:数据结构的基石与代码实践解析
揭秘数组:数据结构的基石与代码实践解析
36 0
|
8月前
|
存储 搜索推荐 算法
从0开始回顾数据结构---十大排序算法
十大排序算法 复杂度和稳定性一览 排序算法 平均时间 最好时间 最坏时间 空间 稳定性 冒泡排序 $O(n^2)$ $O(n)$ $O(n^2)$ $O(1)$ 稳定 选择排序 $O(n^2)$ $O(n^2)$ $O(n^2)$ $O(1)$ 不稳定 插入排序 $O(n^2)$ $O(n)$ $O(n^2)$ $O(1)$ 稳定 希尔排序 $O(nlogn)$~$O(n^2)$ $O(nlogn)$ $O(n^2)$ $O(1)$ 不稳定 归并排序 $O(nlogn)$ $O(nlogn)$ $O(nlogn)$ $O(n)$ 稳定 快速排序 $O(nlogn)$ $O(nlogn)$
|
存储 算法
入门篇2:如何系统高效的学习算法与数据结构
入门篇2:如何系统高效的学习算法与数据结构
队列的企业级应用案例
队列的企业级应用案例
|
存储 运维 算法
数据结构 | 顺序表SeqList【内附众多生活小案例~】
有关数据结构顺序表的算法实现详细介绍,内含众多生活小案例,让你不再枯燥学习
122 0
数据结构 | 顺序表SeqList【内附众多生活小案例~】