数据结构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);
}
相关推荐
程序员清风1 小时前
排序算法:从冒泡排序到归并排序
数据结构·算法·排序算法
Ada's11 小时前
【计算机基础系列】003:Python数据结构
开发语言·数据结构·python
wanderist.14 小时前
线性筛法详解:从筛质数到欧拉函数、Möbius 函数与约数函数
java·数据结构·算法
All for pursuit.14 小时前
【设计-1】208.实现Trie (前缀树)
数据结构·c++·算法·leetcode
程序员清风16 小时前
哈希表:从键值映射到高效查找
数据结构·哈希算法·散列表
Logic10119 小时前
C语言/数据结构字符串题解:最短循环节——找出能重复构成原串的最短基础子串
c语言·数据结构·字符串·枚举·时间复杂度·算法题·kmp优化
垆边人似月.20 小时前
城市连通性(200分 / 并查集)
数据结构·算法·图论
Gust of wind20 小时前
串与KMP模式匹配:存储结构、基本操作、next数组手算
c语言·数据结构·后端·算法
by2099920 小时前
list:迭代器与资源管理实现的综合叙述(下)
数据结构·c++·笔记·list
我不会起名字32221 小时前
二叉树的遍历与二叉搜索树:把递归、迭代、还原树一次讲透
数据结构·leetcode·二叉树·二叉搜索树