1.双向链表
1.空链表的创建
参考单向链表
cslinknode *creat_empty_doulist(void) { linknode *ptmpnode = NULL; ptmpnode = malloc(sizeof(linknode)); if(NULL == ptmpnode) { perror("fail to malloc"); return NULL; } ptmpnode->pnext = NULL; ptmpnode->ppre = NULL; return ptmpnode; }
2.头插法插入节点
参考单向链表
csint insert_head_doulist(linknode *phead, datatype tmpdata) { linknode *ptmpnode = NULL; //申请空间 ptmpnode = malloc(sizeof(linknode)); if(NULL == ptmpnode) { perror("fail to malloc"); return -1; } ptmpnode->data = tmpdata; ptmpnode->pnext = phead->pnext; ptmpnode->ppre = phead; phead->pnext = ptmpnode; if(ptmpnode->pnext != NULL) { ptmpnode->pnext->ppre == ptmpnode; } return 0; }
3.链表的遍历
参考单向链表
csint show_doulist(linknode *phead) { linknode *ptmpnode = NULL; ptmpnode = phead->pnext; while(ptmpnode != NULL) { printf("%d ", ptmpnode->data); ptmpnode = ptmpnode->pnext; } printf("\n"); return 0; }
4.链表的查询
参考单向链表
cslinknode *find_doulist(linknode *phead, datatype tmpdata) { linknode *ptmpnode = NULL; ptmpnode = phead->pnext; while(ptmpnode->data != tmpdata) { if(ptmpnode == NULL || ptmpnode->pnext == NULL) { return NULL; } ptmpnode = ptmpnode->pnext; } return ptmpnode; }
5.链表的修改
csint update_doulist(linknode *phead, datatype olddata, datatype newdata) { linknode *ptmpnode = NULL; ptmpnode = phead->pnext; while(ptmpnode->data != olddata) { if(ptmpnode == NULL || ptmpnode->pnext == NULL) { return 0; } ptmpnode = ptmpnode->pnext; } ptmpnode->data = newdata; return 0; }
6.链表的删除
- 找到要删除的节点
- 让删除的节点的前一个节点的pnext等于要删除节点的后一个节点的地址
- 让删除的节点的后一个节点的ppre等于要删除节点的前一个节点的地址
- 释放删除的节点
csint delete_doulist(linknode *phead, datatype tmpdata) { linknode *ptmpnode = NULL; linknode *pfreenode = NULL; ptmpnode = phead->pnext; while(ptmpnode != NULL) { if(ptmpnode->data == tmpdata) { ptmpnode->ppre->pnext = ptmpnode->pnext; if(ptmpnode->pnext != NULL) { ptmpnode->pnext->ppre = ptmpnode->ppre; } pfreenode = ptmpnode; ptmpnode = ptmpnode->pnext; free(pfreenode); } else { ptmpnode = ptmpnode->pnext; } } return 0; }
7.链表的销毁
csint destroy_doulist(linknode **pphead) { linknode *ptmpnode = NULL; linknode *pfreenode = NULL; ptmpnode = *pphead; pfreenode = *pphead; while(pfreenode != NULL) { ptmpnode = ptmpnode->pnext; free(pfreenode); pfreenode = ptmpnode; } *pphead = NULL; return 0; }
8.链表的尾插法
csint insert_last_doulist(linknode *phead, datatype tmpdata) { linknode *ptmpnode = NULL; linknode *pinsertnode = NULL; pinsertnode = malloc(sizeof(linknode)); if(pinsertnode == NULL) { perror("fail to malloc"); return -1; } ptmpnode = phead->pnext; while(ptmpnode->pnext != NULL) { ptmpnode = ptmpnode->pnext; } pinsertnode->ppre = ptmpnode; pinsertnode->data = tmpdata; pinsertnode->pnext = NULL; ptmpnode->pnext = pinsertnode; return 0; }
2.循环链表
1.特点
- 头节点的ppre指向链表的最后一个节点
- 最后节点的pnext指向链表的第一个节点
2.节点定义与双向链表保持一致
cstypedef int datatype; typedef struct node { datatype data; struct node *ppre; struct node *pnext; }linknode;
3.链表创建
cslinknode *creat_cirlist(void) { linknode *ptmpnode = NULL; ptmpnode = malloc(sizeof(linknode)); if(ptmpnode == NULL) { perror("fail to malloc"); return NULL; } ptmpnode->pnext = ptmpnode; ptmpnode->ppre = ptmpnode; return ptmpnode; }
4.链表的头插法
- 申请空间
- 存放数据
- 将pnext赋值为空白节点的pnext
- 将ppre指向前面的节点
- 将前面的节点的pnext指向新申请的节点
- 将空白节点的ppre指向新申请的节点
csint insert_head_cirlist(linknode *phead, datatype tmpdata) { linknode *ptmpnode = NULL; ptmpnode = malloc(sizeof(linknode)); if(ptmpnode == NULL) { perror("fail to malloc"); return -1; } ptmpnode->data = tmpdata; ptmpnode->pnext = phead->pnext; ptmpnode->ppre = phead; ptmpnode->ppre->pnext = ptmpnode; ptmpnode->pnext->ppre = ptmpnode; return 0; }
5.链表的尾插法
csint insert_tail_cirlist(linknode *phead, datatype tmpdata) { linknode *ptmpnode = NULL; ptmpnode = malloc(sizeof(linknode)); if(ptmpnode == NULL) { perror("fail to malloc"); return -1; } ptmpnode->data = tmpdata; ptmpnode->pnext = phead; ptmpnode->ppre = phead->ppre; ptmpnode->ppre->pnext = ptmpnode; ptmpnode->pnext->ppre = ptmpnode; return 0; }
6.链表的遍历
csint show_cirlist(linknode *phead) { linknode *ptmpnode = NULL; ptmpnode = phead->pnext; while(ptmpnode != phead) { printf("%d ",ptmpnode->data); ptmpnode = ptmpnode->pnext; } printf("\n"); return 0; }
7.链表的查找
cslinknode *find_cirlist(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.链表的修改
csint update_cirlist(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.链表的删除
csint delete_tmpdata_cirlist(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.链表的销毁
csint destroy_cirlist(linknode **pphead) { linknode *ptmpnode = NULL; linknode *pfreenode = NULL; ptmpnode = (*pphead)->pnext; pfreenode = (*pphead)->pnext; while(ptmpnode != *pphead) { ptmpnode = ptmpnode->pnext; free(pfreenode); pfreenode = ptmpnode; } free(*pphead); *pphead = NULL; return 0; }
3.内核链表
1.概念
- Linux内核中所使用的一种链表结构
- 使用同一种结构可以存放不同类型的链表
- 普通链表:链表节点中包含数据
- 内核链表:数据中包含链表节点
2.结构
- 创建:创建空白节点即可
- 插入:申请节点,按照学习的循环链表插入即可(插入链表节点的首地址即数据节点首地址)
- 访问节点:通过遍历找到每个节点的首地址,强制类型转换即可获得对应数据空间首地址