链表特点(单链表 双链表)

优点:插入和删除非常快。因为单链表只需要修改Next指向的节点,双链表只需要指向Next和Prev的节点就可以完成插入和删除操作。

缺点:当需要查找某一个节点的时候就需要一个节点一个节点去访问,这样所花的时候就比较多了。(顺序表可以弥补这缺点,但插入和删除就非常耗性能)

单链表

单链表的构成:必须要有一个链表头(head),每个节点里面有一个Next用于指向下一个节点(类似于指针)。最后一个节点的Next为null来标识链表的尾。

如下图

代码实现

 /* ------------  单链表 ------------- */
//链表头
SingleLink head = new SingleLink();
SingleLink node;
 
//添加节点
node = new SingleLink(, "刘德华");
SingleLink.Add(ref head, node);
 
node = new SingleLink(, "张学友");
SingleLink.Add(ref head, node);
 
node = new SingleLink(, "郭富城");
SingleLink.Add(ref head, node);
 
node = new SingleLink(, "黎明");
SingleLink.Add(ref head, node);
 
 
//删除节点
SingleLink.Remove(ref head, );
 
//遍历所有节点
SingleLink cursor = head;
while (cursor.Next != null)
{
    Console.WriteLine(cursor.Next.ToString());
    cursor = cursor.Next;
}
 
 
/// <summary>
/// 单链表
/// </summary>
public class SingleLink
{
    public int No { get; set; }
 
    public string Name { get; set; }
 
    //指向下一个节点(有点像指针)
    public SingleLink Next { get; set; }
 
    public SingleLink() { }
 
    public SingleLink(int no, string name)
    {
        this.No = no;
        this.Name = name;
    }
 
 
    /// <summary>
    /// 添加
    /// </summary>
    /// <param name="head">链表头</param>
    /// <param name="addNode">添加节点</param>
    public static void Add(ref SingleLink head, SingleLink addNode)
    {
        SingleLink cursor = head;
        while (cursor.Next != null)
        {
            cursor = cursor.Next;
        }
        cursor.Next = addNode;
    }
 
 
    /// <summary>
    /// 删除
    /// </summary>
    /// <param name="head">链表头</param>
    /// <param name="no">删除编号</param>
    public static void Remove(ref SingleLink head, int no)
    {
        SingleLink cursor = head;
        while (cursor.Next !=null)
        {
            if (cursor.Next.No == no)
            {
                cursor.Next = cursor.Next.Next;
                return;
            }
            cursor = cursor.Next;
        }
    }
 
 
    /// <summary>
    /// 输入信息(重写ToString方法)
    /// </summary>
    /// <returns></returns>
    public override string ToString()
    {
        return "No---> " + No + "  Name---> " + Name;
    }
}

代码分析图

双链表

  双链表的构成:双链表跟单链表差不多,也是必须要有一个链表头(head),每个节点里面有一个Next,最后一个节点的Next为null来标识链表的尾。只不过双链表在每个节点上面添加一个Prev,来标识当前节点的上一个节点。

如图:

代码实现

 /* ------------  双链表 ------------- */
//链表头
DoubleLink head = new DoubleLink();
DoubleLink node;
 
//添加节点
node = new DoubleLink(,"刘德华");
DoubleLink.Add(ref head, node);
 
node = new DoubleLink(, "张学友");
DoubleLink.Add(ref head, node);
 
node = new DoubleLink(, "郭富城");
DoubleLink.Add(ref head, node);
 
node = new DoubleLink(, "黎明");
DoubleLink.Add(ref head, node);
 
//删除节点
DoubleLink.Remove(ref head,);
 
//遍历所有节点
DoubleLink cursor = head;
while (cursor.Next != null)
{
    Console.WriteLine(cursor.Next.ToString());
    cursor = cursor.Next;
}
 
 
/// <summary>
/// 双链表
/// </summary>
public class DoubleLink
{
    public int No { get; set; }
 
    public string Name { get; set; }
 
    //下个节点
    public DoubleLink Prev { get; set; }
 
    //上个节点
    public DoubleLink Next { get; set; }
 
    public DoubleLink() { }
 
    public DoubleLink(int no, string name)
    {
        this.No = no;
        this.Name = name;
    }
 
 
    /// <summary>
    /// 添加
    /// </summary>
    /// <param name="head">链表头</param>
    /// <param name="addNode"></param>
    public static void Add(ref DoubleLink head, DoubleLink addNode)
    {
        DoubleLink cursor = head;
        while (cursor.Next != null)
        {
            cursor = cursor.Next;
        }
        cursor.Next = addNode;
        cursor.Next.Prev = cursor;
    }
 
 
    /// <summary>
    /// 删除
    /// </summary>
    /// <param name="head">链表头</param>
    /// <param name="no">删除编号</param>
    public static void Remove(ref DoubleLink head, int no)
    {
        DoubleLink cursor = head.Next;
        while (cursor != null)
        {
            if (cursor.No == no)
            {
                //防止是删除最后一个
                if (cursor.Next != null)
                {
                    cursor.Next.Prev = cursor.Prev;
                }
                cursor.Prev.Next = cursor.Next;
                return;
            }
            cursor = cursor.Next;
        }
    }
 
 
    /// <summary>
    /// 输入信息(重写ToString方法)
    /// </summary>
    /// <returns></returns>
    public override string ToString()
    {
        return "No---> " + No + "  Name---> " + Name;
    }
}

代码分析图

环形链表

  环形链表是在单链表基础之上把尾指向头就构成了一个环形的链表了。也就是单链表最后一个节点的Next指Head就可以了。

 如图:

  

代码实现

 //环形链表
LoopLink head = new LoopLink();
LoopLink node; //添加节点
node = new LoopLink(, "刘德华");
LoopLink.Add(ref head, node); node = new LoopLink(, "张学友");
LoopLink.Add(ref head, node); node = new LoopLink(, "郭富城");
LoopLink.Add(ref head, node); node = new LoopLink(, "黎明");
LoopLink.Add(ref head, node); LoopLink.Remove(ref head, ); //遍历所有节点(遍历需要拿到它的头或者尾来标识链表的结束位置,我是拿到头来遍历的)
LoopLink cursor = head;
LoopLink first = head;
//首先输出头的信息
Console.WriteLine(head);
//遍历所有节点,如果遍历到头节点就退出循环,链表打印完成
while (!Object.ReferenceEquals(cursor.Next, first))
{
Console.WriteLine(cursor.Next.ToString());
cursor = cursor.Next;
} /// <summary>
/// 环形链表
/// </summary>
class LoopLink
{ public int No { get; set; } public string Name { get; set; } public LoopLink Next { get; set; } public LoopLink() { } public LoopLink(int no, string name)
{
this.No = no;
this.Name = name;
} public static LoopLink Cursor { get; set; } /// <summary>
/// 添加
/// </summary>
/// <param name="head">链表头</param>
/// <param name="addNode">所要添加节点</param>
public static void Add(ref LoopLink head, LoopLink addNode)
{
if (head.Next == null)
{
head = addNode;
head.Next = addNode;
Cursor = head;
}
else
{
Cursor.Next = addNode;
addNode.Next = head;
Cursor = Cursor.Next;
}
} /// <summary>
/// 删除节点
/// </summary>
/// <param name="head">链表头</param>
/// <param name="no">所要删除编号</param>
public static void Remove(ref LoopLink head, int no)
{
LoopLink cur = head; while (true)
{
if (cur.Next.No == no)
{
cur.Next = cur.Next.Next;
return;
}
cur = cur.Next;
}
} /// <summary>
/// 输入信息(重写ToString方法)
/// </summary>
/// <returns></returns>
public override string ToString()
{
return "No---> " + No + " Name---> " + Name;
}
}

扩展训练(面试题)

  题目:有一颗炸弹,有N个人围成一个圆形,从第K个人开始数数,数M就退出圆。最后算出留下来要被炸死是第几个人。请用代码实现。

  代码如下:

 //N个人
int n = ; //第K个人开始数数
int k = ; //数到M就退出
int m = ; Game head = new Game(); //构建一个由N个人组成的圆形
Game.Add(ref head, n);
//查找谁会被炸死
Game.Bomb(ref head, k, m); /// <summary>
/// 游戏类
/// </summary>
public class Game
{
public int No { get; set; } public Game Next { get; set; } public Game() { } public Game(int no)
{
this.No = no;
} public static void Add(ref Game head, int n)
{
Game cursor = null;
for (int i = ; i < n; i++)
{
Game temp = new Game(i+);
if (i == )
{
head.Next = temp;
head = temp;
cursor = head;
}
else
{
cursor.Next = temp;
temp.Next = head;
cursor = cursor.Next;
}
}
} /// <summary>
/// 查找谁会被炸死
/// </summary>
/// <param name="head">链表头</param>
/// <param name="k">开始数数的人</param>
/// <param name="m">数几就退出圆圈</param>
public static void Bomb(ref Game head,int k, int m)
{
Game tail = head; //拿到最后一个节点
while (!Object.ReferenceEquals(tail.Next,head))
{
tail = tail.Next;
} //从第K个人开始数数
for (int i = ; i < k; i++)
{
head = head.Next;
tail = tail.Next;
} //当头跟尾是同一个节点说明找到最终的节点
int mark = ;
while (!object.ReferenceEquals(tail,head))
{
for (int i = ; i < m-; i++)
{
head = head.Next;
tail = tail.Next;
} Console.WriteLine(@"第"+mark+@"个安全退出人的编号:"+head.No); head = head.Next;
tail.Next = head;
mark++;
} Console.WriteLine(@"最后被炸死人的编号:" + head.No);
}
}

  总结:

    1.扩展训练题其实考的就是环形链表,这个题目跟约瑟夫问题是一样的(实现思路是一样的)

    2.“程序=算法+数据结构”,但是在我们真正开发的时候算法和数据结构用到很少,一般比较大型项目或者复杂度比较高项目和游戏里面可能才会用到这些,但是我们还是要了解,说不定面试考到了呢?(答对了会加分的哦!^_^)

    3.链表什么时候会用到呢?比如说象棋里面有悔棋,我们就可以用双向链表来实现,这样就可以悔到上一步也可以下一步了,还有很多应用场景。而单链表的话像LinkedList就是用单链表实现的(但是LinkedList被List代替,不推荐用LinkedList,推荐用List.自己查一下为什么?)

  

  (本人学识有限,文章如有误,愿见谅。希望能指出来,以免误人子弟了。^_^)

C# 数据结构 - 单链表 双链表 环形链表的更多相关文章

  1. 【算法训练营day4】LeetCode24. 两两交换链表中的结点 LeetCode19. 删除链表的倒数第N个结点 LeetCode面试题 02.07. 链表相交 LeetCode142. 环形链表II

    [算法训练营day4]LeetCode24. 两两交换链表中的结点 LeetCode19. 删除链表的倒数第N个结点 LeetCode面试题 02.07. 链表相交 LeetCode142. 环形链表 ...

  2. 数据结构与算法——链表 Linked List(单链表、双向链表、单向环形链表-Josephu 问题)

    链表是有序的列表,但是在内存中存储图下图所示 链表是以 节点 的方式来存储,是 链式存储 每个节点包含 data 域.next 域,指向下一个节点 链表的各个节点 不一定是连续存储,如上图所示 链表还 ...

  3. 图解Java数据结构之环形链表

    本篇文章介绍数据结构中的环形链表. 介绍 环形链表,类似于单链表,也是一种链式存储结构,环形链表由单链表演化过来.单链表的最后一个结点的链域指向NULL,而环形链表的建立,不要专门的头结点,让最后一个 ...

  4. 代码随想录第四天| 24. 两两交换链表中的节点 、19.删除链表的倒数第N个节点 、160.链表相交、142.环形链表II

    今天链表致死量 第一题 public static class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { ...

  5. 【LeetCode题解】141_环形链表

    目录 141_环形链表 描述 解法一:哈希表 思路 Java 实现 Python 实现 解法二:双指针(龟兔算法) 思路 Java 实现 Python 实现 141_环形链表 描述 给定一个链表,判断 ...

  6. java数据结构——单链表、双端链表、双向链表(Linked List)

    1.继续学习单链表,终于摆脱数组的魔爪了,单链表分为数据域(前突)和引用域(指针域)(后继),还有一个头结点(就好比一辆火车,我们只关心火车头,不关心其它车厢,只需知晓车头顺藤摸瓜即可),头结点没有前 ...

  7. php实现单,双向链表,环形链表解决约瑟夫问题

    传智播客PHP学院 韩顺平 PHP程序员玩转算法第一季  http://php.itcast.cn 聊天篇: 数学对我们编程来说,重不重要? 看你站在什么样的层次来说. 如果你应用程序开发,对数学要求 ...

  8. python实现数据结构单链表

    #python实现数据结构单链表 # -*- coding: utf-8 -*- class Node(object): """节点""" ...

  9. C语言数据结构-单链表的实现-初始化、销毁、长度、查找、前驱、后继、插入、删除、显示操作

    1.数据结构-单链表的实现-C语言 typedef struct LNode { int data; struct LNode* next; } LNode,*LinkList; //这两者等价.Li ...

随机推荐

  1. 求10000以内n的阶乘(openjudge 2923)

    求10000以内n的阶乘 总时间限制:  5000ms 内存限制:  655360kB 描述 求10000以内n的阶乘. 输入 只有一行输入,整数n(0<=n<=10000). 输出 一行 ...

  2. uoj#352. 新年的五维几何(概率期望+爆搜)

    传送门 我还以为这是个五维半平面交呢--结果没看数据范围-- 题解 //minamoto #include<bits/stdc++.h> #define R register #defin ...

  3. Python书写规范

    一.python脚本的规范: 每个脚本都有自己的规范,以下的规范不是强制的,但是规范一下,可以使你的脚本规范.易懂.方便使用. #!/usr/bin/env python # -*- coding: ...

  4. 剑指Offer的学习笔记(C#篇)-- 二叉搜索树的后序遍历序列

    题目描述 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则输出Yes,否则输出No.假设输入的数组的任意两个数字都互不相同. 一 . 解题思想与二叉搜索树概念 (1). 二叉树 ...

  5. Nginx 最新版源码编译安装 包含常用模块作用及所需依赖

    第一部分 Nginx最新版源码编译安装 1. 使用的模块 模块1:http_rewrite_module 基于正则匹配来实现重定向.依赖PCRE库,见依赖1 模块2:http_gzip_module ...

  6. springmvc配置的国际化资源文件显示为???key???的错误原因

    问题概述: 在spring mvc 的jstl view 视图解析器中 使用jstl <fmt:message key=”“”></fmt> 不不要绑定也可以正常显示,这里却显 ...

  7. mac mysql 编码配置

    mac mysql 编码配置 (mysql目录下没有my.cnf) 想要修改编码发现自己的/usr/local/mysql/support-files里面根本没有my.cnf 安装方式是去mysql官 ...

  8. D-温暖的签到题

    链接:https://ac.nowcoder.com/acm/contest/892/D 题意: 给你一个长度为n的序列,初始为1,2,3...n,对其进行m次操作. 操作有两种: 1 l r  表示 ...

  9. 线程池(3)Executors.newCachedThreadPool

    例子: ExecutorService es = Executors.newCachedThreadPool(); try { for (int i = 0; i < 20; i++) { Ru ...

  10. Jquery使用ajax参数详解

    记录一下  Jquery使用ajax(post.get及参数详解) 1.get: $.ajax({ type: "GET", url: baseUrl + "Showco ...