1.对比单向链表

单向链表查找的方向只能是一个方向,而双向链表可以向前或者向后查找

单向链表不能自我删除,需要靠辅助节点,而双向链表可以自我删除

对于单向链表的删除,我们首先要找到单向链表待删除节点的前一个节点,然后前一个节点的下一个节点指向删除节点的后一个节点。

2.双向链表的思路

3.代码实现

    public class ListNode
{
public ListNode(int id, string name, string nickName)
{
this.Id = id;
this.Name = name;
this.NickName = nickName;
}
public int Id { get; set; } public string Name { get; set; } public string NickName { get; set; } public ListNode Next { get; set; } public ListNode Pre { get; set; }
}
  public class DoubleLinkedList
{
public ListNode HeadNode; public DoubleLinkedList()
{
HeadNode = new ListNode(, "", "");
} public void GetList()
{
var temp = HeadNode.Next; while (temp != null)
{
Console.WriteLine($"id={temp.Id},name={temp.Name},nickName={temp.NickName}"); temp = temp.Next;
}
} public void Add(ListNode listNode)
{
var temp = HeadNode; //如果temp.Next为null就表示temp为最后一个节点;
while (temp.Next != null)
{
temp = temp.Next;
}
//把最后的节点指向待添加的节点
temp.Next = listNode; //将待添加的前一个节点指向temp
listNode.Pre = temp;
} public void Update(ListNode listNode)
{
var temp = HeadNode; //bool flag = false; while (temp.Next != null)
{
if (temp.Next.Id == listNode.Id)
{
//flag = true;
temp.Next.Name = listNode.Name; temp.Next.NickName = listNode.NickName; break;
} temp = temp.Next;
} //if (flag)
//{
// temp.Next.Name = listNode.Name;
// temp.Next.NickName = listNode.NickName;
//}
//else Console.WriteLine("未找到");
} public void Delete(int id)
{
/*{
var temp = HeadNode; while (temp.Next != null)
{
if (temp.Next.Id == id)
{
if (temp.Next.Next != null)
temp.Next.Next.Pre = temp;
temp.Next.Pre.Next = temp.Next.Next;
}
temp = temp.Next;
}
}*/ var temp = HeadNode.Next; while (temp != null)
{
if (temp.Id == id)
{
//如果是最后一个节点,那么就不需要执行下面的temp.Next.Pre = temp.Pre;
if (temp.Next != null) temp.Next.Pre = temp.Pre;//将temp的后一个节点的前一个指针指向temp的前一个节点 temp.Pre.Next = temp.Next;//将temp的前一个节点的后一个指针指向temp的后一个节点
} temp = temp.Next;
}
} public static void Test()
{
Console.WriteLine("双向链表的测试\n"); ListNode listNode1 = new ListNode(, "宋江", "及时雨");
ListNode listNode2 = new ListNode(, "卢俊义", "玉麒麟");
ListNode listNode3 = new ListNode(, "吴用", "智多星");
ListNode listNode4 = new ListNode(, "林冲", "豹子头"); DoubleLinkedList linkedList = new DoubleLinkedList(); //添加链表数据
linkedList.Add(listNode1);
linkedList.Add(listNode2);
linkedList.Add(listNode3);
linkedList.Add(listNode4); //获取链表所有数据
linkedList.GetList(); linkedList.Update(new ListNode(, "宋", "及时")); Console.WriteLine("\n获取链表修改后的所有数据\n");
linkedList.GetList(); linkedList.Delete(); Console.WriteLine("\n获取链表删除后的所有数据\n");
linkedList.GetList();
}
}

C#数据结构与算法系列(六):链表——双链表(Double-LinkedList)的更多相关文章

  1. 数据结构与算法系列2 线性表 链表的分类+使用java实现链表+链表源码详解

    数据结构与算法系列2.2 线性表 什么是链表? 链表是一种物理存储单元上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表的链接次序实现的一系列节点组成,节点可以在运行时动态生成,每个节点包括两个 ...

  2. javascript实现数据结构与算法系列:栈 -- 顺序存储表示和链式表示及示例

    栈(Stack)是限定仅在表尾进行插入或删除操作的线性表.表尾为栈顶(top),表头为栈底(bottom),不含元素的空表为空栈. 栈又称为后进先出(last in first out)的线性表. 堆 ...

  3. C# 数据结构 - 单链表 双链表 环形链表

    链表特点(单链表 双链表) 优点:插入和删除非常快.因为单链表只需要修改Next指向的节点,双链表只需要指向Next和Prev的节点就可以完成插入和删除操作. 缺点:当需要查找某一个节点的时候就需要一 ...

  4. 数据结构与算法系列2 线性表 使用java实现动态数组+ArrayList源码详解

    数据结构与算法系列2 线性表 使用java实现动态数组+ArrayList源码详解 对数组有不了解的可以先看看我的另一篇文章,那篇文章对数组有很多详细的解析,而本篇文章则着重讲动态数组,另一篇文章链接 ...

  5. 数据结构与算法之PHP实现链表类(单链表/双链表/循环链表)

    链表是由一组节点组成的集合.每个节点都使用一个对象的引用指向它的后继.指向另一个节点的引用叫做链表. 链表分为单链表.双链表.循环链表.   一.单链表 插入:链表中插入一个节点的效率很高.向链表中插 ...

  6. 数据结构与算法系列研究七——图、prim算法、dijkstra算法

    图.prim算法.dijkstra算法 1. 图的定义 图(Graph)可以简单表示为G=<V, E>,其中V称为顶点(vertex)集合,E称为边(edge)集合.图论中的图(graph ...

  7. 《数据结构与算法之美》 <05>链表(下):如何轻松写出正确的链表代码?

    想要写好链表代码并不是容易的事儿,尤其是那些复杂的链表操作,比如链表反转.有序链表合并等,写的时候非常容易出错.从我上百场面试的经验来看,能把“链表反转”这几行代码写对的人不足 10%. 为什么链表代 ...

  8. javascript实现数据结构与算法系列:循环链表与双向链表

    循环链表(circular linked list) 是另一种形式的链式存储结构.它的特点是表中最后一个结点的指针域指向头结点,整个表形成一个环. 循环链表的操作和线性链表基本一致,仅有细微差别. w ...

  9. 数据结构与算法系列研究五——树、二叉树、三叉树、平衡排序二叉树AVL

    树.二叉树.三叉树.平衡排序二叉树AVL 一.树的定义 树是计算机算法最重要的非线性结构.树中每个数据元素至多有一个直接前驱,但可以有多个直接后继.树是一种以分支关系定义的层次结构.    a.树是n ...

随机推荐

  1. 【python爬虫】scrapy实战1--百万微博任性采集

    原文: https://blog.csdn.net/qq_36936730/article/details/105132550

  2. Java——多线程基础知识

    多线程进程和线程的区别:每一个进程拥有自己的一整套变量,而线程则共享数据.java.lang.Thread    static void sleep(long millis) 线程休眠给定的毫秒数,用 ...

  3. SPL基础接口

    Iterator 迭代器接口 SPL规定,所有实现了Iterator接口的class,都可以用在foreach Loop中.Iterator接口中包含5个必须实现的方法: interface Iter ...

  4. Mysql与Mysqli的区别及特点

    1)PHP-MySQL 是 PHP 操作 MySQL 资料库最原始的 Extension ,PHP-MySQLi 的 i 代表 Improvement ,提更了相对进阶的功能,就 Extension ...

  5. Python __str__(self)

    python 在打印一个实例化对象时,打印的是对象的地址,比如:<__main__.Workers object at 0x00000000255A9AC8> 而__str__(self) ...

  6. 创建执行线程方式三:实现Callable接口

    Callable接口 ① Java 5.0 在 java.util.concurrent 提供了一个新的创建执行 线程的方式:Callable 接口② Callable 接口类似于 Runnable, ...

  7. ArrayList及List的常用方法

    ArrayList package com.aff.coll; import java.util.ArrayList; import java.util.List; import org.junit. ...

  8. Node.js躬行记(2)——文件系统和网络

    一.文件系统 fs模块可与文件系统进行交互,封装了常规的POSIX函数.POSIX(Portable Operating System Interface,可移植操作系统接口)是UNIX系统的一个设计 ...

  9. PAT1034 有理数四则运算 (20分)

    1034 有理数四则运算 (20分)   本题要求编写程序,计算 2 个有理数的和.差.积.商. 输入格式: 输入在一行中按照 a1/b1 a2/b2 的格式给出两个分数形式的有理数,其中分子和分母全 ...

  10. STL中的迭代器分类

      STL中迭代器的分类 五类迭代器如下: 1.输入迭代器:只读,一次传递    为输入迭代器预定义实现只有istream_iterator和istreambuf_iterator,用于从一个输入流i ...