C#实现双向链表
原文:http://www.cnblogs.com/skywang12345/p/3561803.html#a33 没有C#版本的。。是不是很方。。不过图和说明很好,引用一下
双向链表
双向链表(双链表)是链表的一种。和单链表一样,双链表也是由节点组成,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。
双链表的示意图如下:
表头为空,表头的后继节点为"节点10"(数据为10的节点);"节点10"的后继节点是"节点20"(数据为10的节点),"节点20"的前继节点是"节点10";"节点20"的后继节点是"节点30","节点30"的前继节点是"节点20";...;末尾节点的后继节点是表头。
双链表删除节点
删除"节点30"
删除之前:"节点20"的后继节点为"节点30","节点30" 的前继节点为"节点20"。"节点30"的后继节点为"节点40","节点40" 的前继节点为"节点30"。
删除之后:"节点20"的后继节点为"节点40","节点40" 的前继节点为"节点20"。
双链表添加节点
在"节点10"与"节点20"之间添加"节点15"
添加之前:"节点10"的后继节点为"节点20","节点20" 的前继节点为"节点10"。
添加之后:"节点10"的后继节点为"节点15","节点15" 的前继节点为"节点10"。"节点15"的后继节点为"节点20","节点20" 的前继节点为"节点15"。
代码
- /// <summary>
- /// 双向链表节点
- /// </summary>
- /// <typeparam name="T"></typeparam>
- public class BdNode<T>
- {
- public T Data { set; get; }
- public BdNode<T> Next { set; get; }
- public BdNode<T> Prev { set; get; }
- public BdNode(T val, BdNode<T> prev, BdNode<T> next)
- {
- this.Data = val;
- this.Prev = prev;
- this.Next = next;
- }
- }
链表操作:
- public class DoubleLink<T>
- {
- //表头
- private readonly BdNode<T> _linkHead;
- //节点个数
- private int _size;
- public DoubleLink()
- {
- _linkHead = new BdNode<T>(default(T), null, null);//双向链表 表头为空
- _linkHead.Prev = _linkHead;
- _linkHead.Next = _linkHead;
- _size = ;
- }
- public int GetSize() => _size;
- public bool IsEmpty() => (_size == );
- //通过索引查找
- private BdNode<T> GetNode(int index)
- {
- if (index < || index >= _size)
- throw new IndexOutOfRangeException("索引溢出或者链表为空");
- if (index < _size / )//正向查找
- {
- BdNode<T> node = _linkHead.Next;
- for (int i = ; i < index; i++)
- node = node.Next;
- return node;
- }
- //反向查找
- BdNode<T> rnode = _linkHead.Prev;
- int rindex = _size - index - ;
- for (int i = ; i < rindex; i++)
- rnode = rnode.Prev;
- return rnode;
- }
- public T Get(int index) => GetNode(index).Data;
- public T GetFirst() => GetNode().Data;
- public T GetLast() => GetNode(_size - ).Data;
- // 将节点插入到第index位置之前
- public void Insert(int index, T t)
- {
- if (_size < || index >= _size)
- throw new Exception("没有可插入的点或者索引溢出了");
- if (index == )
- Append(_size, t);
- else
- {
- BdNode<T> inode = GetNode(index);
- BdNode<T> tnode = new BdNode<T>(t, inode.Prev, inode);
- inode.Prev.Next = tnode;
- inode.Prev = tnode;
- _size++;
- }
- }
- //追加到index位置之后
- public void Append(int index, T t)
- {
- BdNode<T> inode;
- if (index == )
- inode = _linkHead;
- else
- {
- index = index - ;
- if (index < )
- throw new IndexOutOfRangeException("位置不存在");
- inode = GetNode(index);
- }
- BdNode<T> tnode = new BdNode<T>(t, inode, inode.Next);
- inode.Next.Prev = tnode;
- inode.Next = tnode;
- _size++;
- }
- public void Del(int index)
- {
- BdNode<T> inode = GetNode(index);
- inode.Prev.Next = inode.Next;
- inode.Next.Prev = inode.Prev;
- _size--;
- }
- public void DelFirst() => Del();
- public void DelLast() => Del(_size - );
- public void ShowAll()
- {
- Console.WriteLine("******************* 链表数据如下 *******************");
- for (int i = ; i < _size; i++)
- Console.WriteLine("(" + i + ")=" + Get(i));
- Console.WriteLine("******************* 链表数据展示完毕 *******************\n");
- }
- }
测试:
- DoubleLink<int> dlink = new DoubleLink<int>();// 创建双向链表
- Console.WriteLine("将 20 插入到表头之后");
- dlink.Append(, );
- dlink.ShowAll();
- Console.WriteLine("将 40 插入到表头之后");
- dlink.Append(, );
- dlink.ShowAll();
- Console.WriteLine("将 10 插入到表头之前");
- dlink.Insert(, );
- dlink.ShowAll();
- Console.WriteLine("将 30 插入到第一个位置之前");
- dlink.Insert(, );
- dlink.ShowAll();
- Console.WriteLine("展示第一个:" + dlink.GetFirst());
- Console.WriteLine("删除第一个");
- dlink.DelFirst();
- Console.WriteLine("展示第一个:" + dlink.GetFirst());
- Console.WriteLine("展示最后一个:" + dlink.GetLast());
- Console.WriteLine("删除最后一个");
- dlink.DelLast();
- Console.WriteLine("展示最后一个:" + dlink.GetLast());
- dlink.ShowAll();
- Console.ReadKey();
C#实现双向链表的更多相关文章
- 学习Redis你必须了解的数据结构——双向链表(JavaScript实现)
本文版权归博客园和作者吴双本人共同所有,转载和爬虫请注明原文链接 http://www.cnblogs.com/tdws/ 下午分享了JavaScript实现单向链表,晚上就来补充下双向链表吧.对链表 ...
- 双向链表、双向循环链表的JS实现
关于链表简介.单链表.单向循环链表.JS中的使用以及扩充方法: 单链表.循环链表的JS实现 关于四种链表的完整封装: https://github.com/zhuwq585/Data-Structu ...
- 剑指Offer面试题:25.二叉搜索树与双向链表
一.题目:二叉搜索树与双向链表 题目:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向.比如输入下图中左边的二叉搜索树,则输出转换之后的 ...
- Linux 内核数据结构:Linux 双向链表
Linux 内核提供一套双向链表的实现,你可以在 include/linux/list.h 中找到.我们以双向链表着手开始介绍 Linux 内核中的数据结构 ,因为这个是在 Linux 内核中使用最为 ...
- Linux 内核数据结构:双向链表
Linux 内核提供一套双向链表的实现,你可以在 include/linux/list.h 中找到.我们以双向链表着手开始介绍 Linux 内核中的数据结构 ,因为这个是在 Linux 内核中使用最为 ...
- 线性表-双向链表(LinkedList)
双向链表:如图1-3 所示,会把当前header拆分开,重新插入一个Entry<E>. LinkedList源码 0.首先这个类中的两个变量 private transient Entry ...
- Shuffling Machine和双向链表
1. 双向链表 https://github.com/BodhiXing/Data_Structure 2. Shuffling Machine https://pta.patest.cn/pta/t ...
- MS - 1 - 把二元查找树转变成排序的双向链表
## 1. 把二元查找树转变成排序的双向链表 ## ### 题目: 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表. ### 要求不能创建任何新的结点,只调整指针的指向. 10 ...
- javascript中的链表结构—双向链表
1.概念 上一个文章里我们已经了解到链表结构,链表的特点是长度不固定,不用担心插入新元素的时候新增位置的问题.插入一个元素的时候,只要找到插入点就可以了,不需要整体移动整个结构. 这里我们了解一下双向 ...
- Java自己实现双向链表LinkList
/** * <p> * Node 双向链表实体类 * <p> * * @author <a href="mailto:yangkj@corp.21cn.com& ...
随机推荐
- c语言结构体可以直接赋值
结构体直接赋值的实现 下面是一个实例: #include <stdio.h> struct Foo { char a; int b; double c; }foo1, foo2; //de ...
- 【转】B树、B-树、B+树、B*树、红黑树、 二叉排序树、trie树Double Array 字典查找树简介
B 树 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: 如: ...
- git使用笔记 bitbucket基本操作
实现目标: 1.将本地已经存在的项目文件保存到 bitbucket.org 2.从 bitbucket.org 检出代码库到本地 操作笔记: 1.首先在bitbucket.org创建一个代码库,并得到 ...
- 【Machine Learning】决策树之简介(1)
Content 1.decision tree representation 2.ID3:a top down learning algorithm 3.expressiveness of data ...
- EF多实体对应单表
1.EF多实体对应单表 适用场景:单数据库表,表数据有较长用字段,有不常用或者大数据字段. 2.建表语句 CREATE TABLE [Chapter2].[Photograph]( ,) primar ...
- HBuilder自定义格式化代码
对于代码格式到底为两个空格还是四个空格,可能大家喜欢的都不同,如果你是在使用HBuilder编辑器,那么恭喜你,这两种代码格式你可以轻易的更换.下面贴步骤 1.打开工具—>选项 2.选择HBui ...
- strace for Android
使用strace for Android跟踪系统调用过程方便后续的so文件分析 http://benno.id.au/blog/2007/11/18/android-runtime-stracehtt ...
- Hadoop HA集群的搭建
HA 集群搭建的难度主要在于配置文件的编写, 心细,心细,心细! ha模式下,secondary namenode节点不存在... 集群部署节点角色的规划(7节点)------------------ ...
- OutputStream-InputStream-FileOutputStream-FileInputStream-BufferedOutputStream-BufferedInputStream-四种复制方式-单层文件夹复制
字节流两套: java.lang.Object--java.io.OutputStream--java.io.FileOutputStream java.lang.Ob ...
- Hyperledger Fabric 1.0 学习搭建 (一)--- 基础环境搭建
1: 环境构建在本文中用到的宿主机环境是Centos ,版本为Centos.x86_64 7.2, 一定要用7版本以上, 要不然会安装出错. 通过Docker 容器来运行Fabric的节点,版本为v1 ...