C#单向链表和双向链表(1)

C#中 类 System.Collections.Generic.LinkedList<T> 代表双向链表,默认并没有定义单向链表。当然:双向链表可以实现单向链表的所有功能。

双向链表LinkedList<T>的C#源代码地址:

https://referencesource.microsoft.com/#System/compmod/system/collections/generic/linkedlist.cs,baf7f8812f420a83

单向链表SingleLinkedList 如图:

单向循环链表CircularSingleLinkedList

双向链表DoubleLinkedList

双向循环链表CircularDoubleLinkedList

 

新建控制台应用程序LinkedListDemo:

 

新建节点类SingleLinkedNode

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

namespace LinkedListDemo
{
    /// <summary>
    /// 表示单向链表的一个节点
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class SingleLinkedNode<T>
    {
        /// <summary>
        /// 初始化一个节点
        /// </summary>
        public SingleLinkedNode() 
        {
            this.Next = null;
        }
        /// <summary>
        /// 初始化一个节点,使用指定的节点值
        /// </summary>
        /// <param name="value"></param>
        public SingleLinkedNode(T value)
        {
            this.Value = value;
        }

        /// <summary>
        /// 当前节点对应的值
        /// </summary>
        public T Value { get; set; }

        /// <summary>
        /// 当前节点的下一个节点
        /// </summary>
        public SingleLinkedNode<T> Next { get; set; }

        /// <summary>
        /// 显示节点和以后节点
        /// </summary>
        public void Show()
        {
            SingleLinkedNode<T> node = this;
            while (node != null)
            {
                Console.Write(node.Value);
                node = node.Next;
                if (node != null) 
                {
                    Console.Write("--->");
                }
            }
            Console.WriteLine();
        }        
    }
}

新建单向链表类SingleLinkedList

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

namespace LinkedListDemo
{
    /// <summary>
    /// 单向链表,为了方便遍历,实现IEnumerable(可枚举)接口。
    /// 同时方便排序,因此T限制为必须是实现IComparable(可比较)接口。
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class SingleLinkedList<T> : IEnumerable<T> where T : IComparable
    {
        /// <summary>
        /// 初始化一个空的单向链表
        /// </summary>
        public SingleLinkedList()
        {
            this.Head = new SingleLinkedNode<T>();
        }

        /// <summary>
        /// 使用一个节点来初始化单向链表
        /// </summary>
        /// <param name="next"></param>
        public SingleLinkedList(SingleLinkedNode<T> next) : this()
        {
            this.Head.Next = next;
        }

        /// <summary>
        /// 使用连续数据来初始化单向链表
        /// </summary>
        /// <param name="itemArray"></param>
        public SingleLinkedList(T[] itemArray) : this()
        {
            SingleLinkedNode<T> current = Head;
            SingleLinkedNode<T> next;
            for (int i = 0; i < itemArray.Length; i++)
            {
                next = new SingleLinkedNode<T>(itemArray[i]);
                //当前节点的下一个节点为新的节点
                current.Next = next;
                //指针偏移到新节点
                current = next;
            }
        }

        /// <summary>
        /// 表示单向链表的头节点
        /// </summary>
        public SingleLinkedNode<T> Head { get; set; }

        /// <summary>
        /// 获取链表的长度:节点个数
        /// </summary>
        public int Count
        {
            get
            {
                int n = 0;
                SingleLinkedNode<T> node = Head.Next;
                while (node != null)
                {
                    n++;
                    node = node.Next;
                }
                return n;
            }
        }

        /// <summary>
        /// 获取链表是否为空
        /// </summary>
        public bool IsEmpty
        {
            get
            {
                return Head.Next == null;
            }
        }

        /// <summary>
        /// 索引器:获得或者设置指定索引处的链表元素
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public T this[int index]
        {
            get
            {
                if (index < 0 || index > Count)
                {
                    throw new IndexOutOfRangeException("索引越界异常");
                }
                int n = 0;
                SingleLinkedNode<T> node = Head.Next;
                while (node != null)
                {
                    if (index == n)
                    {
                        break;
                    }
                    node = node.Next;
                    n++;
                }
                if (node == null)
                {
                    throw new IndexOutOfRangeException("已经找到链表的尾部,仍未找到该索引对应的元素");
                }
                return node.Value;
            }
            set
            {
                if (index < 0 || index > Count)
                {
                    throw new IndexOutOfRangeException("索引越界异常");
                }
                int n = 0;
                SingleLinkedNode<T> node = Head.Next;
                while (node != null)
                {
                    if (index == n)
                    {
                        break;
                    }
                    node = node.Next;
                    n++;
                }
                if (node == null)
                {
                    throw new IndexOutOfRangeException("已经找到链表的尾部,仍未找到该索引对应的元素");
                }
                node.Value = value;
            }
        }

        /// <summary>
        /// 将单向链表转化为一个T类型的数组
        /// </summary>
        /// <returns></returns>
        public T[] ToArray()
        {
            T[] array = new T[Count];
            int n = 0;
            SingleLinkedNode<T> node = Head.Next;
            while (node != null)
            {
                array[n] = node.Value;
                n++;
                node = node.Next;
            }
            return array;
        }

        #region 插入或删除单向链表的节点
        /// <summary>
        /// 在链表的尾部增加一个元素
        /// </summary>
        /// <param name="value"></param>
        public void Add(T value)
        {
            SingleLinkedNode<T> node = Head;
            //如果链表的下一个节点为null,则循环终止
            while (node != null && node.Next != null)
            {
                node = node.Next;
            }
            SingleLinkedNode<T> insertNode = new SingleLinkedNode<T>(value);
            node.Next = insertNode;
        }

        /// <summary>
        /// 在指定的索引处添加一个链表节点
        /// </summary>
        /// <param name="index"></param>
        /// <param name="value"></param>
        public void Insert(int index, T value)
        {
            if (index < 0 || index > Count)
            {
                throw new ArgumentOutOfRangeException("索引越界异常");
            }
            int n = 0;
            SingleLinkedNode<T> node = Head;
            while (node != null)
            {
                if (index == n)
                {
                    break;
                }
                n++;
                node = node.Next;
            }
            //需要插入的节点
            SingleLinkedNode<T> insertNode = new SingleLinkedNode<T>(value);
            insertNode.Next = node.Next;//需要插入的节点的下一个节点是 【指定索引处的原节点的下一个节点】
            node.Next = insertNode;//原节点的下一个节点 就是 当前插入的节点
        }

        /// <summary>
        /// 在指定的索引处添加一个链表节点集合
        /// </summary>
        /// <param name="index"></param>
        /// <param name="itemArray"></param>
        public void InsertRange(int index, T[] itemArray)
        {
            if (index < 0 || index > Count)
            {
                throw new ArgumentOutOfRangeException("索引越界异常");
            }
            int n = 0;
            SingleLinkedNode<T> node = Head;
            while (node != null)
            {
                if (index == n)
                {
                    break;
                }
                n++;
                node = node.Next;
            }
            //记录找到索引处的节点的下一个节点
            SingleLinkedNode<T> tempNode = node.Next;
            //需要插入的节点
            SingleLinkedNode<T> insertNode = null;
            for (int i = 0; i < itemArray.Length; i++)
            {
                insertNode = new SingleLinkedNode<T>(itemArray[i]);
                //当前节点的下一个节点为新的节点
                node.Next = insertNode;
                //指针偏移到新节点
                node = insertNode;
            }
            node.Next = tempNode;//需要插入的节点的下一个节点是 【指定索引处的原节点的下一个节点】            
        }

        /// <summary>
        /// 移除指定值的第一个节点
        /// </summary>
        /// <param name="value"></param>
        public void Remove(T value)
        {
            //是否已查找到指定值的节点
            bool findNodeResult = false;
            int n = 0;
            SingleLinkedNode<T> node = Head;
            SingleLinkedNode<T> frontNode = null;
            while (node != null)
            {
                if (value.CompareTo(node.Value) == 0)
                {
                    findNodeResult = true;
                    break;
                }
                n++;
                frontNode = node;//记录指定值的上一个节点
                node = node.Next;
            }
            if (!findNodeResult)
            {
                //如果没有找到指定值的节点,则什么也不做
                return;
            }
            //如果上一个节点为null,说明是移除头节点,指定第二个节点作为头节点
            if (frontNode == null)
            {
                Head = node.Next;
            }
            else //如果上一个节点不为null,则上一个节点的下一个直接指定为【指定值的节点的下一个节点】
            {
                frontNode.Next = node.Next;
            }
        }

        /// <summary>
        /// 移除指定索引的项
        /// </summary>
        /// <param name="index"></param>
        public void RemoveAt(int index)
        {
            if (index < 0 || index >= Count)
            {
                throw new ArgumentOutOfRangeException("索引越界异常");
            }
            int n = 0;
            SingleLinkedNode<T> node = Head.Next;
            SingleLinkedNode<T> frontNode = null;
            while (node != null)
            {
                if (n == index)
                {
                    break;
                }
                n++;
                frontNode = node;//记录指定值的上一个节点
                node = node.Next;
            }
            //如果上一个节点为null,说明是移除头节点,指定第二个节点作为头节点
            if (frontNode == null)
            {
                Head = node.Next;
            }
            else
            {
                frontNode.Next = node.Next;
            }
        }
        #endregion

        /// <summary>
        /// 反转链表
        /// </summary>
        public SingleLinkedList<T> Reverse()
        {
            T[] itemArray = ToArray();
            Array.Reverse(itemArray);
            return new SingleLinkedList<T>(itemArray);
        }

        /// <summary>
        /// 链表按照节点的值从小到大重新排序
        /// </summary>
        public SingleLinkedList<T> Sort()
        {
            //转化成数组重新排序
            T[] itemArray = ToArray();
            Array.Sort(itemArray);
            //this.Head = new SingleLinkedNode<T>();
            //SingleLinkedNode<T> current = Head;
            //SingleLinkedNode<T> next;
            //for (int i = 0; i < itemArray.Length; i++)
            //{
            //    next = new SingleLinkedNode<T>(itemArray[i]);
            //    //当前节点的下一个节点为新的节点
            //    current.Next = next;
            //    //指针偏移到新节点
            //    current = next;
            //}

            //重新实例化
            return new SingleLinkedList<T>(itemArray);
        }

        #region 实现IEnumerable接口,用于迭代Foreach
        /// <summary>
        /// 可以对接口进行Foreach遍历,迭代
        /// </summary>
        /// <returns></returns>
        public IEnumerator<T> GetEnumerator()
        {
            SingleLinkedNode<T> node = Head.Next;
            while (node != null)
            {
                yield return node.Value;
                node = node.Next;
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }
        #endregion
    }
}

测试单项链表:

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

namespace LinkedListDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            SingleLinkedList<int> linkedList = new SingleLinkedList<int>(new int[] { 1, 2, 3 });
            Console.WriteLine(string.Join("-->", linkedList));
            linkedList.Add(5);
            Console.WriteLine(string.Join("-->", linkedList));
            linkedList.Insert(3, 4);
            Console.WriteLine(string.Join("-->", linkedList));
            linkedList.RemoveAt(2);
            Console.WriteLine(string.Join("-->", linkedList));
            linkedList.Add(3);
            Console.WriteLine(string.Join("-->", linkedList));
            linkedList = linkedList.Reverse();
            Console.WriteLine(string.Join("-->", linkedList));
            linkedList = linkedList.Sort();
            Console.WriteLine(string.Join("-->", linkedList));
            Console.ReadLine();
        }
    }
}

测试运行如图:

猜你喜欢

转载自blog.csdn.net/ylq1045/article/details/112912841
今日推荐