链表:单向链表

Posted dotnet261010

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了链表:单向链表相关的知识,希望对你有一定的参考价值。

一、什么是单向链表

在动态分配内存空间时,最常使用的就是“单向链表”(Single Linked List)。一个单向链表节点基本上是由两个元素,即数据字段和指针所组成,而指针将会指向下一个元素在内存中的位置,如下图所示:

技术图片

在“单向链表”中,第一个节点是“链表头指针”,指向最后一个节点的指针设为NULL,表示它是“链表尾”,不指向任何地方。例如列表A={a、b、c、d、x},其单向链表的数据结构如下图所示:

技术图片

由于单向链表中所有节点都知道节点本身的下一个节点在哪里,但是对于前一个节点却没有办法知道,所以在单向链表的各种操作中,“链表头指针”就显得相当重要,只要存在链表头指针,就可以遍历整个链表,进行加入和删除节点等操作。

注意:除非必要,否则不可移动链表头指针。

通常在其他程序设计语言中,如C或C++语言,是以指针(pointer)类型来处理链表类型的数据结构。由于在C#程序设计语言中没有指针类型,因此可以把链表声明为类(class)。例如要模拟链表中的节点,必须声明如下的Node类,这里使用泛型:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SingleLinkedListDemo
{
    /// <summary>
    /// 链表节点类
    /// </summary>
    public class Node<T>
    {
        /// <summary>
        /// 数据字段
        /// </summary>
        public T Data { get; set; }

        /// <summary>
        /// 指针 指向下一个元素
        /// </summary>
        public Node<T> Next { get; set; }

        /// <summary>
        /// 无参构造函数
        /// </summary>
        public Node()
        {
            // 赋默认值
            this.Data = default(T);
            this.Next = null;
        }

        /// <summary>
        /// 只传递数据字段的构造函数,指针默认为null
        /// </summary>
        /// <param name="value"></param>
        public Node(T value)
        {
            this.Data = value;
            this.Next = null;
        }

        /// <summary>
        /// 同时传递数据和指针的构造函数
        /// </summary>
        /// <param name="value"></param>
        /// <param name="next"></param>
        public Node(T value,Node<T> next)
        {
            this.Data = value;
            this.Next = next;
        }

        /// <summary>
        /// 只传递指针的构造函数
        /// </summary>
        /// <param name="next"></param>
        public Node(Node<T> next)
        {
            this.Next = next;
        }
    }
}

接着可以声明链表SingleLinkedList类,该类定义两个Node<T>类型的节点指针,分别指向链表的第一个节点和最后一个节点:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SingleLinkedListDemo
{
    public class SingleLinkedList<T>
    {
        /// <summary>
        /// 头节点
        /// </summary>
        private Node<T> HeadNode;

        /// <summary>
        /// 尾节点
        /// </summary>
        private Node<T> LastNode;

        // 定义类中其它方法,增加节点、删除节点、移动节点等
    }
}

如果链表中的节点不只记录单一数值,例如每一个节点除了有指向下一个节点的指针字段外,还包括学生的姓名、学号、成绩,则其链表如下图所示:

技术图片

如果是这种链表,我们可以先定义一个Student类,里面包括姓名、学号、成绩,然后Node节点里面使用泛型Node<Student>。下面我们以学生为例讲解如何创建一个单向链表。

1、建立单向链表

现在我们使用C#语言的链表处理以下学生的成绩问题。

技术图片

首先我们必须声明节点的数据类型,让每一个节点包含一个数据,并且包含指向下一个节点的指针,使所有的数据都能被串在一起形成一个列表结构,最终链表如下图所示:

技术图片

下面我们详细说明建立上图所示的单向链表的步骤:

1、建立一个新的节点,如图所示:

技术图片

2、这时链表是空的,所以讲链表的first即last指针字段都指向新创建的节点newNode,如图所示:

技术图片

3、建立另外一个新的节点,如图所示:

技术图片

4、将上面的两个节点串起来,使用下面的代码:

last.next=newNode;
last=newNode;

如图所示:

技术图片

5、重复上面的3、4步骤,将所有的节点都连接起来,最终链表结构如图所示:

技术图片

由于列表中所有节点都知道节点本身的下一个节点在哪里,但是对于前一个节点却没有办法知道,所以“头节点”就显得非常重要。

无论如何,只要有头节点存在,就可以对整个列表进行遍历、加入、删除、查找等操作。而之前建立的节点若没有串接起来就会形成无人管理的节点,并一直占用内存空间。因此在建立列表时必须有一个列表指针指向头节点,并且在没有必要的情况下不可以移动列表首指针。

我们可以在程序中会声明Node类和SignleLinkedList类,在SignleLinkedList类中,定义了两个Node类型的节点指针,分别指向链表的第一个节点和最后一个节点。另外,该类中还需要声明下面的两个方法:

方法名称 功能描述
public bool IsEmpty() 用来判断当前的链表是否为空链表
public void Add(T item) 用来将指定的节点插入到当前的链表

下面我们以一个具体的例子来讲解如何创建一个单向链表。需求如下:

设计一个C#程序,可以让用户输入数据来添加学生数据节点,以建立一个单向链表。一共输入5位学生的成绩来建立单向链表,然后遍历单向链表中的每一个节点来打印输出学生的信息。

我们先建立Node节点类,这里使用泛型,利于扩展:

namespace SingleLinkedListDemo
{
    /// <summary>
    /// 链表节点类
    /// </summary>
    public class Node<T>
    {
        /// <summary>
        /// 数据字段
        /// </summary>
        public T Data { get; set; }

        /// <summary>
        /// 指针 指向下一个元素
        /// </summary>
        public Node<T> Next { get; set; }

        /// <summary>
        /// 无参构造函数
        /// </summary>
        public Node()
        {
            // 赋默认值
            this.Data = default(T);
            this.Next = null;
        }

        /// <summary>
        /// 只传递数据字段的构造函数,指针默认为null
        /// </summary>
        /// <param name="value"></param>
        public Node(T value)
        {
            this.Data = value;
            this.Next = null;
        }

        /// <summary>
        /// 同时传递数据和指针的构造函数
        /// </summary>
        /// <param name="value"></param>
        /// <param name="next"></param>
        public Node(T value,Node<T> next)
        {
            this.Data = value;
            this.Next = next;
        }

        /// <summary>
        /// 只传递指针的构造函数
        /// </summary>
        /// <param name="next"></param>
        public Node(Node<T> next)
        {
            this.Next = next;
        }
    }
}

我们创建一个Student类,用来存放学生信息:

namespace SingleLinkedListDemo
{
    /// <summary>
    /// 学生类
    /// </summary>
    public class Student
    {
        /// <summary>
        /// 学号
        /// </summary>
        public int Number { get; set; }

        /// <summary>
        /// 姓名
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 成绩
        /// </summary>
        public int Score { get; set; }

        public Student(int number,string name,int score)
        {
            Number = number;
            Name = name;
            Score = score;
        }
    }
}

最后创建SignleLinkedList类,代码如下:

using System.Collections.Generic;

namespace SingleLinkedListDemo
{
    /// <summary>
    /// 单向链表类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class SingleLinkedList<T>
    {
        /// <summary>
        /// 存放所有链表节点的集合
        /// </summary>
        public List<Node<T>> ListNode { get; set; }

        /// <summary>
        /// 构造函数
        /// </summary>
        public SingleLinkedList()
        {
            ListNode = new List<Node<T>>();
        }

        /// <summary>
        /// 头节点
        /// </summary>
        private Node<T> HeadNode;

        /// <summary>
        /// 尾节点
        /// </summary>
        private Node<T> LastNode;

        /// <summary>
        /// 判断当前链表是否为空链表
        /// </summary>
        /// <returns></returns>
        public bool IsEmpty()
        {
            return HeadNode == null;
        }

        /// <summary>
        /// 插入节点
        /// </summary>
        public void AddNode(T item)
        {
            // 新建一个节点
            Node<T> newNode = new Node<T>(item);
           
            // 判断头节点是否为null,如果为null,那么新建的节点就是头节点,同时也是尾节点
            if (IsEmpty())
            {
                // 如果是空链表,则将头节点和尾节点都指向新建的节点
                HeadNode = newNode;
                LastNode = newNode;
            }
            else
            {
                // 尾节点的指针指向新建的节点
                // 新建的节点变为尾节点
                LastNode.Next = newNode;
                LastNode = newNode;
            }
            // 将新建的节点添加到集合中
            ListNode.Add(newNode);
        }
    }
}

在Main方法里面调用:

using System;
using System.Collections.Generic;

namespace SingleLinkedListDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            int num;
            string name;
            int score;

            Console.WriteLine("请输入5位学生的成绩:");
            SingleLinkedList<Student> linkedList = new SingleLinkedList<Student>();
            for (int i = 0; i < 5; i++)
            {
                Console.Write("请输入学号:");
                num = int.Parse(Console.ReadLine());
                Console.Write("请输入姓名:");
                name = Console.ReadLine();
                Console.Write("请输入成绩:");
                score = int.Parse(Console.ReadLine());
                Student student = new Student(number: num, name: name, score: score);
                linkedList.AddNode(student);
                Console.WriteLine("----------------");
            }

            Console.WriteLine();
            Console.WriteLine("输出学生成绩信息");
            List<Node<Student>> list = linkedList.ListNode;
            foreach (var item in list)
            {
                Console.WriteLine($"学号: {item.Data.Number},姓名: {item.Data.Name},成绩: {item.Data.Score}");
                Console.WriteLine();
            }

            Console.ReadKey();
        }
    }
}

程序运行结果:

技术图片

2、单向链表节点的删除

在单向链表类型的数据结构中,若要在链表中删除一个节点,则根据所删除节点的位置会有以下三种不同的情况。

1、删除链表的第一个节点

如果是删除链表中的第一个节点,只要把链表的头指针指向第二个节点即可,如图所示:

技术图片

程序参考代码:

if(first.data == delNode.data)
    first=first.next;

2、删除链表内的中间节点

如果是删除链表内的中间节点,那么只要将删除节点的前一个节点的指针,指向要删除节点的下一个节点即可,如图所示:

技术图片

 程序参考代码:

3、删除链表的最后一个节点

如果是删除链表的最后一个节点,那么只要将指向最后一个节点的指针,直接指向null即可,如图所示:

技术图片

程序参考代码

我们还是以上面的例子进行讲解在链表中删除节点。输入学号,如果学号存在,则在链表中删除,然后打印出当前链表中的节点。如果学号不存在,则给出提示信息。要结束输入时,请输入“-1”,此时打印出链表中的节点信息。

这时上面创建的泛型类就不符合需求了,我们重新创建一个节点类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SingleLinkedListDemo
{
    /// <summary>
    /// 演示删除节点使用的节点类
    /// </summary>
    public class StudentNode
    {
        /// <summary>
        /// 学号
        /// </summary>
        public int Number { get; set; }

        /// <summary>
        /// 姓名
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 成绩
        /// </summary>
        public int Score { get; set; }

        /// <summary>
        /// 指针 指向下一个元素
        /// </summary>
        public StudentNode Next { get; set; }

        public StudentNode(int number,string name,int score)
        {
            Number = number;
            Name = name;
            Score = score;
        }
    }
}

链表类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SingleLinkedListDemo
{
    public class StudentLinkedList
    {

        public List<StudentNode> ListNode { get; set; }


        public StudentLinkedList()
        {
            ListNode = new List<StudentNode>();
        }


        /// <summary>
        /// 头节点
        /// </summary>
        public StudentNode HeadNode;

        /// <summary>
        /// 尾节点
        /// </summary>
        public StudentNode LastNode;

        /// <summary>
        /// 判断当前链表是否为空链表
        /// </summary>
        /// <returns></returns>
        public bool IsEmpty()
        {
            return HeadNode == null;
        }

        /// <summary>
        /// 添加节点
        /// </summary>
        /// <param name="node"></param>
        public void AddNode(StudentNode node)
        {
            StudentNode newNode = node;
            // 判断头节点是否为null,如果为null,那么新建的节点就是头节点,同时也是尾节点
            if (IsEmpty())
            {
                // 如果是空链表,则将头节点和尾节点都指向新建的节点
                HeadNode = newNode;
                LastNode = newNode;
            }
            else
            {
                // 尾节点的指针指向新建的节点
                // 新建的节点变为尾节点
                LastNode.Next = newNode;
                LastNode = newNode;
            }
            // 将新建的节点添加到集合中
            ListNode.Add(newNode);
        }

        /// <summary>
        /// 打印
        /// </summary>
        public void Print()
        {
            StudentNode current = HeadNode;
            while (current != null)
            {
                Console.WriteLine("[" + current.Number + " " + current.Name + " " + current.Score + "]");
                current = current.Next;
            }
            Console.WriteLine();
        }

        /// <summary>
        /// 删除节点
        /// </summary>
        /// <param name="delNode"></param>
        public void DeleteNode(StudentNode delNode)
        {
            StudentNode newNode;
            StudentNode tmpNode;

            // 如果删除的是第一个节点
            if(HeadNode.Number==delNode.Number)
            {
                // 头指针指向第二个节点
                HeadNode = HeadNode.Next;
            }
            else if(LastNode.Number==delNode.Number)
            {
                // 删除的是最后一个节点
                newNode = HeadNode;
                // 循环找到最后一个节点的前一个节点
                // 当退出循环的时候newNode就是最后一个节点的前一个节点
                while(newNode.Next!=LastNode)
                {
                    // 指针后移,指向下一个节点
                    newNode = newNode.Next;
                }
                // 最后一个节点的前一个节点的next赋值为null
                newNode.Next = null;
                LastNode = newNode;
            }
            else
            {
                // 删除的是中间的节点
                newNode = HeadNode;
                tmpNode = HeadNode;
                // 循环找到要删除的节点
                // 循环退出时tmpNode节点就是要删除节点的前一个节点,newNode节点就是要删除的节点
                while(newNode.Number!=delNode.Number)
                {
                    tmpNode = newNode;
                    // 后移,指向下一个节点
                    newNode = newNode.Next;
                }
                // 要删除节点的前一个节点的next指向删除节点的下一个节点
                tmpNode.Next = newNode.Next;
            }
        }

    }
}

Main方法里面调用:

using System;
using System.Collections.Generic;

namespace SingleLinkedListDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            #region 创建一个单向链表
            //int num;
            //string name;
            //int score;

            //Console.WriteLine("请输入5位学生的成绩:");
            //SingleLinkedList<Student> linkedList = new SingleLinkedList<Student>();
            //for (int i = 0; i < 5; i++)
            //{
            //    Console.Write("请输入学号:");
            //    num = int.Parse(Console.ReadLine());
            //    Console.Write("请输入姓名:");
            //    name = Console.ReadLine();
            //    Console.Write("请输入成绩:");
            //    score = int.Parse(Console.ReadLine());
            //    Student student = new Student(number: num, name: name, score: score);
            //    linkedList.AddNode(student);
            //    Console.WriteLine("----------------");
            //}

            //Console.WriteLine();
            //Console.WriteLine("输出学生成绩信息");
            //List<Node<Student>> list = linkedList.ListNode;
            //foreach (var item in list)
            //{
            //    Console.WriteLine($"学号: {item.Data.Number},姓名: {item.Data.Name},成绩: {item.Data.Score}");
            //    Console.WriteLine();
            //} 
            #endregion

            #region 删除单向链表中的节点
            Random rand = new Random();
            StudentLinkedList list = new StudentLinkedList();
            int i, j, findword = 0;
            int[,] data = new int[12, 10];
            String[] name = new String[] { "Allen", "Scott",
                "Marry", "Jon", "Mark", "Ricky", "Lisa",
                "Jasica", "Hanson", "Amy", "Bob", "Jack" };
            Console.WriteLine("学号 成绩  学号 成绩  学号 成绩  学号  成绩
 ");
            // 链表里面添加12个节点
            for (i = 0; i < 12; i++)
            {
                data[i, 0] = i + 1;
                data[i, 1] = (Math.Abs(rand.Next(50))) + 50;
                StudentNode node = new StudentNode(data[i, 0], name[i], data[i, 1]);
                list.AddNode(node);
            }
            // 分三行输出
            for (i = 0; i < 3; i++)
            {
                for (j = 0; j < 4; j++)
                    Console.Write("[" + data[j * 3 + i, 0] + "]  [" + data[j * 3 + i, 1] + "]  ");
                Console.WriteLine();
            }
            while (true)
            {
                Console.Write("请输入要删除成绩的学生学号,结束输入-1: ");
                findword = int.Parse(Console.ReadLine());
                if (findword == -1)
                    break;
                else
                {
                    StudentNode current = new StudentNode(list.HeadNode.Number, list.HeadNode.Name, list.HeadNode.Score);
                    current.Next = list.HeadNode.Next;
                    while (current.Number != findword) current = current.Next;
                    list.DeleteNode(current);
                }
                Console.WriteLine("删除后成绩的链表,请注意!要删除的成绩其学生的学号必须在此链表中
");
                list.Print();
            }
            #endregion

            Console.ReadKey();
        }
    }
}

程序运行结果:

技术图片

3、单向链表插入新节点

在单向链表中插入新节点,如同一列火车中加入新的车厢,有三种情况:加到第一个节点之前、加到最后一个节点之后以及加到此链表中间任一位置。

1、新节点插入第一个节点之前

将新节点插入到第一个节点之前,新节点即成为此链表的首节点,只需要把新节点的指针指向链表原来的第一个节点,再把链表头指针指向新节点即可,如图所示:

技术图片

2、新节点插入最后一个节点之后

将新节点插入到最后一个节点之后,只需要把链表的最后一个节点的指针指向新节点,新节点的指针在指向null即可,如图所示:

技术图片

3、新节点插入链表中间位置

例如插入的节点是在X和Y之间,只需要将X节点的指针指向新节点,如图所示:

技术图片

然后将新节点的指针指向Y节点即可,如图所示:

技术图片

下面我们以泛型Node类为例,讲解如何插入节点

using System;
using System.Collections.Generic;

namespace SingleLinkedListDemo
{
    /// <summary>
    /// 单向链表类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class SingleLinkedList<T>
    {
        /// <summary>
        /// 存放所有链表节点的集合
        /// </summary>
        public List<Node<T>> ListNode { get; set; }

        /// <summary>
        /// 构造函数
        /// </summary>
        public SingleLinkedList()
        {
            ListNode = new List<Node<T>>();
        }

        /// <summary>
        /// 头节点
        /// </summary>
        private Node<T> HeadNode;

        /// <summary>
        /// 尾节点
        /// </summary>
        private Node<T> LastNode;

        /// <summary>
        /// 判断当前链表是否为空链表
        /// </summary>
        /// <returns></returns>
        public bool IsEmpty()
        {
            return HeadNode == null;
        }

        /// <summary>
        /// 新增节点
        /// </summary>
        public void AddNode(T item)
        {
            // 新建一个节点
            Node<T> newNode = new Node<T>(item);
           
            // 判断头节点是否为null,如果为null,那么新建的节点就是头节点,同时也是尾节点
            if (IsEmpty())
            {
                // 如果是空链表,则将头节点和尾节点都指向新建的节点
                HeadNode = newNode;
                LastNode = newNode;
            }
            else
            {
                // 尾节点的指针指向新建的节点
                // 新建的节点变为尾节点
                LastNode.Next = newNode;
                LastNode = newNode;
            }
            // 将新建的节点添加到集合中
            ListNode.Add(newNode);
        }

        /// <summary>
        /// 插入节点
        /// </summary>
        /// <param name="item">要插入的节点的值</param>
        /// <param name="index">要插入节点的位置</param>
        public void InsertNode(T item,int index)
        {
            // 创建新的节点
            Node<T> newNode = new Node<T>(item);
            //Node<T> tmpNode = new Node<T>(item);

            // 判断当前链表是否为空链表
            if(IsEmpty())
            {
                HeadNode = newNode;
                LastNode = newNode;
            }
            else
            {
                // 插入第一个节点
                if(index==0)
                {
                    // 新节点执行现在的头节点
                    newNode.Next = HeadNode;
                    // 新节点变为新的头节点
                    HeadNode = newNode;
                }
                else if(index==GetLinkedListLength()-1)
                {
                    // 插入尾节点
                    // 定义一个临时节点tempNode指向HeadNode
                    Node<T> tempNode = HeadNode;
                    // 循环找到尾节点
                    while(true)
                    {
                        // 如果tempNode的next不为null,说明当前节点不是尾节点,则后移
                        if(tempNode.Next!=null)
                        {
                            // 当前tempNode后移
                            tempNode = tempNode.Next;
                        }
                        else
                        {
                            // tempNode的next为null,说明tempNode节点是尾节点,则退出循环
                            break;
                        }
                    }
                    // tempNode是尾节点,则将尾节点的next指向新的节点
                    tempNode.Next = newNode;
                }
                else
                {
                    #region 插入中间位置
                    // 定义临时节点指向头节点
                    Node<T> tempNode = HeadNode;
                    // 经过index-1次循环后移,tempNode移动到要插入位置的前一个节点
                    for (int i = 0; i <=index-1; i++)
                    {
                        // tempNode节点每次后移一个位置
                        tempNode = tempNode.Next;
                    }
                    // 要插入位置的前一个节点
                    Node<T> preNode = tempNode;
                    // 要插入位置的节点
                    Node<T> currentNode = preNode.Next;
                    // 修改next指向,前一个节点指向新节点
                    preNode.Next = newNode;
                    // 新节点指向当前位置的节点
                    newNode.Next = currentNode;
                    #endregion
                }
            }
        }

        /// <summary>
        /// 获取链表长度
        /// </summary>
        /// <returns></returns>
        public int GetLinkedListLength()
        {
            // 长度
            int length = 0;
            if(HeadNode==null)
            {
                length = 0;
            }
            else
            {
                Node<T> tempNode = HeadNode;
                // 循环
                while(true)
                {
                    if(tempNode.Next!=null)
                    {
                        // 当前临时节点后移到下一个节点
                        tempNode = tempNode.Next;
                        // 长度自增
                        length++;
                    }
                    else
                    {
                        // 说明循环到了尾节点,退出循环
                        length++;
                        break;
                    }
                }
            }
            return length;
        }

        /// <summary>
        /// 打印
        /// </summary>
        public void Print()
        {
            //StudentNode current = HeadNode;
            //while (current != null)
            //{
            //    Console.WriteLine("[" + current.Number + " " + current.Name + " " + current.Score + "]");
            //    current = current.Next;
            //}

            Node<T> current = HeadNode;
            while (current != null)
            {
                Console.Write( current.Data+"  ");
                current = current.Next;
            }
            Console.WriteLine();
        }
    }
}

Main方法中调用:

using System;
using System.Collections.Generic;

namespace SingleLinkedListDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            #region 创建一个单向链表
            //int num;
            //string name;
            //int score;

            //Console.WriteLine("请输入5位学生的成绩:");
            //SingleLinkedList<Student> linkedList = new SingleLinkedList<Student>();
            //for (int i = 0; i < 5; i++)
            //{
            //    Console.Write("请输入学号:");
            //    num = int.Parse(Console.ReadLine());
            //    Console.Write("请输入姓名:");
            //    name = Console.ReadLine();
            //    Console.Write("请输入成绩:");
            //    score = int.Parse(Console.ReadLine());
            //    Student student = new Student(number: num, name: name, score: score);
            //    linkedList.AddNode(student);
            //    Console.WriteLine("----------------");
            //}

            //Console.WriteLine();
            //Console.WriteLine("输出学生成绩信息");
            //List<Node<Student>> list = linkedList.ListNode;
            //foreach (var item in list)
            //{
            //    Console.WriteLine($"学号: {item.Data.Number},姓名: {item.Data.Name},成绩: {item.Data.Score}");
            //    Console.WriteLine();
            //} 
            #endregion

            #region 删除单向链表中的节点
            //Random rand = new Random();
            //StudentLinkedList list = new StudentLinkedList();
            //int i, j, findword = 0;
            //int[,] data = new int[12, 10];
            //String[] name = new String[] { "Allen", "Scott",
            //    "Marry", "Jon", "Mark", "Ricky", "Lisa",
            //    "Jasica", "Hanson", "Amy", "Bob", "Jack" };
            //Console.WriteLine("学号 成绩  学号 成绩  学号 成绩  学号  成绩");
            //// 链表里面添加12个节点
            //for (i = 0; i < 12; i++)
            //{
            //    data[i, 0] = i + 1;
            //    data[i, 1] = (Math.Abs(rand.Next(50))) + 50;
            //    StudentNode node = new StudentNode(data[i, 0], name[i], data[i, 1]);
            //    list.AddNode(node);
            //}
            //// 分三行输出
            //for (i = 0; i < 3; i++)
            //{
            //    for (j = 0; j < 4; j++)
            //        Console.Write("[" + data[j * 3 + i, 0] + "]  [" + data[j * 3 + i, 1] + "]  ");
            //    Console.WriteLine();
            //}
            //while (true)
            //{
            //    Console.Write("请输入要删除成绩的学生学号,结束输入-1: ");
            //    findword = int.Parse(Console.ReadLine());
            //    if (findword == -1)
            //        break;
            //    else
            //    {
            //        StudentNode current = new StudentNode(list.HeadNode.Number, list.HeadNode.Name, list.HeadNode.Score);
            //        current.Next = list.HeadNode.Next;
            //        while (current.Number != findword) current = current.Next;
            //        list.DeleteNode(current);
            //    }
            //    Console.WriteLine("删除后成绩的链表,请注意!要删除的成绩其学生的学号必须在此链表中
");
            //    list.Print();
            //}
            #endregion

            #region 单向链表中插入节点
            SingleLinkedList<int> linkedList = new SingleLinkedList<int>();
            linkedList.AddNode(1);
            linkedList.AddNode(45);
            linkedList.AddNode(56);
            linkedList.AddNode(389);
            List<Node<int>> list = linkedList.ListNode;
            Console.WriteLine("插入前链表元素");
            linkedList.Print();
            Console.WriteLine();
            // 插入头节点之前
            linkedList.InsertNode(57, 0);
            Console.WriteLine("插入头节点后链表元素");
            linkedList.Print();
            Console.WriteLine();
            // 插入尾节点之后
            linkedList.InsertNode(123, linkedList.GetLinkedListLength()-1);
            Console.WriteLine("插入尾节点后链表元素");
            linkedList.Print();
            Console.WriteLine();
            // 插入中间节点
            int index= new Random().Next(0, linkedList.GetLinkedListLength() - 1);
            linkedList.InsertNode(935, index);
            Console.WriteLine("插入中间节点后链表元素");
            linkedList.Print();
            Console.WriteLine();
            #endregion
            Console.ReadKey();
        }
    }
}

程序运行结果:

技术图片

GitHub地址:git@github.com:JiangXiaoLiang1988/SingleLinkedList.git

以上是关于链表:单向链表的主要内容,如果未能解决你的问题,请参考以下文章

链表的java实现(单向双向链表,单向链表的反转)

单向链表JAVA代码

C提高 7   单向链表,传统链表,通用链表,linus天才哲学代码

数据结构单向链表及其Java代码实现

数据结构《二》链表的实现

java实现单向链表