• 链表(二):单向链表


    一、什么是单向链表

    在动态分配内存空间时,最常使用的就是“单向链表”(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

  • 相关阅读:
    常用 SQL 语句
    Matalab IFS分形算法
    波粒二象性
    动态下载 Yahoo 网络数据存入 Microsoft SQL Server 再 Matlab 调用的一个完整例子
    4.交易测试
    协议 protocol
    iOS开发使用半透明模糊效果方法整理
    iOS App集成Apple Pay教程(附示例代码)
    iOS中四种实例变量的范围类型@private@protected@public@package
    隐藏TabBar的一些方法小结(适用与各种情况)
  • 原文地址:https://www.cnblogs.com/dotnet261010/p/12312376.html
Copyright © 2020-2023  润新知