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

单链表的局限

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. SQL SEVER 元年是1900年

    用SQL语句求 本月第一天,怎么写? 可以这样写: SELECT DATEADD(mm,DATEDIFF(mm,0,GETDATE()),0); 按照日期函数DATEDIFF的定义,第二个参数是开始日 ...

  2. Visual C++ RunTime的特征——非烫即屯

    Visual C++ RunTime的特征——非烫即屯 大一刚学C语言,第二次上机课,当我发现我照着书抄写的程序在运行之外的黑框里面跳出一排“烫烫烫烫烫”,当时就震惊了.你们能想象一个来自小城,在大学 ...

  3. (hdoj 5137 floyd)How Many Maos Does the Guanxi Worth

    How Many Maos Does the Guanxi Worth Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 512000/5 ...

  4. Node.js:Buffer

    ylbtech-Node.js:Buffer 1.返回顶部 1. Node.js Buffer(缓冲区) JavaScript 语言自身只有字符串数据类型,没有二进制数据类型. 但在处理像TCP流或文 ...

  5. Super超级ERP系统---(10)订单打包

    订单拣货完成后,需要把订单装箱打包,并打印客户地址信息.订单打包的操作流程先是扫描订单号,然后扫描商品条码.  1.订单打包 打印包装箱面单 2.订单发货 订单打包完成后就等待发货,快递公司来拉货的时 ...

  6. 使用Micrisoft.net设计方案 前言

    前言 主要阐述23种设计模式在Microsoft.Net中的使用,以及使用设计模式创建后的对象如何使用.同是向我们传达3个理念,分别是: 1.  使用设计模式可以让程序更加灵活 2.  结构越复杂,意 ...

  7. classname在JavaScript中的应用

    <html> <head> <meta charset="utf-8"> <title>无标题文档</title> &l ...

  8. JavaEE学习记录

    软件152谭智馗 一.JavaEE开发环境配置 1.准备以下压缩包 (1)JDK1.7:jdk1.7.rar (2)开发工具:eclipse-jee-mars-2 (3)项目管理工具:maven-3. ...

  9. HTML 单击a标签 实现下载文件而不是浏览器打开预览

    <a d ownload class="down" title="">

  10. C# indexof 注意