C#数据结构-List实现

把C#内部的List<T>手动实现了一遍,实现很多Array开头的方法,比如Array.Copy() , Array.Clear()等,在.NET Framework的内部方法,当然C#内部实现应该更快。同时,拷贝了C#的排序源码,了解了快速排序和内省排序的实现。

IList<T>接口实现:

namespace StructScript
{
    public interface IList<T> : ICollection<T>
    {
        /// <summary>
        /// 提供读取和编辑列表中的项的方法
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        T this[int index]
        {
            get;
            set;
        }

        /// <summary>
        /// 搜索指定的对象,并返回第一个匹配项的索引
        /// 如果项不在列表中,返回-1
        /// </summary>
        int IndexOf(T value);

        /// <summary>
        /// 如果项在列表中,返回特定项的索引
        /// 如果项不在列表中,返回-1
        /// </summary>
        int LastIndexOf(T value);

        /// <summary>
        /// 插入一个值到列表的一个固定位置
        /// 插入位置必须小于等于列表项的总数,且大于0
        /// </summary>
        /// <param name="index"></param>
        /// <param name="value"></param>
        void Insert(int index, T value);

        /// <summary>
        /// 移除索引位置的项
        /// </summary>
        void RemoveAt(int index);

        /// <summary>
        /// 列表中所有元素的顺序反转
        /// </summary>
        void Reverse();

        /// <summary>
        /// 使用默认比较器对所有元素进行排序
        /// </summary>
        void Sort();
    }
}

IConnection<T>接口实现:

using System.Collections.Generic;

namespace StructScript
{
    public interface ICollection<T> : IEnumerable<T>
    {
        /// <summary>
        /// 返回列表中项的总数
        /// </summary>       
        int Count { get; }

        /// <summary>
        /// 添加一个新的项到列表中
        /// </summary>
        void Add(T item);

        /// <summary>
        /// 从列表中清除所有的项
        /// </summary>
        void Clear();

        /// <summary>
        /// 返回列表是否包含特定的项
        /// </summary>
        bool Contains(T item);

        /// <summary>
        /// 从列表复制到数组中
        /// </summary>
        void CopyTo(T[] array, int arrayIndex);

        /// <summary>
        /// 移除特定对象的第一个匹配项
        /// </summary>
        bool Remove(T item);
    }
}

List<T> C#算法实现:

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

namespace StructScript
{
    public class ListScript<T> : IList<T>
    {
        //默认容量为4
        private const int DEFAULT_CAPACITY = 4;
        //数组最大长度
        private const int MAX_ARRAY_LENGTH = 0X7FEFFFFF;
        private T[] mItems;
        //列表的总长度
        private int mSize;
        //无论创建多少个对象,静态变量共享一个副本
        private static readonly T[] mEmptyList = new T[0];

        public ListScript()
        {
            mItems = mEmptyList;
        }

        public ListScript(int capacity)
        {
            if (capacity < 0 && capacity > MAX_ARRAY_LENGTH)
            {
                throw new IndexOutOfRangeException();
            }

            if (capacity == 0)
            {
                mItems = mEmptyList;
            }
            else
            {
                mItems = new T[capacity];
            }
        }

        public ListScript(IEnumerable<T> collection)
        {
            if (collection == null)
            {
                throw new ArgumentNullException();
            }
            ICollection list = collection as ICollection;
            if (list != null)
            {
                int count = list.Count;
                //初始化时,传入一个collection
                if (count == 0)
                {
                    mItems = mEmptyList;
                }
                else
                {
                    //创建一个数组,把collection的数据复制到mItems中,
                    //同时mSize加上count的数量
                    mItems = new T[count];
                    list.CopyTo(mItems, 0);
                    mSize += count;
                }
            }
            else
            {
                throw new InvalidCastException();
            }
        }

        /// <summary>
        /// 得到或设置列表的容量
        /// </summary>
        public int Capacity
        {
            get
            {
                return mItems.Length;
            }
            set
            {
                if (value < mSize)
                {
                    throw new IndexOutOfRangeException();
                }

                if (value != mItems.Length)
                {
                    if (value > 0)
                    {
                        T[] newItems = new T[value];
                        if (mSize > 0)
                        {
                            Copy(ref mItems, 0, ref newItems, 0, mSize);
                        }
                        mItems = newItems;
                    }
                    else
                    {
                        mItems = mEmptyList;
                    }
                }
            }
        }

        /// <summary>
        /// 返回列表中项的总数
        /// </summary>
        public int Count
        {
            get
            {
                return mSize;
            }
        }

        public object SyncRoot
        {
            get
            {
                throw new NotImplementedException();
            }
        }

        public bool IsSynchronized
        {
            get
            {
                throw new NotImplementedException();
            }
        }

        //列表的索引器
        public T this[int index]
        {
            get
            {
                if (index >= mSize || index < 0)
                {
                    throw new IndexOutOfRangeException();
                }
                return mItems[index];
            }

            set
            {
                if (index >= mSize || index < 0)
                {
                    throw new IndexOutOfRangeException();
                }
                mItems[index] = value;
            }
        }

        /// <summary>
        /// 添加一个新的项到列表中
        /// </summary>
        /// <param name="value"></param>
        public void Add(T value)
        {
            //如果数组满了,先扩容
            if (mSize == mItems.Length)
            {
                EnsureCapacity(mSize + 1);
            }
            mItems[mSize] = value;
            mSize++;
        }

        /// <summary>
        /// 保证列表容量
        /// </summary>
        /// <param name="size"></param>
        private void EnsureCapacity(int size)
        {
            int length = mItems.Length;
            if (length < size)
            {
                int newCapacity = length == 0 ? DEFAULT_CAPACITY : length * 2;
                //如果大于数组最大长度,设置为数组最大长度
                if (newCapacity > MAX_ARRAY_LENGTH)
                {
                    newCapacity = MAX_ARRAY_LENGTH;
                }
                //如果在AddRange新增数据时,length * 2也不能满足所需的容量,设置为size
                if (newCapacity < size)
                {
                    newCapacity = size;
                }
                Capacity = newCapacity;
            }
        }

        /// <summary>
        /// 返回列表是否包含特定的项
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool Contains(T value)
        {
            int index;
            return Contain(value, out index);
        }

        /// <summary>
        /// 从列表中清除所有的项
        /// </summary>
        public void Clear()
        {
            if (mSize > 0)
            {
                //Array.Clear(mItems, 0, mSize);
                for (int i = 0; i < mSize; i++)
                {
                    mItems[i] = default(T);
                }
                mSize = 0;
            }
        }

        private bool Contain(T value, out int index)
        {
            index = 0;
            if (value != null)
            {
                //用于比较泛型参数指定的类型
                //EqualityComparer<T> compare = EqualityComparer<T>.Default;
                for (int i = 0; i < mSize; i++)
                {
                    //if (compare.Equals(mItems[i], value))
                    if (Equal(mItems[i], value))
                    {
                        index = i;
                        return true;
                    }
                }
            }
            return false;
        }

        private bool ContainReverse(T value, out int index)
        {
            index = 0;
            if (value != null)
            {
                //用于比较泛型参数指定的类型
                //EqualityComparer<T> compare = EqualityComparer<T>.Default;
                for (int i = mSize - 1; i > 0; i--)
                {
                    //if (compare.Equals(mItems[i], value))
                    if (Equal(mItems[i], value))
                    {
                        index = i;
                        return true;
                    }
                }
            }
            return false;
        }


        private bool Equal(Object obj1, Object obj2)
        {
            return obj1 == obj2;
        }

        /// <summary>
        /// 搜索指定的对象,并返回整个 List<T> 中第一个匹配项的索引
        /// 如果项不在列表中,返回-1
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public int IndexOf(T value)
        {
            //实际上调用的是下面的语句,不过是在保护级别中,不能直接调用
            //EqualityComparer<T>.Default.IndexOf(T[] array, T value, startIndex, count);
            int index;
            if (Contain(value, out index))
            {
                return index;
            }
            return -1;
        }

        /// <summary>
        /// 搜索指定对象并返回整个 List<T> 中最后一个匹配项的索引
        /// 如果项不在列表中,返回-1
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public int LastIndexOf(T value)
        {
            int index;
            if (ContainReverse(value, out index))
            {
                return index;
            }
            return -1;
        }

        /// <summary>
        /// 插入一个值到列表的一个固定位置
        /// </summary>
        /// <param name="index"></param>
        /// <param name="value"></param>
        public void Insert(int index, T value)
        {
            if (index >= mSize || index < 0)
            {
                throw new IndexOutOfRangeException();
            }
            //如果数组满了,先扩容
            if (mSize == mItems.Length)
            {
                EnsureCapacity(mSize + 1);
            }
            //当插入的index小于mSize,并且数组没有满,
            //这时就可以把插入位置之后的数据复制并依次粘贴到当前数组的下一个位置上
            Copy(ref mItems, index, ref mItems, index + 1, mSize - index);
            mItems[index] = value;
            mSize++;
        }

        /// <summary>
        /// 从 List<T> 中移除特定对象的第一个匹配项
        /// </summary>
        /// <param name="value"></param>
        public bool Remove(T value)
        {
            int index = IndexOf(value);
            if (index >= 0)
            {
                RemoveAt(index);
                return true;
            }
            return false;
        }

        /// <summary>
        /// 移除索引位置的项
        /// </summary>
        /// <param name="index"></param>
        public void RemoveAt(int index)
        {
            if (index >= mSize || index < 0)
            {
                throw new IndexOutOfRangeException();
            }
            mSize--;
            //把索引位置之后的数据复制并覆盖从索引位置开始到结尾的数据
            Copy(ref mItems, index + 1, ref mItems, index, mSize - index);
            //default此关键字对于引用类型会返回空,对于数值类型会返回零, string类型返回""
            //default用来获取一个类型的默认值
            mItems[mSize] = default(T);
        }

        /// <summary>
        /// 从目标数组的指定索引处开始,将整个 List<T> 复制到兼容的一维数组
        /// </summary>
        /// <param name="array"></param>
        /// <param name="arrayIndex"></param>
        public void CopyTo(T[] array, int arrayIndex)
        {
            //Array.Copy(mItems, 0, array, arrayIndex, mSize);
            Copy(ref mItems, 0, ref array, arrayIndex, mSize);
        }

        /// <summary>
        /// 将 List<T> 的元素复制到新数组中
        /// </summary>
        /// <returns></returns>
        public T[] ToArray()
        {
            T[] array = new T[mSize];
            Copy(ref mItems, 0, ref array, 0, mSize);
            return array;
        }

        /// <summary>
        /// 使用默认比较器对整个 List<T> 中的元素进行排序
        /// </summary>
        public void Sort()
        {
            ArraySortHelper<T>.Default.Sort(mItems, 0, mSize, null);
        }

        public void Sort(IComparer<T> comparer)
        {
            ArraySortHelper<T>.Default.Sort(mItems, 0, mSize, comparer);
        }

        public void Sort(Comparison<T> comparsion)
        {
            if (comparsion == null)
            {
                throw new ArgumentNullException();
            }
            if (mSize > 0)
            {
                IComparer<T> comparer = new FunctorComparer<T>(comparsion);
                Sort(comparer);
            }
        }

        /// <summary>
        /// 从给定的索引开始复制数组中的一系列元素,将它们粘贴到另一数组中(从给定的目的开始复制的索引开始)。
        /// </summary>
        /// <param name="sourceArray">包含要复制的数据</param>
        /// <param name="sourceIndex">开始复制的索引</param>
        /// <param name="destinationArray">接收数据</param>
        /// <param name="destinationIndex">目的开始复制的索引</param>
        /// <param name="length">要复制的元素数目</param>
        private void Copy(ref T[] sourceArray, int sourceIndex, ref T[] destinationArray, int destinationIndex, int length)
        {
            if (sourceIndex >= destinationIndex)
            {
                while (length > 0)
                {
                    destinationArray[destinationIndex] = sourceArray[sourceIndex];
                    length--;
                    sourceIndex++;
                    destinationIndex++;
                }
            }
            else
            {
                int lastIndex = sourceIndex + length - 1;
                int otherLastIndex = destinationIndex + length - 1;
                while (length > 0)
                {
                    destinationArray[otherLastIndex] = sourceArray[lastIndex];
                    length--;
                    lastIndex--;
                    otherLastIndex--;
                }
            }
        }

        /// <summary>
        /// 将整个 List<T> 中元素的顺序反转
        /// </summary>
        public void Reverse()
        {
            int i = 0;
            int j = mSize - 1;
            while (i < j)
            {
                T temp = mItems[i];
                mItems[i] = mItems[j];
                mItems[j] = temp;
                i++;
                j--;
            }
        }

        /// <summary>
        /// 将指定集合的元素添加到 List<T> 的末尾
        /// </summary>
        /// <param name="collection"></param>
        public void AddRange(IEnumerable<T> collection)
        {
            if (collection == null)
            {
                throw new ArgumentNullException();
            }
            ICollection<T> list = collection as ICollection<T>;
            if (list != null)
            {
                int count = list.Count;
                //想要增加新的数据,先扩容
                EnsureCapacity(mSize + count);
                //这里有一种情况是,AddRange的是当前的list
                if (this == list)
                {
                    //直接复制当前的数组到结尾,不需要new一个新的数组转存数据
                    Copy(ref mItems, 0, ref mItems, mSize, mSize);
                }
                else
                {
                    T[] addRangeItems = new T[count];
                    //复制新增的collection数组到addRangeItems中
                    list.CopyTo(addRangeItems, 0);
                    //从mItems数组的mSize索引开始,复制数组addRangeItems到mItems中
                    addRangeItems.CopyTo(mItems, mSize);
                }
                mSize += count;
            }
            else
            {
                throw new InvalidCastException();
            }
        }

        public IEnumerator<T> GetEnumerator()
        {
            return new Enumerator(this);
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return new Enumerator(this);
        }

        public struct Enumerator : IEnumerator<T>
        {
            private ListScript<T> list;
            private int index;
            private T current;

            public Enumerator(ListScript<T> list)
            {
                this.list = list;
                index = 0;
                current = default(T);
            }

            public T Current
            {
                get
                {
                    if (index <= 0 || index > list.Count)
                    {
                        throw new IndexOutOfRangeException();
                    }
                    return current;
                }
            }

            object IEnumerator.Current
            {
                get
                {
                    if (index <= 0 || index > list.Count)
                    {
                        throw new IndexOutOfRangeException();
                    }
                    return current;
                }
            }

            public void Dispose()
            {

            }

            public bool MoveNext()
            {
                if (index >= 0 && index < list.Count)
                {
                    current = list[index];
                    index++;
                    return true;
                }
                return false;
            }

            public void Reset()
            {
                index = 0;
                current = default(T);
            }
        }
    }

    public sealed class FunctorComparer<T> : IComparer<T>
    {
        Comparison<T> comparison;

        public FunctorComparer(Comparison<T> comparison)
        {
            this.comparison = comparison;
        }

        public int Compare(T x, T y)
        {
            return comparison(x, y);
        }
    }
}

C#内部排序实现:

using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;

namespace StructScript
{
    public interface IArraySortHelper<TKey>
    {
        void Sort(TKey[] keys, int index, int length, IComparer<TKey> comparer);
        int BinarySearch(TKey[] keys, int index, int length, TKey value, IComparer<TKey> comparer);
    }

    public class ArraySortHelper<T> : IArraySortHelper<T>
    {
        static volatile IArraySortHelper<T> defaultArraySortHelper;

        public static IArraySortHelper<T> Default
        {
            get
            {
                IArraySortHelper<T> sorter = defaultArraySortHelper;
                if (sorter == null)
                    sorter = CreateArraySortHelper();

                return sorter;
            }
        }

        [System.Security.SecuritySafeCritical]  // auto-generated
        private static IArraySortHelper<T> CreateArraySortHelper()
        {
            //if (typeof(IComparable<T>).IsAssignableFrom(typeof(T)))
            //{
            //    defaultArraySortHelper = (IArraySortHelper<T>)RuntimeTypeHandle.Allocate(typeof(GenericArraySortHelper<string>).TypeHandle.Instantiate(new Type[] { typeof(T) }));
            //}
            //else
            {
                defaultArraySortHelper = new ArraySortHelper<T>();
            }
            return defaultArraySortHelper;
        }

        #region IArraySortHelper<T> Members

        public void Sort(T[] keys, int index, int length, IComparer<T> comparer)
        {
            Contract.Assert(keys != null, "Check the arguments in the caller!");
            Contract.Assert(index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!");

            // Add a try block here to detect IComparers (or their
            // underlying IComparables, etc) that are bogus.
            try
            {
                if (comparer == null)
                {
                    comparer = Comparer<T>.Default;
                }

#if FEATURE_CORECLR
                // Since QuickSort and IntrospectiveSort produce different sorting sequence for equal keys the upgrade 
                // to IntrospectiveSort was quirked. However since the phone builds always shipped with the new sort aka 
                // IntrospectiveSort and we would want to continue using this sort moving forward CoreCLR always uses the new sort.
 
                IntrospectiveSort(keys, index, length, comparer);
#else
                //if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
                //{
                    IntrospectiveSort(keys, index, length, comparer);
                //}
                //else
                //{
                //    DepthLimitedQuickSort(keys, index, length + index - 1, comparer, 32);
                //}
#endif
            }
            catch (IndexOutOfRangeException)
            {
                //IntrospectiveSortUtilities.ThrowOrIgnoreBadComparer(comparer);
            }
            catch (Exception e)
            {
                throw new InvalidOperationException();//Environment.GetResourceString("InvalidOperation_IComparerFailed"), e);
            }
        }

        public int BinarySearch(T[] array, int index, int length, T value, IComparer<T> comparer)
        {
            try
            {
                if (comparer == null)
                {
                    comparer = Comparer<T>.Default;
                }

                return InternalBinarySearch(array, index, length, value, comparer);
            }
            catch (Exception e)
            {
                throw new InvalidOperationException();//Environment.GetResourceString("InvalidOperation_IComparerFailed"), e);
            }
        }

        #endregion

        internal static int InternalBinarySearch(T[] array, int index, int length, T value, IComparer<T> comparer)
        {
            Contract.Requires(array != null, "Check the arguments in the caller!");
            Contract.Requires(index >= 0 && length >= 0 && (array.Length - index >= length), "Check the arguments in the caller!");

            int lo = index;
            int hi = index + length - 1;
            while (lo <= hi)
            {
                int i = lo + ((hi - lo) >> 1);
                int order = comparer.Compare(array[i], value);

                if (order == 0) return i;
                if (order < 0)
                {
                    lo = i + 1;
                }
                else
                {
                    hi = i - 1;
                }
            }

            return ~lo;
        }

        private static void SwapIfGreater(T[] keys, IComparer<T> comparer, int a, int b)
        {
            if (a != b)
            {
                if (comparer.Compare(keys[a], keys[b]) > 0)
                {
                    T key = keys[a];
                    keys[a] = keys[b];
                    keys[b] = key;
                }
            }
        }

        private static void Swap(T[] a, int i, int j)
        {
            if (i != j)
            {
                T t = a[i];
                a[i] = a[j];
                a[j] = t;
            }
        }

        internal static void DepthLimitedQuickSort(T[] keys, int left, int right, IComparer<T> comparer, int depthLimit)
        {
            do
            {
                if (depthLimit == 0)
                {
                    Heapsort(keys, left, right, comparer);
                    return;
                }

                int i = left;
                int j = right;

                // pre-sort the low, middle (pivot), and high values in place.
                // this improves performance in the face of already sorted data, or 
                // data that is made up of multiple sorted runs appended together.
                // >> 运算符相当于除,5 >> 1,相当于5/2,等于2
                int middle = i + ((j - i) >> 1);
                SwapIfGreater(keys, comparer, i, middle);  // swap the low with the mid point
                SwapIfGreater(keys, comparer, i, j);   // swap the low with the high
                SwapIfGreater(keys, comparer, middle, j); // swap the middle with the high

                T x = keys[middle];
                do
                {
                    while (comparer.Compare(keys[i], x) < 0) i++;
                    while (comparer.Compare(x, keys[j]) < 0) j--;
                    Contract.Assert(i >= left && j <= right, "(i>=left && j<=right)  Sort failed - Is your IComparer bogus?");
                    if (i > j) break;
                    if (i < j)
                    {
                        T key = keys[i];
                        keys[i] = keys[j];
                        keys[j] = key;
                    }
                    i++;
                    j--;
                } while (i <= j);

                // The next iteration of the while loop is to "recursively" sort the larger half of the array and the
                // following calls recrusively sort the smaller half.  So we subtrack one from depthLimit here so
                // both sorts see the new value.
                depthLimit--;

                if (j - left <= right - i)
                {
                    if (left < j) DepthLimitedQuickSort(keys, left, j, comparer, depthLimit);
                    left = i;
                }
                else
                {
                    if (i < right) DepthLimitedQuickSort(keys, i, right, comparer, depthLimit);
                    right = j;
                }
            } while (left < right);
        }

        internal static void IntrospectiveSort(T[] keys, int left, int length, IComparer<T> comparer)
        {
            Contract.Requires(keys != null);
            Contract.Requires(comparer != null);
            Contract.Requires(left >= 0);
            Contract.Requires(length >= 0);
            Contract.Requires(length <= keys.Length);
            Contract.Requires(length + left <= keys.Length);

            if (length < 2)
                return;

            IntroSort(keys, left, length + left - 1, 2 * FloorLog2(keys.Length), comparer);
        }

        internal static int FloorLog2(int n)
        {
            int num = 0;
            while (n >= 1)
            {
                ++num;
                n /= 2;
            }
            return num;
        }

        private static void IntroSort(T[] keys, int lo, int hi, int depthLimit, IComparer<T> comparer)
        {
            Contract.Requires(keys != null);
            Contract.Requires(comparer != null);
            Contract.Requires(lo >= 0);
            Contract.Requires(hi < keys.Length);

            while (hi > lo)
            {
                int partitionSize = hi - lo + 1;
                if (partitionSize <= 16)
                {
                    if (partitionSize == 1)
                    {
                        return;
                    }
                    if (partitionSize == 2)
                    {
                        SwapIfGreater(keys, comparer, lo, hi);
                        return;
                    }
                    if (partitionSize == 3)
                    {
                        SwapIfGreater(keys, comparer, lo, hi - 1);
                        SwapIfGreater(keys, comparer, lo, hi);
                        SwapIfGreater(keys, comparer, hi - 1, hi);
                        return;
                    }

                    InsertionSort(keys, lo, hi, comparer);
                    return;
                }

                if (depthLimit == 0)
                {
                    Heapsort(keys, lo, hi, comparer);
                    return;
                }
                depthLimit--;

                int p = PickPivotAndPartition(keys, lo, hi, comparer);
                // Note we've already partitioned around the pivot and do not have to move the pivot again.
                IntroSort(keys, p + 1, hi, depthLimit, comparer);
                hi = p - 1;
            }
        }

        private static int PickPivotAndPartition(T[] keys, int lo, int hi, IComparer<T> comparer)
        {
            Contract.Requires(keys != null);
            Contract.Requires(comparer != null);
            Contract.Requires(lo >= 0);
            Contract.Requires(hi > lo);
            Contract.Requires(hi < keys.Length);
            Contract.Ensures(Contract.Result<int>() >= lo && Contract.Result<int>() <= hi);

            // Compute median-of-three.  But also partition them, since we've done the comparison.
            int middle = lo + ((hi - lo) / 2);

            // Sort lo, mid and hi appropriately, then pick mid as the pivot.
            SwapIfGreater(keys, comparer, lo, middle);  // swap the low with the mid point
            SwapIfGreater(keys, comparer, lo, hi);   // swap the low with the high
            SwapIfGreater(keys, comparer, middle, hi); // swap the middle with the high

            T pivot = keys[middle];
            Swap(keys, middle, hi - 1);
            int left = lo, right = hi - 1;  // We already partitioned lo and hi and put the pivot in hi - 1.  And we pre-increment & decrement below.

            while (left < right)
            {
                while (comparer.Compare(keys[++left], pivot) < 0) ;
                while (comparer.Compare(pivot, keys[--right]) < 0) ;

                if (left >= right)
                    break;

                Swap(keys, left, right);
            }

            // Put pivot in the right location.
            Swap(keys, left, (hi - 1));
            return left;
        }

        private static void Heapsort(T[] keys, int lo, int hi, IComparer<T> comparer)
        {
            Contract.Requires(keys != null);
            Contract.Requires(comparer != null);
            Contract.Requires(lo >= 0);
            Contract.Requires(hi > lo);
            Contract.Requires(hi < keys.Length);

            int n = hi - lo + 1;
            for (int i = n / 2; i >= 1; i = i - 1)
            {
                DownHeap(keys, i, n, lo, comparer);
            }
            for (int i = n; i > 1; i = i - 1)
            {
                Swap(keys, lo, lo + i - 1);
                DownHeap(keys, 1, i - 1, lo, comparer);
            }
        }

        private static void DownHeap(T[] keys, int i, int n, int lo, IComparer<T> comparer)
        {
            Contract.Requires(keys != null);
            Contract.Requires(comparer != null);
            Contract.Requires(lo >= 0);
            Contract.Requires(lo < keys.Length);

            T d = keys[lo + i - 1];
            int child;
            while (i <= n / 2)
            {
                child = 2 * i;
                if (child < n && comparer.Compare(keys[lo + child - 1], keys[lo + child]) < 0)
                {
                    child++;
                }
                if (!(comparer.Compare(d, keys[lo + child - 1]) < 0))
                    break;
                keys[lo + i - 1] = keys[lo + child - 1];
                i = child;
            }
            keys[lo + i - 1] = d;
        }

        private static void InsertionSort(T[] keys, int lo, int hi, IComparer<T> comparer)
        {
            Contract.Requires(keys != null);
            Contract.Requires(lo >= 0);
            Contract.Requires(hi >= lo);
            Contract.Requires(hi <= keys.Length);

            int i, j;
            T t;
            for (i = lo; i < hi; i++)
            {
                j = i;
                t = keys[i + 1];
                while (j >= lo && comparer.Compare(t, keys[j]) < 0)
                {
                    keys[j + 1] = keys[j];
                    j--;
                }
                keys[j + 1] = t;
            }
        }
    }
}

最后附上,测试用例:

using System;


namespace StructScript
{

    public class Fruit
    {
        public string name;
        public int num;
    }

    class TestList
    {
        static void Main(string[] args)
        {
            int[] arr = new int[] { 123, 121, 111, 123, 123 };
            ListScript<int> list__ = new ListScript<int>(arr);
            ShowData(list__);

            ListScript<int> list = new ListScript<int>();
            list.Add(1);
            list.Add(2);

            //需要实现IEnumerable<T>接口
            ListScript<int> list1 = new ListScript<int>() { 123, 121, 111, 123, 123 };
            list1.AddRange(list);

            ShowData(list1);

            Console.WriteLine("第一个匹配项的索引 " + list1.IndexOf(123));
            Console.WriteLine("最后一个匹配项的索引 " + list1.LastIndexOf(123));
            Console.WriteLine("返回列表是否包含特定的项" + list1.Contains(123));
            list1.Insert(2, 12);
            Console.WriteLine("在索引2的位置插入了12");
            ShowData(list1);
            Console.WriteLine("删除索引3位置的数据");
            list1.RemoveAt(3);
            ShowData(list1);
            Console.WriteLine("移除特定对象的第一个匹配项");
            list1.Remove(123);
            ShowData(list1);
            //Console.WriteLine("对列表进行排序");
            //list1.Sort();
            //ShowData(list1);
            Console.WriteLine("反转列表的元素 ");
            list1.Reverse();
            ShowData(list1);

            ListScript<Fruit> list2 = new ListScript<Fruit>();
            for (int i = 0; i < 5; i++)
            {
                Fruit apple = new Fruit();
                apple.name = "苹果";
                apple.num = i + 1;
                list2.Add(apple);
            }

            list2.Sort(SortDescend);
            //foreach语句中,第一次遇到Fruit对象时,调用GetEnumerator(),
            //当每次执行到in关键字,调用MoveNext()方法,每次读取数据则调用Current属性。
            foreach (Fruit item in list2)
            {
                Console.WriteLine(item.name + " " + item.num);
            }

            list2.Clear();
            foreach (Fruit item in list2)
            {
                Console.WriteLine(item.name + " " + item.num);
            }
            Console.ReadLine();
        }

        public static void ShowData(ListScript<int> list1)
        {
            int count = list1.Count;
            for (int i = 0; i < count; i++)
            {
                Console.Write(list1[i] + " ");
            }
            Console.WriteLine();
        }

        //指示 x 与 y 的相对值,如下表所示。值含义小于 0x 小于 y。0x 等于 y。大于 0x 大于 y。
        public static int SortDescend(Fruit fruit1, Fruit fruit2)
        {
            if (fruit1 == null && fruit2 == null)
            {
                return 0;
            }
            else if (fruit1 != null && fruit2 == null)
            {
                return 1;
            }
            else if (fruit1 == null && fruit2 != null)
            {
                return -1;
            }
            if (fruit1.num > fruit2.num)
            {
                return -1;
            }
            else if (fruit1.num < fruit2.num)
            {
                return 1;
            }
            return 1;
        }
    }
}

总结:

      在实现List<T>时,发现C#内部有两个Array.Copy和Buffer.BlockCopy拷贝方法,在刚开始的多维数组和一维数组的10000长度的数组拷贝测试中,直接把数组的数据长度count传入当做参数,Buffer.BlockCopy()执行效率比Array.Copy()好很多,尤其在一维数组的拷贝测试中,大约有4倍的优势。这时,我就想微软这是傻了吗,明明有更好用更快的接口,怎么List实现中用Array.Copy接口。

这里,犯一个很大的错误,所以才出现了这样的结果,请看下回分解:C#数据结构-Array.Copy和Buffer.BlockCopy详解

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
c# 数据结构的底层实现有两个例子可以说明。首先是Dictionary,它的底层实现是使用数组+单项链表的数据结构。具体来说,它包含了一个hashcode桶数组,用于指向当前桶的最后一个元素,以及一个Entry数组,用于存储所有的数据。每个Entry结构包含了hashcode、下一个元素在entries中的索引、Key和Value等信息。\[1\]\[2\] 另一个例子是Queue,它使用的是循环数组的结构。它包含了一个数组用于存储数据,以及First、Last和N等变量用于记录队列的状态。其中,First表示队列的第一个元素的索引,Last表示队列的最后一个元素的索引,N表示队列中元素的数量。通过循环数组的方式,可以实现队列的先进先出的特性。\[3\] 总结起来,c# 数据结构的底层实现可以根据具体的需求选择不同的数据结构,如数组+单项链表用于实现Dictionary,循环数组用于实现Queue等。这些底层实现的选择可以根据数据结构的特点和性能需求来进行优化。 #### 引用[.reference_title] - *1* *2* [C# 数据结构 - Dictionary](https://blog.csdn.net/qq_28019809/article/details/103805083)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [C# 内置数据结构类及其底层详解(1)--基于循环数组的队列Queue](https://blog.csdn.net/weixin_41372626/article/details/113548086)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值