C#算法从入门到跑路 第1章:线性表之循环链表

单循环链表

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

namespace DataStruct.List
{
    /// 
    /// 循环链表
    /// 
    /// 数据类型
    class CycleLinkList : IList, IEnumerable
        where T : IComparable
    {
        /// 
        /// 获取头结点
        /// 
        public Node Head { get; }
        /// 
        /// 获取尾节点
        /// 
        public Node P { get; private set; }
        /// 
        /// 节点数量
        /// 
        private int count;
        /// 
        /// 构造器
        /// 
        public CycleLinkList()
        {
            this.Head = new Node();
            this.Head.Next = this.Head;
            this.P = this.Head;
        }
        /// 
        /// 构造器
        /// 
        /// 数组
        public CycleLinkList(params T[] array)
        {
            Node p = this.Head = new Node();
            foreach (var item in array)
            {
                Node t = new Node(item);
                p.Next = t;
                p = p.Next;
                this.count++;
            }
            p.Next = Head;
            this.P = p;
        }
        /// 
        /// 构造器
        /// 
        /// 数组
        /// 是否使用尾插法
        public CycleLinkList(IEnumerable array, bool reverse = false)
        {
            if (reverse)
            {
                this.Head = new Node();
                bool flag=true;
                Node t = null;
                foreach (var item in array)
                {
                    if(flag)
                    {
                        t = new Node(item, Head);
                        flag = false;
                        this.P = t;
                    }
                    else
                        t = new Node(item, Head.Next);
                    Head.Next = t;
                    this.count++;
                }

            }
            else
            {
                Node p = this.Head = new Node();
                foreach (var item in array)
                {
                    Node t = new Node(item);
                    p.Next = t;
                    p = p.Next;
                    this.count++;
                }
                p.Next = Head;
                this.P = p;
            }
        }
        /// 
        /// 检查索引
        /// 
        /// 索引
        private void RaiseForIndex(ref int index)
        {
            if (index < 0)
                index += this.count;
            if (index < 0 || index >= count)
                throw new IndexOutOfRangeException("列表索引访问越界了");
        }
        /// 
        /// 检查区间
        /// 
        /// 索引
        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("列表索引访问越界了");
        }
        /// 
        /// 查找给定索引元素的前驱节点
        /// 
        /// 索引
        /// 返回节点
        public Node FindPrevious(int index)
        {
            RaiseForIndex(ref index);
            int i = 0;
            Node p = this.Head;
            while (i < index && p.Next != this.Head)
            {
                p = p.Next;
                i++;
            }
            return p;
        }
        ///// 
        ///// 返回倒数第index个元素的节点
        ///// 
        ///// 倒数第几
        ///// 返回该节点
        //public Node FindLast(int index)
        //{
        //    if(index<=0)
        //        throw new IndexOutOfRangeException("索引访问越界");
        //    Node p= this.Head;
        //    for (int i = 0; i < index; i++)
        //    {
        //        if (p.Next == null)
        //            throw new IndexOutOfRangeException("索引访问越界");
        //        p = p.Next;
        //    }
        //    Node q = this.Head;
        //    while(p.Next!=null)
        //    {
        //        p = p.Next;
        //        q = q.Next;
        //    }
        //    return q.Next;
        //}


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

        /// 
        /// 增加元素
        /// 
        /// 元素变量
        public void Add(T val)
        {
            Node t = new Node(val, this.Head);
            this.P.Next = t;
            this.P =t;
            this.count++;
        }
        /// 
        /// 清理
        /// 
        public void Clear()
        {
            this.Head.Next = Head;
            this.count = 0;
        }
        /// 
        /// 查看数据在列表中的位置
        /// 
        /// 数据
        /// 返回索引
        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;
        }
        /// 
        /// 插入元素
        /// 
        /// 元素索引
        /// 插入元素值
        public void Insert(int index, T val)
        {
            var p = this.FindPrevious(index);
            Node temp = new Node(val, p.Next);
            p.Next = temp;
            this.count++;
        }
        /// 
        /// 判断列表是否包含某个元素
        /// 
        /// 元素
        /// 返回是否包含
        public bool IsContains(T val) => this.IndexOf(val) != null;
        /// 
        /// 判空
        /// 
        /// 表是否为空
        public bool IsEmpty() => this.Head.Next == this.Head;
        /// 
        /// 删除元素
        /// 
        /// 元素索引
        /// 返回要删除的元素
        public T Remove(int index)
        {
            var p = this.FindPrevious(index);
            var q = p.Next;
            var temp = q.Data;
            p.Next = q.Next;
            this.count--;
            //如果要删除的节点为尾巴节点:改变尾巴节点指向
            if (p.Next == this.Head)
                this.P = p;
            return temp;
        }
        /// 
        /// 覆盖ToString方法
        /// 
        /// 返回字符串
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("[");
            Node p = this.Head;
            while (p.Next != this.Head)
            {
                p = p.Next;
                sb.Append(p);
            }
            sb.Append("]");
            return sb.ToString();
        }
        /// 
        /// 转化为数组
        /// 
        /// 数组
        public T[] ToArray()
        {
            T[] array = new T[count];
            int i = 0;
            foreach (var item in this)
                array[i++] = item;
            return array;
        }
        /// 
        /// 隐式类型转换
        /// 
        /// 顺序表
        public static explicit operator CycleLinkList(SequenceList ls) => new CycleLinkList(ls.ToArray());
        /// 
        /// 显式类型转换
        /// 
        /// 数组
        public static implicit operator CycleLinkList(T[] array) => new CycleLinkList(array);
        /// 
        /// 获取迭代器
        /// 
        /// 返回迭代器
        public IEnumerator GetEnumerator()
        {
            var p = this.Head;
            while (p.Next != this.Head)
            {
                p = p.Next;
                yield return p.Data;
            }
        }
        /// 
        /// 获取迭代器
        /// 
        /// 返回迭代器
        IEnumerator IEnumerable.GetEnumerator()
        {
            var p = this.Head;
            while (p.Next != this.Head)
            {
                p = p.Next;
                yield return p.Data;
            }
        }
        /// 
        /// 范围添加
        /// 
        /// 可迭代集合
        public void AddRange(IEnumerable collection)
        {
            foreach (var item in collection)
            {
                this.P.Next = new Node(item, this.Head);
                P = P.Next;
                this.count++;
            }
        }
        /// 
        /// 范围移除
        /// 
        /// 开始索引
        /// 结束索引
        public void RemoveRange(int start, int end)
        {
            RaiseForRange(ref start, ref end);
            Node pstart = this.FindPrevious(start);
            Node pend = this.FindPrevious(end - 1);
            pstart.Next = pend.Next.Next;
            //如果要删除的节点包含尾巴节点:改变尾巴节点指向
            if (pstart.Next==this.Head)
                this.P = pstart; 
        }
        /// 
        /// 链表1复制到链表2
        /// 
        /// 顺序表1
        /// 顺序表2
        /// 开始索引
        /// 结束索引
        public static bool TryCopy(CycleLinkList t1, out CycleLinkList 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 CycleLinkList();
            Node q = t2.Head, p = t1.FindPrevious(start);
            while (p.Next != t1.Head && start < end)
            {
                p = p.Next;
                q.Next = new Node(p.Data, null);
                q = q.Next;
                start++;
            }
            q.Next = t2.Head;
            t2.P = q;
            return true;
        }
        /// 
        /// 链表切片
        /// 
        /// 开始索引
        /// 结束索引
        /// 切片结果
        public CycleLinkList this[(int start, int end) t]
        {
            get
            {
                TryCopy(this, out CycleLinkList ans, t.start, t.end);
                return ans;
            }
        }
        /// 
        /// 链表切片
        /// 
        /// 开始索引
        /// 结束索引
        /// 结束索引
        /// 切片结果
        public CycleLinkList 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 CycleLinkList();

                Node q = ls.Head, p = this.FindPrevious(t.start);
                int i = 0;
                int cnt = 0;
                while (p.Next != this.Head && i < t.end)
                {
                    p = p.Next;
                    if (cnt == t.step || i == t.start)
                    {
                        q.Next = new Node(p.Data, null);
                        q = q.Next;
                        cnt = 0;
                    }
                    i++;
                    cnt++;
                }
                q.Next = ls.Head;
                ls.P = q;
                return ls;
            }
        }
        /// 
        /// 删除列表最后一个元素
        /// 
        /// 返回被删除的元素值
        public T Pop()
        {
            Node p = this.FindPrevious(this.count - 1);
            Node q = p.Next;
            var temp = q.Data;
            p.Next =q.Next;
            this.P = p;
            this.count--;
            return temp;
        }
        /// 
        /// 逆置
        /// 
        public void Reverse()
        {
            Node p = this.Head.Next, q = null, t = null;
            while (p != null)
            {
                t = p.Next;
                p.Next = q;
                q = p;
                p = t;
            }
        }
}

循环链表解决约瑟夫问题


        /// 
        /// 约瑟夫问题
        /// 
        /// n个人
        /// 杀掉第m个
        /// 依次返回可枚举集合
        public static IEnumerable Josephus(int n, int m)
        {
            CycleLinkList rec = new CycleLinkList(Util.range(1, n));
            Node p = rec.Head.Next;
            while (p.Next != p)
            {
                for (int i = 1; i < m - 1; ++i)
                    p = p.Next;
                Node q = p.Next;
                yield return q.Data;
                p.Next = q.Next;
                p = p.Next;
            }
            yield return p.Data;
        }

    }

你可能感兴趣的:(c#,算法-数据结构)