【五】双向链表
来源:互联网 发布:芗里芗亲app软件下载 编辑:程序博客网 时间:2024/05/22 14:58
1、双向链表的定义
在单链表的结点中增加一个指向其前驱的p r e指针!
2、数据结构的定义
//dlinklist.h/* 对外做数据封装,屏蔽线性表的实现*/typedef void DLinklist;typedef struct _struct_linklistNode DLinklistNode;struct _struct_linklistNode{ DLinklistNode *pre; DLinklistNode *next;};
//dlinklist.c//内部头结点的真实定义typedef struct _struct_dlinklist{ DLinklistNode header; //游标成员 DLinklistNode *silder; int length;}TDLinklist;
//main.c//被插入元素的定义typedef struct _struct_value{ DLinklistNode node; int v;}Value;
3、创建操作
/*该方法用于创建并且返回一个空的线性表*/DLinklist* List_Create(){ TDLinklist *tlist = NULL; tlist = (TDLinklist*)malloc(sizeof(TDLinklist)); if(tlist != NULL) { tlist->header.pre = NULL; tlist->header.next = NULL; tlist->silder = NULL; tlist->length = 0; } return tlist;}
4、插入操作
示意图:
/*该方法用于向一个线性表list的pos位置处插入新元素node返回值为1表示插入成功,0表示插入失败*/int List_Insert(DLinklist* list, DLinklistNode* node, int pos){ int iret = 1; TDLinklist *tlist = (TDLinklist*)list; iret = iret && (tlist != NULL) && (node != NULL) && (pos >= 0); if(iret) { DLinklistNode *current = (DLinklistNode*)tlist; DLinklistNode *next = NULL; for(int i = 0; (i<pos) && (current->next != NULL); i++) { current = current->next; } next = current->next; current->next = node; node->next = next; if(next != NULL) { next->pre = node; } node->pre = current; if(tlist->length == 0) { //如果插入的是第一个元素,则默认让游标指向它 //游标默认指向第一个插入的元素 tlist->silder = tlist->header.next; } //如果插入的位置是第一个元素,则修正新的第一个元素的pre指针 if(current == (DLinklistNode*)tlist) { //让第一个元素的pre指向NULL node->pre = NULL; //添加如下的代码,可让游标始终指向链表的第一个元素 //tlist->silder = tlist->header.next; } tlist->length++; } return iret;}
5、删除操作
示意图:
/*该方法用于删除一个线性表list的pos位置处的元素返回值为被删除的元素,NULL表示删除失败*/DLinklistNode* List_Delete(DLinklist* list, int pos){ DLinklistNode *ret = NULL; TDLinklist *tlist = (TDLinklist*)list; if(tlist != NULL) { //要保证被删除的元素存在, && (tlist->length > 0) if((pos >= 0)&&(pos < tlist->length)) { DLinklistNode *current = (DLinklistNode*)tlist; DLinklistNode *next = NULL; for(int i = 0;i<pos;i++) { current = current->next; } ret = current->next; next = ret->next; current->next = ret->next; if(next != NULL) { next->pre = current; //以下条件等价于:current == (DLinklistNode*)tlist if(pos == 0) { next->pre = NULL; } } //如果游标当前指向了要删除的元素,则让游标指向它的下一个元素 if(ret == tlist->silder) { tlist->silder = ret->next; } ret->pre = NULL; ret->next = NULL; tlist->length--; } } return ret;}
6、增加游标后的新操作
- 获取当前游标指向的数据元素
- 将游标重置指向链表中的第一个数据元素
- 将游标移动指向到链表中的下一个数据元素
- 将游标移动指向到链表中的上一个数据元素
- 直接指定删除链表中的某个数据元素
相关定义:
/* 删除指定结点 如果成功,返回被删除的结点,否则返回NULL*/DLinklistNode* List_DeleteNode(DLinklist *list,DLinklistNode *node);/* 重置游标 如果成功,返回重置后的元素,否则返回NULL*/DLinklistNode* List_Reset(DLinklist *list);/* 获取当前游标指向的元素 如果成功,返回当前游标指向的元素,否则返回NULL*/DLinklistNode* List_Current(DLinklist *list);/* 让游标指向下一个元素 如果成功,返回下一个元素,否则返回NULL 特殊情况:链表最后一个元素的下一个元素也为NULL*/DLinklistNode* List_Next(DLinklist *list);/* 让游标指向前一个元素 如果成功,返回前一个元素,否则返回NULL 特殊情况:链表的第一个元素的前一个元素也为NULL*/DLinklistNode* List_Pre(DLinklist *list);
相关实现:
/* 删除指定结点 如果成功,返回被删除的结点,否则返回NULL*/DLinklistNode* List_DeleteNode(DLinklist *list,DLinklistNode *node){ DLinklistNode *ret = NULL; TDLinklist *tlist = (TDLinklist*)list; if((tlist != NULL) && (node != NULL)) { int i = 0; DLinklistNode *current = (DLinklistNode*)tlist; for(i = 0;i < tlist->length;i++) { current = current->next; if(current == node) { ret = current; break; } } //判断是否找到要删除的元素 if(ret != NULL) { List_Delete(list,i); } } return ret;}/* 重置游标 如果成功,返回重置后的元素,否则返回NULL*/DLinklistNode* List_Reset(DLinklist *list){ DLinklistNode *ret = NULL; TDLinklist *tlist = (TDLinklist*)list; if(tlist != NULL) { tlist->silder = tlist->header.next; ret = tlist->silder; } return ret;}/* 获取当前游标指向的元素 如果成功,返回当前游标指向的元素,否则返回NULL*/DLinklistNode* List_Current(DLinklist *list){ DLinklistNode *ret = NULL; TDLinklist *tlist = (TDLinklist*)list; if(tlist != NULL) { ret = tlist->silder; } return ret;}/* 让游标指向下一个元素 如果成功,返回下一个元素,否则返回NULL 特殊情况:链表最后一个元素的下一个元素也为NULL*/DLinklistNode* List_Next(DLinklist *list){ DLinklistNode *ret = NULL; TDLinklist *tlist = (TDLinklist*)list; if(tlist != NULL) { tlist->silder = tlist->silder->next; ret = tlist->silder; } return ret;}/* 让游标指向前一个元素 如果成功,返回前一个元素,否则返回NULL 特殊情况:链表的第一个元素的前一个元素也为NULL*/DLinklistNode* List_Pre(DLinklist *list){ DLinklistNode *ret = NULL; TDLinklist *tlist = (TDLinklist*)list; if(tlist != NULL) { tlist->silder = tlist->silder->pre; ret = tlist->silder; } return ret;}
7、小结
- 双向链表在单链表的基础上增加了指向前驱的指针
- 功能上双向链表可以完全取代单链表的使用
- 循环链表的N e xt,Pre和C u rre nt操作可以高效遍历链表中的所有元素
8、完整源码下载
文件名称:dlinklist-1.0.tar.gz
链接: http://pan.baidu.com/s/1c0bFUda 密码: 2asr
编译步骤:
0.1 解压缩:tar -zxvf dlinklist-1.0.tar.gz
0.2 进入目录:./configure
0.3 生成Seqlist:make
0.4 运行程序:./Dlinklist
0 0
- 【五】双向链表
- 数据结构五双向链表
- STL(五)list 双向链表
- 链表算法五之双向链表
- 五.单链表、双向链表与循环链表
- Linux双向链表(五)——简单使用示例
- 双向循环链表设计分析之五
- 五、创建一个可复用的双向链表
- 【nginx源码学习与运用 五】双向链表ngx_queue_t
- 06.线性表(五)链式存储结构.循环链表与双向链表
- 数据结构算法代码实现——循环链表、双向链表(五)
- C语言实现链表之双向链表(五)头结点前插入结点
- 大话数据结构五:线性表的链式存储结构(双向链表)
- 大话数据结构五:线性表的链式存储结构(双向链表)
- ACE篇之五:ACE容器之一(双向链表)
- ACE篇之五:ACE容器之一(双向链表)
- 紫书章六例题五 移动盒子 UVA 12657 (数组模拟双向链表)
- Java数据结构与算法分析《五》双端链表和双向链表
- CocoaPods详解之----使用篇
- DataTable添加行的方法
- crontab定时任务
- Hadoop之HDFS文件读写过程
- https协议
- 【五】双向链表
- hadoop初级班(二)
- YII 路径总结
- DbVisualizer用JDBC连接SQL Server
- 杭电ACM1391——Number Steps
- islider实现图片轮播效果
- 注解@PostConstruct与@PreDestroy讲解及实例
- dll动态链接库入门2
- 零基础学习HTML5系列课程