Linux学习-数据结构(链表)
1.双向链表
1.空链表的创建
参考单向链表
linknode *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.头插法插入节点
参考单向链表
int 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.链表的遍历
参考单向链表
int 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.链表的查询
参考单向链表
linknode *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.链表的修改
int 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等于要删除节点的前一个节点的地址
- 释放删除的节点
int 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.链表的销毁
int 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.链表的尾插法
int 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.节点定义
与双向链表保持一致
typedef int datatype;typedef struct node {datatype data;struct node *ppre;struct node *pnext; }linknode;
3.链表创建
linknode *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指向新申请的节点
int 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.链表的尾插法
int 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.链表的遍历
int 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.链表的查找
linknode *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.链表的修改
int 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.链表的删除
int 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.链表的销毁
int 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.结构
- 创建:创建空白节点即可
- 插入:申请节点,按照学习的循环链表插入即可(插入链表节点的首地址即数据节点首地址)
- 访问节点:通过遍历找到每个节点的首地址,强制类型转换即可获得对应数据空间首地址