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& ...
随机推荐
- MyBaits_查询缓存02_Ehcache二级缓存
一.Ehcache二级缓存的开启 导入jar(https://github.com/mybatis/ehcache-cache/releases) <cache type="org.m ...
- [Java反射基础二]获取类的信息
本文接上文“Class类的使用”,以编写一个用来获取类的信息(成员函数.成员变量.构造函数)的工具类来讲解"反射之获取类的信息" 1.获取成员函数信息 /** * 获取成员函数信息 ...
- mysql 的用法
SELECT CASEWHEN //当count(userId) = 0的时候 让其为null 不然报警告 // count(DISTINCT userId) 不用处理 count(userId ...
- Luogu4234:最小差值生成树
题面 luogu Sol 好久没写\(LCT\) 然而写跪了\(TAT\) 把边从小到大加入森林 如果形成环,就替换最小的边 如果已经是树,更新答案 \(LCT\)维护 # include <b ...
- BZOJ1898: [Zjoi2005]Swamp 沼泽鳄鱼(矩阵快速幂)
题意 题目链接 Sol 不难发现吃人鱼的运动每\(12s\)一个周期 所以暴力建12个矩阵,放在一起快速幂即可 最后余下的部分暴力乘 #include<bits/stdc++.h> usi ...
- php动态链接扩展库
文章来源:http://keping.me/php-call-so/ PHP调用C/C++动态链接库 David June 19, 2013 C++, Linux, Study 摘要 有时候,单纯依靠 ...
- console的一些方法
原文参考http://mp.weixin.qq.com/s?__biz=MzU3MDA0NTMzMA==&mid=2247485510&idx=2&sn=0adff5754a2 ...
- Idea15 常用设置(一):JDK、SVN
1:显示行号 File->Settings->General->Appearance 2: 代码自动补齐即使是小写字母也会弹出代码补齐提示 3:自动编译 设置 4: 设 ...
- Flink Flow
1. Create environment for stream computing StreamExecutionEnvironment env = StreamExecutionEnvironme ...
- MARS3.6 Programming
An Assembly Language I.D.E. To Engage Students Of All Levels * A Tutorial *2007 CCSC: Central Plains ...