双向链表的实现与操作(C语言实现)
双向链表也叫双链表,是链表的一种,它的每一个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的随意一个结点開始,都能够非常方便地訪问它的前驱结点和后继结点。
单链表的局限
1。单链表的结点都仅仅有一个指向下一个结点的指针
2,单链表的数据元素无法直接訪问其前驱元素
3。逆序訪问单链表中的元素是极其耗时的操作
双向链表的操作
双向链表的新操作
1,获取当前游标指向的数据元素
2,将游标重置指向链表中的第一个数据元素
3,将游标移动指向到链表中的下一个数据元素
4,将游标移动指向到链表中的上一个数据元素
5,直接指定删除链表中的某个数据元素
DLinkListNode*DLinkList_DeleteNode(DLinkList* list, DLinkListNode* node);
DLinkListNode*DLinkList_Reset(DLinkList* list);
DLinkListNode*DLinkList_Current(DLinkList* list);
DLinkListNode*DLinkList_Next(DLinkList* list);
DLinkListNode*DLinkList_Pre(DLinkList* list);
头文件:
- #ifndef _DDLinkList_H_
- #define _DDLinkList_H_
- typedef void DLinkList;
- typedef struct DLinkListNode //声明指针域
- {
- DLinkListNode * pre;
- DLinkListNode * next;
- }DLinkListNode;
- DLinkList * DLinkList_Create();
- void DLinkList_DesTroy(DLinkList * list);
- void DLinkList_Clear(DLinkList* list);
- int DLinkList_Length(DLinkList* list);
- int DLinkList_Insert(DLinkList* list, DLinkListNode* node, int pos);
- DLinkListNode* DLinkList_Get(DLinkList* list, int pos);
- DLinkListNode* DLinkList_Delete(DLinkList* list, int pos);
- DLinkListNode* DLinkList_DeleteNode(DLinkList* list, DLinkListNode* node);
- DLinkListNode* DLinkList_Reset(DLinkList* list);
- DLinkListNode* DLinkList_Current(DLinkList* list);
- DLinkListNode* DLinkList_Next(DLinkList* list);
- DLinkListNode* DLinkList_Pre(DLinkList* list);
- #endif
源文件:
- // 双向链表.cpp : 定义控制台应用程序的入口点。
- //
- #include "stdafx.h"
- #include "DLinkList.h"
- #include <stdlib.h>
- #include <malloc.h>
- typedef struct
- {
- DLinkListNode header;
- DLinkListNode * slider; //游标
- int len;
- }TDLinkList;
- struct Value
- {
- DLinkListNode header; //指针域
- int v; //数据域
- };
- int _tmain(int argc, _TCHAR* argv[])
- {
- int i = 0;
- DLinkList* list = DLinkList_Create();//创建链表
- struct Value* pv = NULL;
- struct Value v1;
- struct Value v2;
- struct Value v3;
- struct Value v4;
- struct Value v5;
- v1.v = 1;
- v2.v = 2;
- v3.v = 3;
- v4.v = 4;
- v5.v = 5;
- //插入5个数
- DLinkList_Insert(list, (DLinkListNode*)&v1, DLinkList_Length(list));
- DLinkList_Insert(list, (DLinkListNode*)&v2, DLinkList_Length(list));
- DLinkList_Insert(list, (DLinkListNode*)&v3, DLinkList_Length(list));
- DLinkList_Insert(list, (DLinkListNode*)&v4, DLinkList_Length(list));
- DLinkList_Insert(list, (DLinkListNode*)&v5, DLinkList_Length(list));
- for(i=0; i<DLinkList_Length(list); i++)
- {
- pv = (struct Value*)DLinkList_Get(list, i);
- printf("插入了:%d\n", pv->v);
- }
- printf("\n");
- //删除头尾
- DLinkList_Delete(list, DLinkList_Length(list)-1);
- DLinkList_Delete(list, 0);
- printf("删除头尾结点后:\n");
- for(i=0; i<DLinkList_Length(list); i++)
- {
- pv = (struct Value*)DLinkList_Next(list);
- printf("%d\n", pv->v);
- }
- printf("\n");
- DLinkList_Reset(list);//游标指向第一个结点 2
- DLinkList_Next(list);//游标指向第二个结点 3
- pv = (struct Value*)DLinkList_Current(list);
- printf("游标移到第二个结点后的值: %d\n", pv->v);
- DLinkList_DeleteNode(list, (DLinkListNode*)pv);//删除第二个结点
- pv = (struct Value*)DLinkList_Current(list);
- printf("游标删除第二个结点后的值: %d\n", pv->v);
- DLinkList_Pre(list); //将游标向前移动一位
- pv = (struct Value*)DLinkList_Current(list);
- printf("游标向前移了一位后的值:%d\n", pv->v);
- printf("Length: %d\n", DLinkList_Length(list));
- DLinkList_DesTroy(list);
- system("pause");
- return 0;
- }
- //创建
- DLinkList * DLinkList_Create()
- {
- TDLinkList* list = NULL;
- list = (TDLinkList*)malloc(sizeof(TDLinkList));
- if(NULL != list)
- {
- list->len = 0;
- list->header.next = NULL;
- list->header.pre = NULL;
- list->slider = NULL;
- }
- return list;
- }
- //销毁
- void DLinkList_DesTroy(DLinkList * list)
- {
- free(list);
- }
- //清空
- void DLinkList_Clear(DLinkList* list)
- {
- TDLinkList* sList = (TDLinkList*)list;
- if(NULL != sList)
- {
- sList->len = 0;
- sList->header.next = NULL;
- sList->header.pre = NULL;
- sList->slider = NULL;
- }
- }
- //获得长度
- int DLinkList_Length(DLinkList* list)
- {
- TDLinkList* sList = (TDLinkList*)list;
- int len = -1;
- if(NULL != sList)
- {
- len = sList->len;
- }
- return len;
- }
- //插入
- int DLinkList_Insert(DLinkList* list, DLinkListNode* node, int pos)
- {
- TDLinkList* sList = (TDLinkList*)list;
- int i = 0;
- int ret = 0;
- if((NULL != sList) && (pos >= 0) && (NULL != node))
- {
- DLinkListNode* current = (DLinkListNode*)sList;
- DLinkListNode* next = NULL;
- for( i=0; (i<pos) && (current->next != NULL); i++)
- {
- current = current->next;
- }
- next = current->next;
- current->next = node;
- node->next = next;
- if(NULL != next)
- {
- next->pre = node;
- }
- node->pre = current;
- if(sList->len == 0)
- {
- node->pre = NULL;
- sList->slider = node;
- }
- sList->len++;
- ret = 1;
- }
- return ret;
- }
- //获得结点
- DLinkListNode* DLinkList_Get(DLinkList* list, int pos)
- {
- TDLinkList* sList = (TDLinkList*)list;
- int i = 0;
- DLinkListNode * resnode = NULL;
- if((pos >= 0) && (pos < sList->len) && (NULL != sList))
- {
- DLinkListNode * current = (DLinkListNode*)sList;
- for ( i=0; i<pos; i++)
- {
- current = current->next;
- }
- resnode = current->next;
- }
- return resnode;
- }
- //删除
- DLinkListNode* DLinkList_Delete(DLinkList* list, int pos)
- {
- TDLinkList* sList = (TDLinkList*)list;
- int i = 0;
- DLinkListNode* ret = NULL;
- if((NULL != sList) && (pos >= 0) && (pos < sList->len))
- {
- DLinkListNode* current = (DLinkListNode*)sList;
- DLinkListNode* next = NULL;
- for ( i=0; i<pos; i++)
- {
- current = current->next;
- }
- ret = current->next;
- next = ret->next;
- current->next = next;
- if(NULL != next)
- {
- next->pre = current;
- //当删除的结点是第一个结点的时候
- if(current == (DLinkListNode*)sList)
- {
- //前驱指针为空
- next->pre = NULL;
- }
- }
- if(sList->slider == ret)
- {
- sList->slider = next;
- }
- sList->len--;
- }
- return ret;
- }
- //通过指定结点删除
- DLinkListNode* DLinkList_DeleteNode(DLinkList* list, DLinkListNode* node)
- {
- TDLinkList* sList = (TDLinkList*)list;
- DLinkListNode* ret = NULL;
- int i = 0;
- if((NULL != sList) && (NULL != node))
- {
- DLinkListNode* current = (DLinkListNode*)sList;
- for ( i=0; i<sList->len; i++)
- {
- if(current->next == node)
- {
- ret = current->next;
- break;
- }
- current = current->next;
- }
- if( ret != NULL )
- {
- DLinkList_Delete(sList, i);
- }
- }
- return ret;
- }
- //重置游标,使其到第一个结点处
- DLinkListNode* DLinkList_Reset(DLinkList* list)
- {
- TDLinkList* sList = (TDLinkList*)list;
- DLinkListNode* ret = NULL;
- if((NULL != sList))
- {
- sList->slider = sList->header.next;
- ret = sList->slider;
- }
- return ret;
- }
- //将游标移至当前结点处
- DLinkListNode* DLinkList_Current(DLinkList* list)
- {
- TDLinkList* sList = (TDLinkList*)list;
- DLinkListNode* ret = NULL;
- if(NULL != sList)
- {
- ret = sList->slider;
- }
- return ret;
- }
- //
- DLinkListNode* DLinkList_Next(DLinkList* list)
- {
- TDLinkList* sList = (TDLinkList*)list;
- DLinkListNode* ret = NULL;
- if((NULL != sList) && (NULL != sList->slider ))
- {
- ret = sList->slider;
- sList->slider = ret->next;
- }
- return ret;
- }
- DLinkListNode* DLinkList_Pre(DLinkList* list)
- {
- TDLinkList* sList = (TDLinkList*)list;
- DLinkListNode* ret = NULL;
- if((NULL != sList) && (NULL != sList->slider ))
- {
- ret = sList->slider;
- sList->slider = ret->pre;
- }
- return ret;
- }
执行结果:
- 插入了:1
- 插入了:2
- 插入了:3
- 插入了:4
- 插入了:5
- 删除头尾结点后:
- 2
- 3
- 4
- 游标移到第二个结点后的值: 3
- 游标删除第二个结点后的值: 4
- 游标向前移了一位后的值:2
- Length: 2
- 请按随意键继续. . .
如有错误,望不吝指出。
双向链表的实现与操作(C语言实现)的更多相关文章
- neo4j初次使用学习简单操作-cypher语言使用
Neo4j 使用cypher语言进行操作 Cypher语言是在学习Neo4j时用到数据库操作语言(DML),涵盖对图数据的增删改查 neo4j数据库简单除暴理解的概念: Neo4j中不存在表的概念, ...
- 栈的实现与操作(C语言实现)
栈的定义 1, 栈是一种特殊的线性表 2,栈仅能在线性表的一端进行操作 3,栈顶(Top): 同意操作的一端 同意操作的一端 4,栈底(Bottom): ,不同意操作的一端 不同意操作 ...
- 动态单链表的传统存储方式和10种常见操作-C语言实现
顺序线性表的优点:方便存取(随机的),特点是物理位置和逻辑为主都是连续的(相邻).但是也有不足,比如:前面的插入和删除算法,需要移动大量元素,浪费时间,那么链式线性表 (简称链表) 就能解决这个问题. ...
- Gremlin--一种支持对图表操作的语言
Gremlin 是操作图表的一个非常有用的图灵完备的编程语言.它是一种Java DSL语言,对图表进行查询.分析和操作时使用了大量的XPath. Gremlin可用于创建多关系图表.因为图表.顶点和边 ...
- 动态分配的顺序线性表的十五种操作—C语言实现
线性表 定义:是最常用的,也是最简单的数据结构,是长度为n个数据元素的有序的序列. 含有大量记录的线性表叫文件 记录:稍微复杂的线性表里,数据元素为若干个数据项组成,这时把一个数据元素叫记录 结构特点 ...
- 循环链表的实现与操作(C语言实现)
循环链表是还有一种形式的链式存贮结构.它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环. 循环链表的操作 1,循环链表的新操作 2, 获取当前游标指向的数据元素 3, 将游标重置指向链 ...
- 图的存储结构与操作--C语言实现
图(graph)是一种比树结构还要复杂的数据结构,它的术语,存储方式,遍历方式,用途都比较广,所以如果想要一次性完成所有的代码,那代码会非常长.所以,我将分两次来完成图的代码.这一次,我会完成图的五种 ...
- 二叉树的操作--C语言实现
树是一种比较复杂的数据结构,它的操作也比较多.常用的有二叉树的创建,遍历,线索化,线索化二叉树的遍历,这些操作又可以分为前序,中序和后序.其中,二叉树的操作有递归与迭代两种方式,鉴于我个人的习惯,在这 ...
- C文件操作的语言fgets()
谈fgets(..)功能. 原型 char * fgets(char * s, int n,FILE *stream); 參数: s: 字符型指针.指向存 ...
随机推荐
- poj1179 区间dp(记忆化搜索写法)有巨坑!
http://poj.org/problem?id=1179 Description Polygon is a game for one player that starts on a polygon ...
- [NOIP 2017] 奶酪
[题目链接] http://uoj.ac/problem/332 [算法] 直接搜索即可 注意使用long long [代码] #include<bits/stdc++.h> using ...
- kubernetes系列(小知识):kubectl命令自动补全
kubectl命令自动补全 linux系统 yum install -y bash-completion source /usr/share/bash-completion/completions/d ...
- linux下使用bcp备份sybase数据
命令|数据库名|表名|导出到|文件名|格式|sybase服务名|数据库登录名 |字符集 bcp dbname..tablename out filename -n -Sgfdmhk -UISISMan ...
- [hihocoder][Offer收割]编程练习赛44
扫雷游戏 #pragma comment(linker, "/STACK:102400000,102400000") #include<stdio.h> #includ ...
- 第一天:java与mysql的连接工具类
第一天:java与mysql的连接工具类 java最新版马上就要收费,这无疑是这门语言的衰败起始,毕竟在中国收费便难发展,例如c#,但是毕业设计已经选好用java来写一个动态网站, 这已经是一个事实, ...
- css3动画简单案例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 【Oracle】Rman简介
1.备份和恢复功能的用途: –保护数据 -介质故障 -用户错误 -应用程序错误 –数据保存和历史数据保留 –数据传输 2.典型的备份和恢复任务 –通过配置数据库实现可恢复 –定义备份计划 –对不同类型 ...
- 3D特征:关于HFM和HBB
1.HBB 三维绑定框 (1): 要用到HBB,定义还不太清楚,来自于 VALVE Developer Community (https://developer.valvesoftware.co ...
- swift 类型备份
Swift语法3.03(类型Types) https://www.jianshu.com/p/839f9bc4b9a3 https://developer.apple.com/library/cont ...