线性表

线性表:相同特性数据元素的有限序列
<1>有且只有一个头结点
<2>有且只有一个尾结点
<3>表头外所有元素都有一个直接前驱
<4>表尾外所有元素都有一个直接后继

线性表之顺序表

顺序表:逻辑上相邻,物理上也相邻
特性:地址连续,随机存取,类型相同,依次存放

线性表接口

namespace DataStruct.List
{
    /// <summary>
    /// 列表接口
    /// </summary>
    /// <typeparam name="T">列表数据类型</typeparam>
    interface IList<T>
    {
        /// <summary>
        /// 元素个数
        /// </summary>
        /// <returns>返回表中元素个数</returns>
        public  int Count { get; }
        /// <summary>
        /// 判断表是否为空
        /// </summary>
        /// <returns>返回是否为空</returns>
        public bool IsEmpty();

        /// <summary>
        /// 增加元素
        /// </summary>
        /// <param name="val">元素变量</param>
        public void Add(T val);
        /// <summary>
        /// 插入元素
        /// </summary>
        /// <param name="index">元素索引</param>
        /// <param name="val">插入元素值</param>
        public void Insert(int index, T val);
        /// <summary>
        /// 删除元素
        /// </summary>
        /// <param name="val">元素变量</param>
        /// <returns>返回要删除的元素</returns>
        public T Remove(T val);
        /// <summary>
        /// 索引器
        /// </summary>
        /// <param name="index">索引值</param>
        /// <returns>返回对应数据</returns>
        public T this[int index]
        {
            get; set;
        }
        /// <summary>
        /// 查看数据在列表中的位置
        /// </summary>
        /// <param name="val">数据</param>
        /// <returns>返回索引</returns>
        public int? IndexOf(T val);
        /// <summary>
        /// 清理列表元素
        /// </summary>
        public void Clear();
        /// <summary>
        /// 判断列表是否包含某个元素
        /// </summary>
        /// <param name="val">元素</param>
        /// <returns>返回是否包含</returns>
        public bool IsContains(T val);
    }
}

顺序表实现

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

namespace DataStruct.List
{
    class SequenceList<T> : IList<T>, IEnumerable<T>
        where T:IComparable<T>
    {
        #region 数据域
        /// <summary>
        /// 列表元素个数
        /// </summary>
        private int count;
        /// <summary>
        /// 数据
        /// </summary>
        private T[] data;
        /// <summary>
        /// 默认列表大小
        /// </summary>
        private const int DEFAULT_SIZE = 10;
        #endregion
        #region 构造器
        /// <summary>
        /// 构造器
        /// </summary>
        public SequenceList()
        {
            this.data = new T[DEFAULT_SIZE];
        }
        /// <summary>
        /// 构造器
        /// </summary>
        /// <param name="data">数组</param>
        public SequenceList(params T[]data)
        {
            this.count = data.Length;
            this.data = data;
        }
        #endregion
        #region 辅助函数
        /// <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 RaiseForIndex_Add(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>
        private void Expand()
        {
            if (count >= data.Length)
                Array.Resize<T>(ref data,data.Length+data.Length << 1);
        }
        #endregion
        #region 实现接口
        /// <summary>
        /// 索引器
        /// </summary>
        /// <param name="index">索引值</param>
        /// <returns>返回对应数据</returns>
        public T this[int index]
        {
            get
            {
                RaiseForIndex(ref index);
                return this.data[index];
            }
            set
            {
                RaiseForIndex(ref index);
                this.data[index] = value;
            }
        }
        /// <summary>
        /// 增加元素
        /// </summary>
        /// <param name="val">元素变量</param>
        public void Add(T val)
        {
            Expand();
            this.data[count++] = val;
        }
        /// <summary>
        /// 清理列表元素
        /// </summary>
        public void Clear() => this.count = 0;
        /// <summary>
        /// 获取给定元素的索引
        /// </summary>
        /// <param name="val">给定元素</param>
        /// <returns>索引</returns>
        public int? IndexOf(T val)
        {
            for (int i = 0; i < count; ++i)
            {
                if (val.CompareTo(data[i]) == 0)
                    return i;
            }
            return null;
        }
        /// <summary>
        /// 插入元素
        /// </summary>
        /// <param name="index">元素索引</param>
        /// <param name="val">插入元素值</param>
        public void Insert(int index, T val)
        {
            RaiseForIndex_Add(index);
            Expand();
            for (int i = count; i >index; i--)
                this.data[i] = this.data[i - 1];
            this.data[index] = val;
            this.count++;
        }
        /// <summary>
        /// 获取元素个数
        /// </summary>
        public int Count => this.count;
        /// <summary>
        /// 判断是否为空
        /// </summary>
        /// <returns>是否为空</returns>
        public bool IsEmpty()=>this.count == 0;
        /// <summary>
        /// 删除元素
        /// </summary>
        /// <param name="val">元素变量</param>
        /// <returns>返回要删除的元素</returns>
        public T Remove(int index)
        {
            RaiseForIndex(ref index);//检查越界
            var temp = this.data[index];
            for (int i = index; i < count; i++)
                this.data[i] = this.data[i + 1];
            this.count--;
            return temp;
        }
        /// <summary>
        /// 判断列表是否包含某个元素
        /// </summary>
        /// <param name="val">元素</param>
        /// <returns>返回是否包含</returns>
        public bool IsContains(T val)
        {
            return this.IndexOf(val).HasValue;
        }

        #endregion
        #region 转化其他
        /// <summary>
        /// 覆盖ToString方法
        /// </summary>
        /// <returns>返回字符串</returns>
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("[");
            bool tag = true;
            for(int i=0;i<count;++i)
            {
                if (tag)
                {
                    sb.Append(this.data[i] + "");
                    tag = false;
                }
                else
                    sb.Append(","+ this.data[i]);
            }
            sb.Append("]");
            return sb.ToString();
        }
        /// <summary>
        /// 转化为数组
        /// </summary>
        /// <returns></returns>
        public T[]ToArray()=>this.data;
        #endregion
        /// <summary>
        /// 显式类型转换
        /// </summary>
        /// <param name="array">数组</param>
        public static implicit operator SequenceList<T>(T[]array)=>new SequenceList<T>(array);
        /// <summary>
        /// 获取迭代器
        /// </summary>
        /// <returns>返回迭代器</returns>
        public IEnumerator<T> GetEnumerator()
        {
            for (int i = 0; i < this.count; i++)
                yield return this.data[i];
        }
        /// <summary>
        /// 获取迭代器
        /// </summary>
        /// <returns>返回迭代器</returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            for (int i = 0; i < this.count; i++)
                yield return this.data[i];
        }

        /// <summary>
        /// 范围添加
        /// </summary>
        /// <param name="collection">可迭代集合</param>
        public void AddRange(IEnumerable<T> collection)
        {
            foreach (var item in collection)
            {
                this.Add(item);
            }
        }
        /// <summary>
        /// 范围移除
        /// </summary>
        /// <param name="start">开始索引</param>
        /// <param name="end">结束索引</param>
        /// <returns>删除几个</returns>
        public int RemoveRange(int start, int end)
        {
            RaiseForRange(ref start, ref end);
            while (end<count)
                this.data[start++] = this.data[end++];
            this.count = start;
            return start - end;
        }
        /// <summary>
        /// 顺序表切片
        /// </summary>
        /// <param name="start">开始索引</param>
        /// <param name="end">结束索引</param>
        /// <returns>切片结果</returns>
        public SequenceList<T> this[(int start,int end) t]
        {
            get
            {
                TryCopy(this, out SequenceList<T> ans, t.start, t.end);
                return ans; 
            }
        }
        /// <summary>
        /// 顺序表切片
        /// </summary>
        /// <param name="start">开始索引</param>
        /// <param name="end">结束索引</param>
        /// <returns>切片结果</returns>
        public SequenceList<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 SequenceList<T>();
                for (int i = t.start; i < t.end; i += t.step)
                    ls.Add(this[i]);
                return ls;
            }
        }
        /// <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(SequenceList<T> t1, out SequenceList<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;
            }
            var t = new T[cnt];
            Array.Copy(t1.data, start, t, 0, cnt);
            t2 = new SequenceList<T>(t);
            return true;
        }
        /// <summary>
        /// 删除列表顶部元素
        /// </summary>
        /// <returns>返回被删除的元素值</returns>
        public T Pop()
        {
            if (this.count == 0)
                throw new IndexOutOfRangeException("列表为空!");
            return this.data[--this.count];
        }
        /// <summary>
        /// 列表逆置
        /// </summary>
        public void Reverse()
        {
            for (int i = 0; i < this.count/2; i++)
                (data[i],data[count - i - 1]) = (data[count-i-1], this.data[i]);
        }
        /// <summary>
        /// 划分问题
        /// </summary>
        /// <param name="val">值</param>
        /// <param name="reverse">是否逆序</param>
        public void Partition(T val,bool reverse=false)
        {
            int i = 0;
            int j = count-1;
            if(reverse)
            {
                while (i < j)
                {
                    while (i < j && data[i].CompareTo(val) >= 0)
                        i++;
                    while (i < j && data[j].CompareTo(val) < 0)
                        j--;
                    if (i < j)
                        (data[i], data[j]) = (data[j], data[i]);
                }
            }
            else
            {
                while (i < j)
                {
                    while (i < j && data[i].CompareTo(val) <= 0)
                        i++;
                    while (i < j && data[j].CompareTo(val) > 0)
                        j--;
                    if (i < j)
                        (data[i], data[j]) = (data[j], data[i]);
                }
            }
        }
        /// <summary>
        /// 元素左移
        /// </summary>
        public void MoveLeft()
        {
            var temp = this.data[0];
            for (int i = 0; i < count-1; i++)
                this.data[i] = this.data[i + 1];
            this.data[count - 1] = temp;
        }
        /// <summary>
        /// 元素右移
        /// </summary>
        public void MoveRight()
        {
            var temp = this.data[count - 1];
            for (int i = count - 1; i > 0; i--)
                data[i] = data[i - 1];
            this.data[0] = temp;
        }
        /// <summary>
        /// 运算符重载:添加元素
        /// </summary>
        /// <param name="x">顺序表</param>
        /// <param name="val">值</param>
        /// <returns>返回添加后的新表</returns>
        public static SequenceList<T> operator +(SequenceList<T> x,T val)
        {
            TryCopy(x, out SequenceList<T> t, 0, x.count);
            t.Add(val);
            return t;
        }
        /// <summary>
        /// 运算符重载:追加列表
        /// </summary>
        /// <param name="x">顺序表1</param>
        /// <param name="y">顺序表2</param>
        /// <returns>返回添加后的列表</returns>
        public static SequenceList<T> operator+(SequenceList<T> x,SequenceList<T> y)
        {
            T[] data = new T[x.count + y.count];
            Array.Copy(x.data, 0, data, 0, x.count);
            Array.Copy(y.data, 0, data, x.count, y.count);
            return new SequenceList<T>(data);
        }
    }
}

顺序表操作

创建

var a = new SequenceList<int>();
var b = new SequenceList<double>(1.0,2.3,3,4,5,6,7);
SequenceList<int> c= new int[] { 2, 3, 5, 7, 8 };

索引

WriteLine(b);//[1,2.3,3,4,5,6,7]
WriteLine(b[-1]);//7

切片

WriteLine(b[(0, 2)]);//[1,2.3]
WriteLine(c[(0, 5, 2)]);//[2,5,8]
WriteLine(c[(0, -1, 2)]);//[2,5]

基本操作

c.Add(5);
c.AddRange(new int[] { 6, 5, 8, 9 });
WriteLine(c.IsContains(5));//True
c.Insert(0, 10086);
WriteLine(c.IndexOf(5));//3
WriteLine(c);//[10086,2,3,5,7,8,5,6,5,8,9]
c.RemoveRange(0, 5);
WriteLine(c);//[8,5,6,5,8,8,5,6,5,8]
c.Clear();

列表复制

SequenceList<int> c= new int[] { 2, 3, 5, 7, 8 };
//深复制,返回新列表
c += 1;
c += 2;
c += 5;
WriteLine(c);//[2,3,5,7,8,1,2,5]
c.Pop();
c.Pop();
c.Pop();
c += new SequenceList<int>(5,7,8);
WriteLine(c);//[2,3,5,7,8,5,7,8]

其他

var a = new SequenceList<int>(1,5,7,8,9,6,5,3,0);
a.Reverse();
WriteLine(a);//[0,3,5,6,9,8,7,5,1]
a.MoveLeft();
WriteLine(a);//[3,5,6,9,8,7,5,1,0]
a.MoveRight();
WriteLine(a);//[0,3,5,6,9,8,7,5,1]
a.Partition(5, false);
WriteLine(a);//[0,3,5,1,5,8,7,9,6]

csharper
1 声望3 粉丝

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