数据结构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);
}