目录
双向链表
与单向链表相比,双向链表多增加一个指针域,指向前一个结点。

头文件
cpp
#ifndef __DOULINK_H__
#define __DOULINK_H__
//双向链表存储的数据类型
typedef struct stu
{
int id;
char name[32];
int score;
}Data_type_t;
/*双向链表的结点类型*/
typedef struct dounode
{
Data_type_t data;
struct dounode *ppre; //指向前驱结点的指针
struct dounode *pnext; //指向后继结点的指针
}DNode_t;
/*双向链表对象类型*/
typedef struct doulink
{
DNode_t *phead; //双向链表头结点地址
int clen; //双向链表结点个数
}DLink_t;
extern DLink_t *create_doulink();
extern int insert_doulink_head(DLink_t *pdlink, Data_type_t data);
extern int is_empty_doulink(DLink_t *pdlink);
extern void doulink_for_each(DLink_t *pdlink, int dir);
extern int insert_doulink_tail(DLink_t *pdlink, Data_type_t data);
extern int delete_doulink_head(DLink_t *pdlink);
extern int delete_doulink_tail(DLink_t *pdlink);
extern DNode_t *find_doulink(DLink_t *pdlink, char *name);
extern int change_doulink(DLink_t *pdlink, char *name, int score);
extern int delete_point_node(DLink_t *pdlink, char *name);
extern void destroy_doulink(DLink_t **ppdlink);
#endif
创建
cpp
DLink_t *create_doulink()
{
DLink_t *pdlink = malloc(sizeof(DLink_t));
if (NULL == pdlink)
{
printf("malloc error");
return NULL;
}
pdlink->phead = NULL;
pdlink->clen = 0;
return pdlink;
}
遍历
cpp
void doulink_for_each(DLink_t *pdlink, int dir)
{
if (is_empty_doulink(pdlink))
{
return;
}
DNode_t *ptemp = NULL;
ptemp = pdlink->phead;
if (dir)
{
while (ptemp != NULL)
{
printf("%d,%s,%d\n", ptemp->data.id, ptemp->data.name,
ptemp->data.score);
ptemp = ptemp->pnext;
}
}
else
{
while (ptemp->pnext != NULL)
{
ptemp = ptemp->pnext;
}
while (ptemp != NULL)
{
printf("%d,%s,%d\n", ptemp->data.id, ptemp->data.name,
ptemp->data.score);
ptemp = ptemp->ppre;
}
}
printf("\n");
}
头插
cpp
int insert_doulink_head(DLink_t *pdlink, Data_type_t data)
{
DNode_t *pnode = malloc(sizeof(DNode_t));
if (NULL == pnode)
{
printf("malloc error");
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++;
}
尾插
cpp
int insert_doulink_tail(DLink_t *pdlink, Data_type_t data)
{
DNode_t *pnode = malloc(sizeof(DNode_t));
if (NULL == pnode)
{
printf("malloc error");
return -1;
}
pnode->data = data;
pnode->pnext = NULL;
pnode->ppre = NULL;
if (pdlink->phead == NULL)
{
pdlink->phead = pnode;
}
else
{
DNode_t *ptemp = pdlink->phead;
while (ptemp->pnext != NULL)
{
ptemp = ptemp->pnext;
}
ptemp->pnext = pnode;
pnode->ppre = ptemp;
pnode->pnext = NULL;
pdlink->clen++;
}
}
头删
cpp
int delete_doulink_head(DLink_t *pdlink)
{
if (pdlink->phead == NULL)
{
return -1;
}
else if (pdlink->phead->pnext == NULL)
{
DNode_t *ptemp = pdlink->phead;
pdlink->phead = NULL;
free(ptemp);
}
else
{
DNode_t *ptemp = pdlink->phead;
pdlink->phead = ptemp->pnext;
ptemp->pnext->ppre = NULL;
free(ptemp);
pdlink->clen--;
}
}
尾删
cpp
int delete_doulink_tail(DLink_t *pdlink)
{
if (pdlink->phead == NULL)
{
return -1;
}
else if (pdlink->phead->pnext == NULL)
{
DNode_t *ptemp = pdlink->phead;
pdlink->phead = NULL;
free(ptemp);
pdlink->clen--;
}
else
{
DNode_t *ptemp = pdlink->phead;
while (ptemp->pnext != NULL)
{
ptemp = ptemp->pnext;
}
ptemp->ppre->pnext = NULL;
free(ptemp);
pdlink->clen--;
}
}
查找指定节点
cpp
DNode_t *find_doulink(DLink_t *pdlink, char *name)
{
DNode_t *ptmp = pdlink->phead;
while (ptmp != NULL)
{
if (0 == strcmp(ptmp->data.name, name))
{
return ptmp;
}
ptmp = ptmp->pnext;
}
return NULL;
}
修改
cpp
int change_doulink(DLink_t *pdlink, char *name, int score)
{
DNode_t *ptmp = find_doulink(pdlink, name);
if (NULL == ptmp)
{
return -1;
}
ptmp->data.score = score;
return 0;
}
删除指定结点
cpp
int delete_point_node(DLink_t *pdlink, char *name)
{
DNode_t* pnode = find_doulink(pdlink, name);
if (NULL == pnode)
{
return -1;
}
if (pnode == pdlink->phead)
{
delete_doulink_head(pdlink);
}
else if (NULL == pnode->pnext)
{
delete_doulink_tail(pdlink);
}
else
{
pnode->ppre->pnext = pnode->pnext;
pnode->pnext->ppre = pnode->ppre;
free(pnode);
pdlink->clen--;
}
return 0;
}
销毁
cpp
void destory_doulink(DLink_t *pdlink)
{
DNode_t *ptemp = pdlink->phead;
if (ptemp == NULL)
{
free(pdlink);
}
else
{
while (ptemp != NULL)
{
ptemp = ptemp->pnext;
delete_doulink_head(pdlink);
}
free(pdlink);
}
printf("Destory pdlink\n");
}
void destroy_doulink(DLink_t **ppdlink)
{
while (!is_empty_doulink(*ppdlink))
{
delete_doulink_head(*ppdlink);
}
free(*ppdlink);
*ppdlink = NULL;
}
内核链表
无数据域,只有指针域,双向循环链表,不再将数据存储到链表节点中,而是将节点嵌入到存储的数据中。

offset-of:获取内核链表中链表结点到结构体起始位置的偏移量。
container-of:通过偏移量获取结构体首地址(节点首地址-偏移量)。
