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

优点:插入和删除非常快。因为单链表只需要修改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. 取消eclipse英文单词拼写验证

    依次点击Preferences->General->Editors->TexEditors->Spelling->Enable Spell Checkingt , 如下图 ...

  2. [转] 【iOS基础知识】之判断NSString是否为整数、浮点数

    //判断是否为整形: - (BOOL)isPureInt:(NSString*)string{ NSScanner* scan = [NSScannerscannerWithString:string ...

  3. jsp学习与提高(一)——JSP生命周期、三大指令及动作

    1.jsp定义: 1.1以java语言为脚本语言,运行在服务端的程序: 1.2处理客户请求,生成页面 1.3其本质是个sevlet会生成.java文件编译后再生成.class文件 2.jsp生命周期( ...

  4. NOIp知识集合 By cellur925

    基本算法 快速幂 ll ksm(ll a,ll b) { ll ans=; while(b) { ) ans=ans*a%p; b>>=; a=a*a%p; } return ans; } ...

  5. Invalid YGDirection 'vertical'. should be one of: ( inherit, ltr, rtl )

    react native 路由( react-native-router-flux )跳转页面一直都报错 本项目解决方法:不是路由的问题,是跳转的页面有有问题,删除下图标记的红色即可(解决方法是排除法 ...

  6. C# 多线程程序隐患

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  7. 【考试记录】2018 山东省队集训第一轮D4(雾)

    T1题意: 给你一个$n\times m$的矩阵$B$,求它能由最少多少个形如两个向量之积$(n\times 1)\times(1\times m)$的矩阵相加得到. 题解: 考虑上界,最多需要$mi ...

  8. Codeforces Round #527 -A. Uniform String(思维)

    time limit per test 1 second memory limit per test 256 megabytes input standard input output standar ...

  9. Web自动化测试—PO设计模式(二)

    PO设计模式要点一:页面类都继承于BasePage 目录结构 ui_auto_test --src --pages --__init__.py --base_page.py --login_page. ...

  10. php设计模式-单例

    单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中一个类只有一个实例. <设计模式>对此的定义:保证一个类仅有一个实例,并提供一个访 ...