day18练习:
循环链表
1.特点:
头结点的ppre指向链表的最后一个节点
最后节点的pnex指向链表的第一个节点
2.节点定义:
与双向链表保持一致
3.链表创建
linknode *create_empty_linklist(void)
{
linknode *ptmpnode = NULL;
ptmpnode = malloc(sizeof(linknode));
if (NULL == ptmpnode)
{
printf("fail to malloc");
return NULL;
}
ptmpnode->pnext = ptmpnode->ppre = ptmpnode;
return ptmpnode;
}
申请节点
pnex和ppre都指向自己
4.链表头插法
int insert_head_linklist(linknode *phead, datatype tmpdata)
{
linknode *ptmpnode = NULL;
ptmpnode = malloc(sizeof(linknode));
if (NULL == ptmpnode)
{
printf("fail to malloc");
return -1;
}
ptmpnode->data = tmpdata;
ptmpnode->pnext = phead->pnext;
ptmpnode->ppre = phead;
phead->pnext = ptmpnode;
ptmpnode->pnext->ppre = ptmpnode;
return 0;
}
申请节点空间
存放数据
将pnext指向空白节点的pnext
将ppre指向空白节点
将空白节点的pnext指向新申请节点
将后续节点的ppre指向新申请节点
5.链表尾差法
int insert_tail_linklist(linknode *phead, datatype tmpdata)
{
linknode *ptmpnode = NULL;
ptmpnode = malloc(sizeof(linknode));
if (NULL == ptmpnode)
{
printf("fail to malloc");
return -1;
}
ptmpnode->data = tmpdata;
ptmpnode->pnext = phead;
ptmpnode->ppre = phead->ppre;
phead->ppre->pnext = ptmpnode;
phead->ppre = ptmpnode;
return 0;
}
申请节点空间
存放数据
将pnext赋值为空白节点
将ppre赋值为之前的最后一个节点地址
将之前最后一个节点的pnext指向新申请节点
将空白节点的ppre指向新申请节点
6.链表节点遍历
int show_linklist(linknode *phead)
{
linknode *ptmpnode = NULL;
ptmpnode = phead->pnext;
while (ptmpnode != phead)
{
printf("%d ", ptmpnode->data);
ptmpnode = ptmpnode->pnext;
}
printf("\n");
return 0;
}
7.链表查找
linknode *find_linklist(linknode *phead, datatype tmpdata)
{
linknode *ptmpnode = NULL;
ptmpnode = phead->pnext;
while (ptmpnode != phead)
{
if (ptmpnode->data == tmpdata)
{
return ptmpnode;
}
ptmpnode = ptmpnode->pnext;
}
return NULL;
}
8.链表的修改
int update_linklist(linknode *phead, datatype olddata, datatype newdata)
{
linknode *ptmpnode = NULL;
ptmpnode = phead->pnext;
while (ptmpnode != phead)
{
if (ptmpnode->data == olddata)
{
ptmpnode->data = newdata;
}
ptmpnode = ptmpnode->pnext;
}
return 0;
}
9.链表的删除
int delete_linklist(linknode *phead, datatype tmpdata)
{
linknode *ptmpnode = NULL;
linknode *pfreenode = NULL;
ptmpnode = phead->pnext;
while (ptmpnode != phead)
{
if (ptmpnode->data == tmpdata)
{
ptmpnode->ppre->pnext = ptmpnode->pnext;
ptmpnode->pnext->ppre = ptmpnode->ppre;
pfreenode = ptmpnode;
ptmpnode = ptmpnode->pnext;
free(pfreenode);
}
else
{
ptmpnode = ptmpnode->pnext;
}
}
return 0;
}
10.链表的销毁
int destroy_linklist(linknode **pphead)
{
linknode *ptmpnode = NULL;
linknode *pfreenode = NULL;
ptmpnode = (*pphead)->pnext;
pfreenode = ptmpnode;
while (ptmpnode != *pphead)
{
ptmpnode = ptmpnode->pnext;
free(pfreenode);
pfreenode = ptmpnode;
}
free(*pphead);
*pphead = NULL;
return 0;
}
内核链表
1.概念:
- linux内核中所使用到的一种链表结构
- 使用同一种结构可以存储不同类型的链表
- 普通链表:链表节点中包含数据
- 内核链表:数据中包含链表节点
2.结构描述:
- 创建:创建空白节点即可
- 插入:申请节点,并按照之前学习的循环链表插入即可(插入的链表节点首地址即数据节点首地址)
- 访问节点:通过遍历找到每个节点的首地址,通过强制类型转换即可获得对应数据空间首地址