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

目录

双向链表

头文件

创建

遍历

头插

尾插

头删

尾删

查找指定节点

修改

删除指定结点

销毁

内核链表


双向链表

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

头文件

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:通过偏移量获取结构体首地址(节点首地址-偏移量)。

相关推荐
chlk1231 天前
Linux文件权限完全图解:读懂 ls -l 和 chmod 755 背后的秘密
linux·操作系统
舒一笑1 天前
Ubuntu系统安装CodeX出现问题
linux·后端
改一下配置文件1 天前
Ubuntu24.04安装NVIDIA驱动完整指南(含Secure Boot解决方案)
linux
深紫色的三北六号2 天前
Linux 服务器磁盘扩容与目录迁移:rsync + bind mount 实现服务无感迁移(无需修改配置)
linux·扩容·服务迁移
SudosuBash2 天前
[CS:APP 3e] 关于对 第 12 章 读/写者的一点思考和题解 (作业 12.19,12.20,12.21)
linux·并发·操作系统(os)
哈基咪怎么可能是AI2 天前
为什么我就想要「线性历史 + Signed Commits」GitHub 却把我当猴耍 🤬🎙️
linux·github
十日十行3 天前
Linux和window共享文件夹
linux
木心月转码ing3 天前
WSL+Cpp开发环境配置
linux
崔小汤呀4 天前
最全的docker安装笔记,包含CentOS和Ubuntu
linux·后端
何中应4 天前
vi编辑器使用
linux·后端·操作系统