当前位置: 首页 > article >正文

数据结构2 :双向链表和内核链表

1.双向链表是一种链表数据结构,其中每个节点包含三个部分:一个数据域(存储节点的数据)、一个前驱指针(指向列表中的前一个节点)和一个后继指针(指向列表中的下一个节点)。这种结构使得遍历和修改链表变得非常灵活,因为它可以从任意一个节点开始向前或向后遍历。

2.双向链表的特点

     1. 双向遍历:可以从头节点遍历到尾节点,也可以从尾节点遍历到头节点。

     2. 方便插入和删除:在双向链表中插入或删除一个节点只需要修改相邻节点的前后指针,而不需要遍历整个链表来查找前驱或后继节点。

     3. 额外的空间开销:每个节点需要额外存储两个指针,因此相对于单向链表,双向链表占用更多内存。

3.双向链表的优点

灵活性:可以在任意位置插入或删除节点,而无需重新排列整个链表。

双向遍历:可以从头到尾或从尾到头遍历链表,提供了更高的灵活性。

方便实现复杂操作:如反转链表、合并链表等操作变得更加简单。

4。双向链表的缺点

   额外的空间开销:每个节点需要额外存储两个指针,增加了内存消耗。

  稍微复杂的操作:相对于单向链表,双向链表的操作逻辑稍微复杂一些,需要同时更新前后指针。

双向链表的创建与插入

Dlink_t *create_doulink()
{
    Dlink_t *pdlink = malloc(sizeof(Dlink_t));
    if(NULL == pdlink)
    {
        perror("malloc fail");
        return NULL;
    }
    pdlink->phead = NULL;
    pdlink->clen = 0;
    pthread_mutex_init(&(pdlink->mutex),NULL);
    return pdlink;
}
int is_empty_doulink(Dlink_t *pdlink)
{
    return NULL == pdlink->phead;
}
int push_doulink_head(Dlink_t *pdlink,DATATYPE data)
{
    DLink_Node_t *pnode = malloc(sizeof(DLink_Node_t));
    if(NULL == pnode)
    {
        perror("malloc fail");
        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++;
    return 0;
}

双向链表的查找和修改

DLink_Node_t *find_doulink(Dlink_t *pdlink,char *name)
{
    if(is_empty_doulink(pdlink))
    {
        return NULL;
    }
    else
    {
        DLink_Node_t *p = pdlink->phead;
        while(p != NULL)
        {
            if(strcmp(p->data.name,name) == 0)
            {
                return p;
            }
            p = p->pnext;
        }
    }
    return NULL;
}
DLink_Node_t *change_doulink(Dlink_t *pdlink,char *oldname,int newscore)
{
    if(is_empty_doulink(pdlink))
    {
        return NULL;
    }
    else
    {
        DLink_Node_t *p = find_doulink(pdlink,oldname);
        if(p != NULL)
        {
            p->data.score = newscore;
            return p;
        }
    }
}

双向链表的删除和销毁

int pop_doulink_head(Dlink_t *pdlink)
{
    DLink_Node_t *p = pdlink->phead;
    if(is_empty_doulink(pdlink))
    {
        return 0;
    }
    if(1 == pdlink->clen)
    {
        free(p);
        pdlink->phead = NULL;
    }
    else
    {
        pdlink->phead = p->pnext;
        p->pnext->ppre = NULL;
        free(p);
    }
    pdlink->clen--;
    return 0;
}
void destroy_doulink(Dlink_t *pdlink)
{
    while(!is_empty_doulink(pdlink))
    {
        pop_doulink_head(pdlink);
    }
    free(pdlink);
}

2.内核链表

 内核链表通常指的是在操作系统内核中使用的链表结构。内核链表是操作系统内核用来管理和组织内核数据结构的一种重要工具。

内核链表的特点

1. 并发安全性:内核链表需要在多处理器或多线程环境中安全地进行并发访问,通常需要使用原子操作或锁机制来保证数据的一致性。

2. 内存管理:内核链表的节点需要从内核的内存池中分配和回收,因此需要考虑内存碎片和内存使用效率等问题。

3. 高性能:内核链表需要在低级别的系统操作中提供高性能的支持,如进程调度、设备驱动等。

4. 稳定性:内核链表的实现需要非常稳定可靠,任何错误都可能导致系统崩溃或其他严重后果。

内科链表的创建和插入

KLink_t *create_klink()
{
    KLink_t *pklink = malloc(sizeof(KLink_t));
    if(NULL == pklink)
    {
        perror("malloc fail");
        return NULL;
    }
    pklink->phead = NULL;
    pklink->clen = 0;
    pthread_mutex_init(&(pklink->mutex),NULL);
    return pklink;
}
int push_klink_head(KLink_t *pklink,void*p)
{
    KNode_t *pnode = (KNode_t *)p;
    pnode->ppre = NULL;
    pnode->pnext = NULL;
    pnode->pnext = pklink->phead;
    if(pklink->phead != NULL)
    {
        pklink->phead->ppre = pnode;
    }
    pklink->phead = pnode;
    pklink->clen++;
    return 0;
}

内核链表的删除和销毁

int pop_klink_head(KLink_t *pklink)
{
    if(is_empty_klink(pklink))
    {
        return 0;
    }
    KNode_t *pnode = pklink->phead;
    if(plink->phead->pnext == NULL)
    {
        pklink->phead = NULL;
        free(pnode);
    }
    else
    {
        pklink->phead = pnode->pnext;
        pklink->phead->ppre = NULL;
        free(pnode);
    }
    pklink->clen--;
    return 1;
}
void destroy_klink(KLink_t *pklink)
{
    while(!is_empty_klink(pklink))
    {
        pop_klink_head(pklink);
    }
    free(pklink);
}


http://www.kler.cn/a/302499.html

相关文章:

  • 解决failed to execute PosixPath(‘dot‘) 或者GraphViz‘s executables not found
  • 用 Python 从零开始创建神经网络(三):添加层级(Adding Layers)
  • 【代码审计】常见漏洞专项审计-业务逻辑漏洞审计
  • Wordpress常用配置,包括看板娘跨域等
  • Elasticsearch集群和Kibana部署流程
  • FFmpeg 4.3 音视频-多路H265监控录放C++开发十三.2:avpacket中包含多个 NALU如何解析头部分析
  • mysql可重复读不能解决幻读吗?
  • linux————根据端口查找运行目录的三种方法
  • STM32内部闪存FLASH(内部ROM)、IAP
  • 信息安全工程师题
  • ASR(自动语音识别)识别文本效果的打分总结
  • 用Cri-O,Sealos CLI,Kubeadm方式部署K8s高可用集群
  • 【docker】了解什么是Docker
  • 欧洲麻花钻市场主要企业市场占有率及排名
  • Framework | 在Android中运行时获取顶层Activity并处理业务逻辑
  • 【测试】——自动化测试入门(Selenium环境搭建)
  • Golang | Leetcode Golang题解之第395题至少有K个重复字符的最长子串
  • IPC$漏洞多位密码爆破方法
  • 揭开Facebook AI的神秘面纱:如何利用人工智能提升社交体验
  • Java笔试面试题AI答之单元测试JUnit(4)
  • 亚信安全出席第五届国际反病毒大会 探究AI现代网络勒索治理
  • SprinBoot+Vue爱老助老服务平台的设计与实现
  • JAVAEE初阶第六节——网络编程套接字
  • 通信工程学习:什么是SLF签约数据定位功能
  • 携手科大讯飞丨云衔科技为企业提供全栈AI技术解决方案
  • yolov8学习笔记