链表

逻辑上相邻,物理上不一定相邻

头结点

1.统一首节点和其他节点插入,删除操作
2.防止链表空

分类

单链表,双链表,循环链表

单链表实现

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace DataStruct.List
{
    /// <summary>
    /// 链表节点
    /// </summary>
    /// <typeparam name="T">数据类型</typeparam>
    class Node<T>
    {
        /// <summary>
        /// 数据域
        /// </summary>
        public T Data { get; set; }
        /// <summary>
        /// 引用域
        /// </summary>
        public Node<T> Next {get;set;}
        /// <summary>
        /// 构造器
        /// </summary>
        public Node(){}
        /// <summary>
        /// 节点构造器
        /// </summary>
        /// <param name="data">数据域</param>
        /// <param name="next">引用域</param>
        public Node(T data,Node<T> next=null)
        {
            this.Data = data;
            this.Next = next;
        }
        /// <summary>
        /// 覆盖ToString方法
        /// </summary>
        /// <returns>返回字符串</returns>
        public override string ToString()
        {
            if (this.Next!=null)
                return this.Data + "->";
            else
                return this.Data + "^";
        }
    }
    /// <summary>
    /// 链表辅助工具类
    /// </summary>
    /// <typeparam name="T">数据类型</typeparam>
    static class LinkListUtil<T>
    {
        /// <summary>
        /// 判断链表成环
        /// </summary>
        /// <param name="head">头结点</param>
        /// <returns>返回是否成环</returns>
        public static bool HasCycle(Node<T> head)
        {
            if (head == null || head.Next == null)
                return false;
            Node<T> p = head;
            Node<T> q = head;
            while(q!=null&&q.Next!=null)
            {
                p = p.Next;
                q = q.Next.Next;
            }
            return false;
        }
    }
    /// <summary>
    /// 单链表
    /// </summary>
    /// <typeparam name="T">数据类型</typeparam>
    class LinkList<T> : IList<T>, IEnumerable<T>
        where T:IComparable<T>
    {

        /// <summary>
        /// 获取头结点
        /// </summary>
        public Node<T> Head { get; }
        /// <summary>
        /// 节点数量
        /// </summary>
        private int count;
        /// <summary>
        /// 构造器
        /// </summary>
        public LinkList()
        {
            this.Head = new Node<T>();
        }
        /// <summary>
        /// 构造器
        /// </summary>
        /// <param name="array">数组</param>
        public LinkList(params T[]array)
        {
            Node<T> p = this.Head = new Node<T>();
            foreach (var item in array)
            {
                Node<T> t = new Node<T>(item);
                p.Next = t;
                p = p.Next;
                this.count++;
            }
        }
        /// <summary>
        /// 构造器
        /// </summary>
        /// <param name="array">数组</param>
        /// <param name="reverse">是否使用尾插法</param>
        public LinkList(IEnumerable<T> array, bool reverse = false)
        {
            if(reverse)
            {
                this.Head = new Node<T>();
                foreach (var item in array)
                {
                    Node<T> t = new Node<T>(item,Head.Next);
                    Head.Next = t;
                    this.count++;
                }
            }
            else
            {
                Node<T> p = this.Head = new Node<T>();
                foreach (var item in array)
                {
                    Node<T> t = new Node<T>(item);
                    p.Next = t;
                    p = p.Next;
                    this.count++;
                }
            }
        }
        /// <summary>
        /// 检查索引
        /// </summary>
        /// <param name="index">索引</param>
        private void RaiseForIndex(ref int index)
        {
            if (index < 0)
                index += this.count;
            if (index < 0|| index >= count)
                throw new IndexOutOfRangeException("列表索引访问越界了");
        }
        /// <summary>
        /// 检查区间
        /// </summary>
        /// <param name="index">索引</param>
        private void RaiseForRange(ref int start, ref int end)
        {
            if (start < 0) start += count;
            if (end < 0) end += count;
            var cnt = end - start;
            if (start < 0 || end < 0 || cnt <= 0 || start >= count || end > count)
                throw new IndexOutOfRangeException("列表索引访问越界了");
        }
        /// <summary>
        /// 查找给定索引元素的前驱节点
        /// </summary>
        /// <param name="index">索引</param>
        /// <returns>返回节点</returns>
        public Node<T> FindPrevious(int index)
        {
            RaiseForIndex(ref index);
            int i = 0;
            Node<T> p = this.Head;
            while (i < index && p.Next != null)
            {
                p = p.Next;
                i++;
            }
            return p;
        }
        ///// <summary>
        ///// 返回倒数第index个元素的节点
        ///// </summary>
        ///// <param name="index">倒数第几</param>
        ///// <returns>返回该节点</returns>
        //public Node<T> FindLast(int index)
        //{
        //    if(index<=0)
        //        throw new IndexOutOfRangeException("索引访问越界");
        //    Node<T> p= this.Head;
        //    for (int i = 0; i < index; i++)
        //    {
        //        if (p.Next == null)
        //            throw new IndexOutOfRangeException("索引访问越界");
        //        p = p.Next;
        //    }
        //    Node<T> q = this.Head;
        //    while(p.Next!=null)
        //    {
        //        p = p.Next;
        //        q = q.Next;
        //    }
        //    return q.Next;
        //}


        /// <summary>
        /// 索引器
        /// </summary>
        /// <param name="index">索引值</param>
        /// <returns>返回对应数据</returns>
        public T this[int index]
        {
            get
            {
                return FindPrevious(index).Next.Data;
            }
            set
            {
                FindPrevious(index).Next.Data= value;
            }
        }
        /// <summary>
        /// 节点数量
        /// </summary>
        public int Count => this.count;

        /// <summary>
        /// 增加元素
        /// </summary>
        /// <param name="val">元素变量</param>
        public void Add(T val)
        {
            Node<T> p = this.Head;
            while (p.Next != null)
                p = p.Next;
            p.Next = new Node<T>(val,null);
            this.count++;
        }
        /// <summary>
        /// 清理
        /// </summary>
        public void Clear()
        {
            this.Head.Next = null;
            this.count = 0;
        }
        /// <summary>
        /// 查看数据在列表中的位置
        /// </summary>
        /// <param name="val">数据</param>
        /// <returns>返回索引</returns>
        public int? IndexOf(T val)
        {
            int i = 0;
            var p= this.Head;
            while(i<this.count)
            {
                p = p.Next;
                if (p.Data.CompareTo(val) == 0)
                    return i;
                i++;
            }
            return null;
        }
        /// <summary>
        /// 插入元素
        /// </summary>
        /// <param name="index">元素索引</param>
        /// <param name="val">插入元素值</param>
        public void Insert(int index, T val)
        {
            var p=this.FindPrevious(index);
            Node<T> temp = new Node<T>(val,p.Next);
            p.Next = temp;
            this.count++;
        }
        /// <summary>
        /// 判断列表是否包含某个元素
        /// </summary>
        /// <param name="val">元素</param>
        /// <returns>返回是否包含</returns>
        public bool IsContains(T val) => this.IndexOf(val) != null;
        /// <summary>
        /// 判空
        /// </summary>
        /// <returns>表是否为空</returns>
        public bool IsEmpty()=>this.Head.Next==null;
        /// <summary>
        /// 删除元素
        /// </summary>
        /// <param name="index">元素索引</param>
        /// <returns>返回要删除的元素</returns>
        public T Remove(int index)
        {
            var p = this.FindPrevious(index);
            var q = p.Next;
            var temp = q.Data;
            p.Next = q.Next;
            this.count--;
            return temp;
        }
        /// <summary>
        /// 覆盖ToString方法
        /// </summary>
        /// <returns>返回字符串</returns>
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("[");
            Node<T> p = this.Head;
            while(p.Next!=null)
            {
                p = p.Next;
                sb.Append(p);
            }
            sb.Append("]");
            return sb.ToString();
        }
        /// <summary>
        /// 转化为数组
        /// </summary>
        /// <returns>数组</returns>
        public T[] ToArray()
        {
            T[] array = new T[count];
            int i = 0;
            foreach (var item in this)
                array[i++] = item;
            return array;
        }
        /// <summary>
        /// 隐式类型转换
        /// </summary>
        /// <param name="array">顺序表</param>
        public static explicit operator LinkList<T>(SequenceList<T> ls)=>new LinkList<T>(ls.ToArray());
        /// <summary>
        /// 显式类型转换
        /// </summary>
        /// <param name="array">数组</param>
        public static implicit operator LinkList<T>(T[] array) => new LinkList<T>(array);
        /// <summary>
        /// 获取迭代器
        /// </summary>
        /// <returns>返回迭代器</returns>
        public IEnumerator<T> GetEnumerator()
        {
            var p = this.Head;
            while(p.Next!=null)
            {
                p = p.Next;
                yield return p.Data;
            }
        }
        /// <summary>
        /// 获取迭代器
        /// </summary>
        /// <returns>返回迭代器</returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            var p = this.Head;
            while (p.Next != null)
            {
                p = p.Next;
                yield return p.Data;
            }
        }

        /// <summary>
        /// 范围添加
        /// </summary>
        /// <param name="collection">可迭代集合</param>
        public void AddRange(IEnumerable<T> collection)
        {
            Node<T> p = this.FindPrevious(this.count-1).Next;
            foreach (var item in collection)
            {
                p.Next= new Node<T>(item, null);
                p = p.Next;
                this.count++;
            }
        }
        /// <summary>
        /// 范围移除
        /// </summary>
        /// <param name="start">开始索引</param>
        /// <param name="end">结束索引</param>
        public void RemoveRange(int start, int end)
        {
            RaiseForRange(ref start,ref end);
            Node<T> pstart = this.FindPrevious(start);
            Node<T> pend = this.FindPrevious(end-1);
            pstart.Next = pend.Next.Next;
        }
        /// <summary>
        /// 链表1复制到链表2
        /// </summary>
        /// <param name="t1">顺序表1</param>
        /// <param name="t2">顺序表2</param>
        /// <param name="start">开始索引</param>
        /// <param name="end">结束索引</param>
        public static bool TryCopy(LinkList<T> t1,out LinkList<T> t2,int start,int end)
        {
            if (start < 0) start += t1.count;
            if (end < 0) end += t1.count;
            var cnt = end - start;
            if (start < 0 || end < 0 || cnt <= 0 || start >= t1.count || end > t1.count)
            {
                t2 = null;
                return false;
            }

            t2 = new LinkList<T>();
            Node<T> q = t2.Head, p = t1.FindPrevious(start);
            while(p.Next!=null&& start < end)
            {
                p = p.Next;
                q.Next= new Node<T>(p.Data, null);
                q = q.Next;
                start++;
            }
            return true;
        }
        /// <summary>
        /// 链表切片
        /// </summary>
        /// <param name="start">开始索引</param>
        /// <param name="end">结束索引</param>
        /// <returns>切片结果</returns>
        public LinkList<T> this[(int start, int end) t]
        {
            get
            {
                TryCopy(this, out LinkList<T> ans, t.start, t.end);
                return ans;
            }
        }
        /// <summary>
        /// 链表切片
        /// </summary>
        /// <param name="start">开始索引</param>
        /// <param name="end">结束索引</param>
        /// <param name="step">结束索引</param>
        /// <returns>切片结果</returns>
        public LinkList<T> this[(int start, int end,int step) t]
        {
            get
            {
                if (t.step <= 0)
                    throw new IndexOutOfRangeException("列表索引访问越界了");
                RaiseForRange(ref t.start, ref t.end);
                var ls = new LinkList<T>();

                Node<T> q = ls.Head, p =this.FindPrevious(t.start);
                int i = 0;
                int cnt = 0;
                while (p.Next != null && i < t.end)
                {
                    p = p.Next;
                    if(cnt==t.step||i==t.start)
                    {
                        q.Next = new Node<T>(p.Data, null);
                        q = q.Next;
                        cnt = 0;
                    }
                    i++;
                    cnt++;
                }
                return ls;
            }
        }

        /// <summary>
        /// 删除列表顶部元素
        /// </summary>
        /// <returns>返回被删除的元素值</returns>
        public T Pop()
        {
            Node<T> p = this.FindPrevious(this.count - 1);
            Node<T> q = p.Next;
            p.Next = q.Next;
            var temp = q.Data;
            this.count--;
            return temp;
        }
        /// <summary>
        /// 逆置
        /// </summary>
        public void Reverse()
        {
            Node<T> p = this.Head.Next,q = null, t=null;
            while(p!=null)
            {
                t = p.Next;
                p.Next = q;
                q = p;
                p = t;
            }
            this.Head.Next = q;
        }
    }
}

csharper
1 声望3 粉丝

曲终过尽松陵路,回首烟波十四桥。