嵌入式学习数据结构(二)双向链表 内核链表

目录

双向链表

头文件

创建

遍历

头插

尾插

头删

尾删

查找指定节点

修改

删除指定结点

销毁

内核链表


双向链表

与单向链表相比,双向链表多增加一个指针域,指向前一个结点。

头文件

cpp 复制代码
#ifndef __DOULINK_H__
#define __DOULINK_H__
//双向链表存储的数据类型
typedef struct stu
{
    int id;
    char name[32];
    int score;
}Data_type_t;

/*双向链表的结点类型*/
typedef struct dounode
{
    Data_type_t data;
    struct dounode *ppre;  //指向前驱结点的指针
    struct dounode *pnext; //指向后继结点的指针
}DNode_t;

/*双向链表对象类型*/
typedef struct doulink
{
    DNode_t *phead;   //双向链表头结点地址
    int clen;         //双向链表结点个数
}DLink_t;


extern DLink_t *create_doulink();
extern int insert_doulink_head(DLink_t *pdlink, Data_type_t data);
extern int is_empty_doulink(DLink_t *pdlink);
extern void doulink_for_each(DLink_t *pdlink, int dir);
extern int insert_doulink_tail(DLink_t *pdlink, Data_type_t data);
extern int delete_doulink_head(DLink_t *pdlink);
extern int delete_doulink_tail(DLink_t *pdlink);
extern DNode_t *find_doulink(DLink_t *pdlink, char *name);
extern int change_doulink(DLink_t *pdlink, char *name, int score);
extern int delete_point_node(DLink_t *pdlink, char *name);
extern void destroy_doulink(DLink_t **ppdlink);

#endif

创建

cpp 复制代码
DLink_t *create_doulink()
{
  DLink_t *pdlink = malloc(sizeof(DLink_t));
  if (NULL == pdlink)
    {
      printf("malloc error");
      return NULL;
    }
  pdlink->phead = NULL;
  pdlink->clen = 0;
 
  return pdlink;
}

遍历

cpp 复制代码
void doulink_for_each(DLink_t *pdlink, int dir)
{
  if (is_empty_doulink(pdlink))
    {
      return;
    }
  DNode_t *ptemp = NULL;
  ptemp = pdlink->phead;
  if (dir)
    {
      while (ptemp != NULL)
        {
          printf("%d,%s,%d\n", ptemp->data.id, ptemp->data.name,
                 ptemp->data.score);
          ptemp = ptemp->pnext;
        }
    }
  else
    {
      while (ptemp->pnext != NULL)
        {
          ptemp = ptemp->pnext;
        }
      while (ptemp != NULL)
        {
          printf("%d,%s,%d\n", ptemp->data.id, ptemp->data.name,
                 ptemp->data.score);
          ptemp = ptemp->ppre;
        }
    }
  printf("\n");
}

头插

cpp 复制代码
int insert_doulink_head(DLink_t *pdlink, Data_type_t data)
{
  DNode_t *pnode = malloc(sizeof(DNode_t));
  if (NULL == pnode)
    {
      printf("malloc error");
      return -1;
    }
  pnode->data = data;
  pnode->ppre = NULL;
  pnode->pnext = NULL;
  if (is_empty_doulink(pdlink))
    {
      pdlink->phead = pnode;
    }
  else
    {
      pnode->pnext = pdlink->phead;
      pdlink->phead->ppre = pnode;
      pdlink->phead = pnode;
    }
  pdlink->clen++;
}

尾插

cpp 复制代码
int insert_doulink_tail(DLink_t *pdlink, Data_type_t data)
{
  DNode_t *pnode = malloc(sizeof(DNode_t));
  if (NULL == pnode)
    {
      printf("malloc error");
      return -1;
    }
  pnode->data = data;
  pnode->pnext = NULL;
  pnode->ppre = NULL;
  if (pdlink->phead == NULL)
    {
      pdlink->phead = pnode;
    }
  else
    {
      DNode_t *ptemp = pdlink->phead;
      while (ptemp->pnext != NULL)
        {
          ptemp = ptemp->pnext;
        }
      ptemp->pnext = pnode;
      pnode->ppre = ptemp;
      pnode->pnext = NULL;
      pdlink->clen++;
    }
}

头删

cpp 复制代码
int delete_doulink_head(DLink_t *pdlink)
{
  if (pdlink->phead == NULL)
    {
      return -1;
    }
  else if (pdlink->phead->pnext == NULL)
    {
      DNode_t *ptemp = pdlink->phead;
      pdlink->phead = NULL;
      free(ptemp);
    }
  else
    {
      DNode_t *ptemp = pdlink->phead;
      pdlink->phead = ptemp->pnext;
      ptemp->pnext->ppre = NULL;
      free(ptemp);
      pdlink->clen--;
    }
}

尾删

cpp 复制代码
int delete_doulink_tail(DLink_t *pdlink)
{
  if (pdlink->phead == NULL)
    {
      return -1;
    }
  else if (pdlink->phead->pnext == NULL)
    {
      DNode_t *ptemp = pdlink->phead;
      pdlink->phead = NULL;
      free(ptemp);
      pdlink->clen--;
    }
  else
    {
      DNode_t *ptemp = pdlink->phead;
      while (ptemp->pnext != NULL)
        {
          ptemp = ptemp->pnext;
        }
      ptemp->ppre->pnext = NULL;
      free(ptemp);
      pdlink->clen--;
    }
}

查找指定节点

cpp 复制代码
DNode_t *find_doulink(DLink_t *pdlink, char *name)
{
    DNode_t *ptmp = pdlink->phead;
    while (ptmp != NULL)
    {
        if (0 == strcmp(ptmp->data.name, name))
        {
            return ptmp;
        }
        ptmp = ptmp->pnext;
    }
    return NULL;
}

修改

cpp 复制代码
int change_doulink(DLink_t *pdlink, char *name, int score)
{
    DNode_t *ptmp = find_doulink(pdlink, name);
    if (NULL == ptmp)
    {
        return -1;
    }
    ptmp->data.score = score;
    return 0;
}

删除指定结点

cpp 复制代码
int delete_point_node(DLink_t *pdlink, char *name)
{
    DNode_t* pnode = find_doulink(pdlink, name);
    if (NULL == pnode)
    {
        return -1;
    }

    if (pnode == pdlink->phead)
    {
        delete_doulink_head(pdlink);
    }
    else if (NULL == pnode->pnext)
    {
        delete_doulink_tail(pdlink);
    }
    else
    {
        pnode->ppre->pnext = pnode->pnext;
        pnode->pnext->ppre = pnode->ppre;
        free(pnode);
        pdlink->clen--;
    }

    return 0;

}

销毁

cpp 复制代码
void destory_doulink(DLink_t *pdlink)
{
  DNode_t *ptemp = pdlink->phead;
  if (ptemp == NULL)
    {
      free(pdlink);
    }
  else
    {
      while (ptemp != NULL)
        {
          ptemp = ptemp->pnext;
          delete_doulink_head(pdlink);
        }
      free(pdlink);
    }
  printf("Destory pdlink\n");
}
void destroy_doulink(DLink_t **ppdlink)
{
    while (!is_empty_doulink(*ppdlink))
    {
        delete_doulink_head(*ppdlink);
    }
    free(*ppdlink);
    *ppdlink = NULL;
}

内核链表

无数据域,只有指针域,双向循环链表,不再将数据存储到链表节点中,而是将节点嵌入到存储的数据中。

offset-of:获取内核链表中链表结点到结构体起始位置的偏移量。

container-of:通过偏移量获取结构体首地址(节点首地址-偏移量)。

相关推荐
FreakStudio13 小时前
W55MH32L-EVB 上手测评:硬件 TCP/IP 加持的以太网单片机,MicroPython 零门槛开发
python·单片机·嵌入式·大学生·面向对象·并行计算·电子diy·电子计算机
AlfredZhao14 小时前
Docker 容器时区不对,`timedatectl` 不存在怎么办?
linux·timezone
zzzzzz3102 天前
9K Star 炸裂开源!这个 C 语言写的代码知识图谱,把 Linux 内核索引压缩到了 3 分钟
linux·服务器·sql
XIAOHEZIcode2 天前
Linux系统鼠标偏移常见原因以及修复方案
linux·运维·游戏
A小辣椒4 天前
TShark:Wireshark CLI 功能
linux
A小辣椒4 天前
TShark:基础知识
linux
AlfredZhao4 天前
OCI 明明分配了 200G 系统盘,为什么 df 只看到 30G?
linux·oci
AlfredZhao5 天前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
Darling噜啦啦5 天前
列表转树算法深度解析:从 Map 到 Reduce 的两种实现,面试高频考点
数据结构·算法·面试
用户9718356334665 天前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux