C#双链表
单链表允许从一个结点直接访问它的后继结点,所以, 找直接后继结点的时间复杂度是 O(1)。但是,要找某个结点的直接前驱结点,只能从表的头引用开始遍历各结点。如果某个结点的 Next 等于该结点,那么,这个结点就是该结点的直接前驱结点。也就是说,找直接前驱结点的时间复杂度是 O(n),n是单链表的长度。当然,我们也可以在结点的引用域中保存直接前驱结点的地址而不是直接后继结点的地址。这样,找直接前驱结点的时间复杂度只有 O(1),但找直接后继结点的时间复杂度是 O(n)。如果希望找直接前驱结点和直接后继结点的时间复杂度都是 O(1),那么,需要在结点中设两个引用域,一个保存直接前驱结点的地址,叫 prev,一个直接后继结点的地址,叫 next,这样的链表就是双向链表(Doubly Linked List)。
双链表节点类的实现如下所示:
public class DbNode<T>//双向链表结点类
{
private T data;
private DbNode<T> prev;
private DbNode<T> next;
public DbNode(DbNode<T> p, T val)
{
next = p;
data = val;
}
public DbNode(DbNode<T> p)
{
next = p;
}
public DbNode(T val)
{
next = null;
data = val;
}
public DbNode()
{
next = null;
data = default(T);
}
public T Data
{
get { return data; }
set { data = value; }
}
public DbNode<T> Prev
{
get { return prev; }
set { prev = value; }
}
public DbNode<T> Next
{
get { return next; }
set { next = value; }
}
}
双链表接口的实现如下所示:
public interface ILinkList<T>//双向链表接口
{
void AddFirst(T t);
void AddLast(T t);
void Clear();
int Count { get; }
DbNode<T> Head { get; set; }
DbNode<T> Tail { get; set; }
void Insert(int index, T t);
bool IsEmpty { get; }
void RemoveAt(int index);
void RemoveFirst();
void RemoveLast();
DbNode<T> this[int index] { get; }
}
双链表的实现如下所示:
public class LinkList<T> : ILinkList<T>
{
private DbNode<T> head;
private DbNode<T> tail;
private int size;
public DbNode<T> Head
{
get { return head; }
set { head = value; }
}
public DbNode<T> Tail
{
get { return tail; }
set { tail = value; }
}
public DbNode<T> this[int index]
{
get
{
if (head == null || index < 0 || index >= Count)
{
return null;
}
int i = 0;
DbNode<T> current = new DbNode<T>();
if (i < size / 2)
{
current = head;
while (true)
{
if (i == index) { break; }
current = current.Next;
i++;
}
return current;
}
else
{
current = tail;
i = size;
while (true)
{
if (i == index) { break; }
current = current.Prev;
i--;
}
return current.Next;
}
}
}
public bool IsEmpty
{
get { return head == null; }
}
public void AddFirst(T t)
{
DbNode<T> node = new DbNode<T>();
if (head == null)
{
head = node;
tail = node;
++size;
return;
}
node.Next = head;
head.Prev = node;
head = node;
++size;
}
public void AddLast(T t)
{
DbNode<T> node = new DbNode<T>();
if (head == null)
{
head = node;
tail = node;
++size;
return;
}
tail.Next = node;
node.Prev = tail;
tail = node;
++size;
}
public void Clear()
{
head = null;
tail = null;
size = 0;
}
public int Count
{
get { return size; }
}
public void Insert(int index, T t)
{
if (index < 0 || index >= Count)
{
return;
}
if (IsEmpty && index > 0)
{
return;
}
if (IsEmpty)
{
AddFirst(t);
return;
}
DbNode<T> current = head;
DbNode<T> node = new DbNode<T>(t);
int i = 0;
while (true)
{
if (i == index) break;
current = current.Next;
i++;
}
current.Prev.Next = node;//此处很重要
node.Prev = current.Prev;
node.Next = current;
current.Prev = node;
size++;
}
public void RemoveAt(int index)
{
if (index < 0 || index >= Count)
{
return;
}
if (IsEmpty && index > 0)
{
return;
}
if (IsEmpty)
{
RemoveFirst();
return;
}
if (index == size - 1)
{
RemoveLast();
return;
}
DbNode<T> current = head;
int i = 0;
while (true)
{
if (i == index) break;
current = current.Next;
i++;
}
current.Prev.Next = current.Next;
current.Next.Prev = current.Prev;
size--;
}
public void RemoveFirst()
{
if (IsEmpty) { return; }
if (size == 1) { Clear(); }
head = head.Next;
head.Prev = null;
size--;
}
public void RemoveLast()
{
if (IsEmpty) { return; }
if (size == 1) { Clear(); }
tail = tail.Prev;
tail.Next = null;
size--;
}
}
C#双链表的更多相关文章
- JAVA 链表操作:单链表和双链表
主要讲述几点: 一.链表的简介 二.链表实现原理和必要性 三.单链表示例 四.双链表示例 一.链表的简介 链表是一种比较常用的数据结构,链表虽然保存比较复杂,但是在查询时候比较便捷,在多种计算机语言都 ...
- java实现双链表(差点没写吐系列...)
刚才把单链表写完了,现在又把双链表写了,双链表和单链表的区别就是每个节点有prior和next两个指针,不同于单链表的一个next指针,而且,正是因为有这两个指针,所以双链表可以前后两个方向去移动指针 ...
- 数据结构图文解析之:数组、单链表、双链表介绍及C++模板实现
0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...
- C和指针 第十二章 使用结构和指针 双链表和语句提炼
双链表中每个节点包含指向当前和之后节点的指针,插入节点到双链表中需要考虑四种情况: 1.插入到链表头部 2.插入到链表尾部 3.插入到空链表中 4.插入到链表内部 #include <stdio ...
- [C++11][数据结构]自己的双链表实现
这个双链表,是我模仿stl的list制作的,只实现了一些基本功能,像merge,transfer这些就没有实现,用户可以用基本操作来自己做外部实现. 我没有选用stl的[begin,end)迭代器模式 ...
- Linux 底下使用C语言的 单链表 ,双链表,二叉树 读取文件,并排序
直接上代码 单链表Linux读文件排序: 双链表Linux读取文件排序: 二叉树LinuX读取文件并排序:
- 再谈LRU双链表内存管理
N年前我写了个双链表也发了博客,还添了代码.但是那个代码不但复杂,而且还有有问题的,一直懒得整理,放在空间误导别人.最近在写服务端,今天抽点空补一篇. 关于LRU网上随便搜,有过后端经验的人应该很多都 ...
- 数组、单链表和双链表介绍 以及 双向链表的C/C++/Java实现
概要 线性表是一种线性结构,它是具有相同类型的n(n≥0)个数据元素组成的有限序列.本章先介绍线性表的几个基本组成部分:数组.单向链表.双向链表:随后给出双向链表的C.C++和Java三种语言的实现. ...
- C++ 双链表基本操作
上一篇博客主要总结了单向链表,这次再总结一下双向链表. 1.概念 双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱.所以,从双向链表中的任意一个结点开始,都 ...
随机推荐
- aliyun source.list
电信的网络越来越不靠普.ubuntu环境使用下面的source.list deb http://mirrors.aliyun.com/ubuntu/ trusty main restricted un ...
- 关于紫光a5扫描仪的安装
同事需要扫描写东西,从别的机器上搬来紫光a5的扫描仪,不会安装,需要帮忙. 插上扫描仪,win7提示发现新硬件,开始自动安装驱动.等了一会儿,提示无法安装,看来得手工寻找驱动来安装了.上网搜索a5的驱 ...
- ASP.NET MVC多表单提交
多表单提交需要写清路径,以便主程序可以找到 方法一:直接写路径, action="~/Home/other1" "~"表示从根目录开始 方法2:@using ...
- 实际项目中的一个angularjs 应用
实际需求:通过下拉框,选择自己需要的类型,创建元素(要求必须是输入点击保存了才能出现对应的类型块) html代码: <div class="list-panel-data"& ...
- JavaScript 面向对象(二) —— 案例篇
看案例前可以先看看基础篇:JavaScript 面向对象(一) —— 基础篇 案例——面向对象的选项卡:把面向过程的程序一步步改成面向对象的形式,使其能够更加的通用(但是通用的东西,一般会比较臃肿). ...
- css3圆角(还有百分比设置椭圆) 阴影 字体
一. 现在前面只写知识点,全部内容放在后面截图展示: 给元素添加圆角: border-radius属性,他的值如果等于高的一半,将会等到一个圆形,大于一半叶然是一个圆形 radius是指半径,他求出圆 ...
- java解析XML文件
dom4j是一个Java的XML API,类似于jdom,用来读写XML文件的.dom4j是一个非常非常优秀的Java XML API,具有性能优异.功能强大和极端易用使用的特点,同时它也是一个开放源 ...
- Ubuntu安装node
#!/bin/bash echo "添加环境变量需要root权限,如无root权限,则不添加环境变量" echo "输入Node下载地址(目前仅支持Node官方网站上Li ...
- Codeforces Round #383 (Div. 2) 解题报告
本来是打算所有半夜进行的CF都不参加的,但看到这次比赛22:35就开始,还是没有忍住orz--晚上总是不够清醒,做题思维不如白天活跃,低级错误常常出现.出的比较早的C因为一个书写错误有点小bug,在比 ...
- mac 端口被占用及kill端口
在本地部署 Web 应用时我有遇到过某网络端口已经被其他程序占用的情况,这时候就需要先退出占用该端口的进程,我们可以通过“终端”来实现结束占用某特定端口的进程 1.打开终端,使用如下命令: lsof ...