双向链表也叫双链表,是链表的一种,它的每一个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的随意一个结点開始,都能够非常方便地訪问它的前驱结点和后继结点。

单链表的局限

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语言实现)的更多相关文章

  1. neo4j初次使用学习简单操作-cypher语言使用

    Neo4j 使用cypher语言进行操作 Cypher语言是在学习Neo4j时用到数据库操作语言(DML),涵盖对图数据的增删改查  neo4j数据库简单除暴理解的概念: Neo4j中不存在表的概念, ...

  2. 栈的实现与操作(C语言实现)

    栈的定义  1, 栈是一种特殊的线性表  2,栈仅能在线性表的一端进行操作  3,栈顶(Top): 同意操作的一端 同意操作的一端  4,栈底(Bottom): ,不同意操作的一端 不同意操作 ...

  3. 动态单链表的传统存储方式和10种常见操作-C语言实现

    顺序线性表的优点:方便存取(随机的),特点是物理位置和逻辑为主都是连续的(相邻).但是也有不足,比如:前面的插入和删除算法,需要移动大量元素,浪费时间,那么链式线性表 (简称链表) 就能解决这个问题. ...

  4. Gremlin--一种支持对图表操作的语言

    Gremlin 是操作图表的一个非常有用的图灵完备的编程语言.它是一种Java DSL语言,对图表进行查询.分析和操作时使用了大量的XPath. Gremlin可用于创建多关系图表.因为图表.顶点和边 ...

  5. 动态分配的顺序线性表的十五种操作—C语言实现

    线性表 定义:是最常用的,也是最简单的数据结构,是长度为n个数据元素的有序的序列. 含有大量记录的线性表叫文件 记录:稍微复杂的线性表里,数据元素为若干个数据项组成,这时把一个数据元素叫记录 结构特点 ...

  6. 循环链表的实现与操作(C语言实现)

    循环链表是还有一种形式的链式存贮结构.它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环. 循环链表的操作 1,循环链表的新操作 2, 获取当前游标指向的数据元素 3, 将游标重置指向链 ...

  7. 图的存储结构与操作--C语言实现

    图(graph)是一种比树结构还要复杂的数据结构,它的术语,存储方式,遍历方式,用途都比较广,所以如果想要一次性完成所有的代码,那代码会非常长.所以,我将分两次来完成图的代码.这一次,我会完成图的五种 ...

  8. 二叉树的操作--C语言实现

    树是一种比较复杂的数据结构,它的操作也比较多.常用的有二叉树的创建,遍历,线索化,线索化二叉树的遍历,这些操作又可以分为前序,中序和后序.其中,二叉树的操作有递归与迭代两种方式,鉴于我个人的习惯,在这 ...

  9. C文件操作的语言fgets()

        谈fgets(..)功能.     原型  char *  fgets(char * s, int n,FILE *stream);     參数:          s: 字符型指针.指向存 ...

随机推荐

  1. 301 和 302 对 SEO 的影响

    网站优化中,经常会面临网站链接修改或改变的事情,其中一个解决办法就是使用网站跳转的方式,处理变化的链接,下面讲述301和302跳转对SEO的影响. 301(永久移动) 请求的网页已被永久移动到新位置. ...

  2. 【SDOI 2010】 计算器

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=2242 [算法] 第一问用快速幂解决 第二问用exgcd解决 第三问用BSGS算法解决 ...

  3. EOJ 2844 排序去重

    有 n 个 1 到 1000 之间的整数 (1≤n≤100),对于其中重复的数字,只保留一个,把其余相同的数去掉.然后再按照指定的排序方式把这些数排序. Input 第 1 行为字母 A 或 D,A ...

  4. Spark Streaming概念学习系列之Spark Streaming容错

    Spark Streaming容错 检查点机制-checkpoint 什么是检查点机制? Spark Streaming 周期性地把应用数据存储到诸如HDFS 或Amazon S3 这样的可靠存储系统 ...

  5. SQLServer inner join,left join,right join,outer join 备忘备忘

    LEFT JOIN LEFT JOIN 关键字会从左表那里返回所有的行,即使在右表中没有匹配的行. 即LEFT JOIN 的 ON 条件不会对数据行造成影响 RIGHT JOIN RIGHT JOIN ...

  6. Service不完全解析

    本篇的内容并不是介绍service使用方法和生命周期的,而是对其中的一些要点进行记录和分析. 我们都知道,Service是一个在后台执行的应用组件,用于在后台进行长期操作,例如进行网络事务,播放背景音 ...

  7. innerHTML的用法

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  8. Java单例模式 多种实现方式

    一:通过静态私有成员实现单例模式 (1):私有化构造函数 (2):new静态实例属性对象,加锁. 单例类: package SinglePag; /* * 构造函数私有化,结合锁+静态的概念 实现单例 ...

  9. 【Oracle】重置参数

    单实例中: alter system reset parameter <scope=memory|spfile|both>: --memory|spfile|both,选其一 集群环境中: ...

  10. C# 时间日期(函数,解释)

    C#时间/日期格式大全,C#时间/日期函数大全 有时候我们要对时间进行转换,达到不同的显示效果 默认格式为:2005-6-6 14:33:34 如果要换成成200506,06-2005,2005-6- ...