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

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

2.双向链表的特点

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

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

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

3.双向链表的优点

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

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

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

4。双向链表的缺点

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

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

双向链表的创建与插入

cs 复制代码
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;
}

双向链表的查找和修改

cs 复制代码
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;
        }
    }
}

双向链表的删除和销毁

cs 复制代码
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. 稳定性:内核链表的实现需要非常稳定可靠,任何错误都可能导致系统崩溃或其他严重后果。

内科链表的创建和插入

cs 复制代码
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;
}

内核链表的删除和销毁

cs 复制代码
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);
}
相关推荐
CSharp精选营3 天前
关系型 vs 非关系型:从原理到选型,一文搞定数据库核心分类
数据结构·nosql·关系型数据库·非关系型数据库·技术选型
刘马想放假7 天前
Modbus 全栈技术解析:TCP、RTU、ASCII、RTU over TCP
数据结构·网络协议
北域码匠8 天前
冒泡排序太慢?鸡尾酒排序双向优化,原生 C# 零第三方库完整代码
数据结构·排序算法·泛型·c# 算法·鸡尾酒排序·原生 c# 开发·冒泡排序优化·嵌入式算法
Darling噜啦啦14 天前
列表转树算法深度解析:从 Map 到 Reduce 的两种实现,面试高频考点
数据结构·算法·面试
小小工匠15 天前
Redis - 事务机制:能实现 ACID 属性吗
数据结构·redis·性能优化·并发·持久化
玖玥拾15 天前
C/C++ 数据结构(七)栈、容器适配器
c语言·数据结构·c++··容器适配器
Qres82115 天前
算法复键——树状数组
数据结构·算法
牛油果子哥q16 天前
并查集(DSU)超精讲,路径压缩、按秩合并、万能模板、连通性判定、最小生成树与刷题实战全解
数据结构·c++·最小生成树·并查集
凌波粒16 天前
LeetCode--491.递增子序列(回溯算法)
数据结构·算法·leetcode
疯狂成瘾者16 天前
Java 集合 LinkedList 详解:链表结构、常用方法和队列使用
java·开发语言·链表