zoukankan      html  css  js  c++  java
  • 数据结构之动态数组

    1.静态数组是不可以更改数组长度的

    2.动态数据组:ArrayList,List(泛型)。动态数组本质上就是数组,是由静态数组封装的一些扩容能力。

    下面看一下动态数组的底层实现原理,并创建属于自己的动态数组,

      public class MyArray
        {
            //设置私有,防止用户私自查看更改。
            private int[] data;
            //表示此数组目前数组实际存储元素数量
            private int N;
    
    
            #region  设置外部可以查看数组信息的属性方法
    
            /// <summary>
            /// 在这里构造整个数组的长度
            /// </summary>
            /// <param name="capacity"></param>
            public MyArray(int capacity)
            {
                data = new int[capacity];
                N = 0;
            }
            /// <summary>
            /// 因为目前要做动态数组,所以我们可以在无参构造函数这里
            /// 先默认一个长度,比如10。
            /// </summary>
            //public MyArray()
            //{
            //    data = new int[10];
            //    N = 0;
            //}
    
            //注意这个写法和上面注释的无参构造函数一样,
            //只不过是借用了有参构造函数,往里面传入了一个定死的值。
            public MyArray() : this(10)
            {
            }
            /// <summary>
            /// 数组长度
            /// </summary>
            public int Length
            {
                get
                {
                    return data.Length;
                }
            }
            /// <summary>
            /// 数组实际存储数量
            /// </summary>
            public int Count
            {
                get
                {
                    return N;
                }
            }
            /// <summary>
            /// 可以看数组元素是否为空
            /// </summary>
            public bool IsNull
            {
                get
                {
                    return N == 0;
                }
            }
            #endregion
    
    
            #region 添加数组
            /// <summary>
            /// 添加方法
            /// </summary>
            /// <param name="index"></param>
            /// <param name="v"></param>
            public void Add(int index, int v)
            {
                //前提要看长度是否足够
                if (index < 0 || index > N)
                {
                    throw new Exception("数组索引越界上");
                }
                if (N == data.Length)
                {
                    throw new Exception("数组已满");
                }
    
                //首先要将index后面的值依次往后移动一位,防止值被覆盖
                for (int i = N - 1; i >= index; i--)
                {
                    data[i + 1] = data[i];
                }
    
                //赋值
                data[index] = v;
                N++;//元素数量加一
    
            }
            /// <summary>
            /// 末尾添加
            /// </summary>
            /// <param name="v"></param>
            public void AddLast(int v)
            {
                Add(N, v);
            }
            /// <summary>
            /// 头部添加
            /// </summary>
            /// <param name="v"></param>
            public void AddFirst(int v)
            {
                Add(0, v);
            }
    
            #endregion
    
            #region 获取  修改  删除
    
            public int Get(int index)
            {
                //确认索引合法性
                if (index < 0 || index >= N)
                {
                    throw new Exception("索引超出数组长度");
                }
    
                return data[index];
            }
    
            public int RemoveAt(int index)
            {
                if (index < 0 || index >= N)
                {
                    throw new Exception("索引超出数组长度");
                }
    
                int del = data[index];
                //被删除当前元素的后面值依次向前回退一步
                for (int i = index - 1; i <= N - 1; i++)
                {
                    data[i - 1] = data[i];
                }
    
                N--;
                //给最高位默认值,因为此时还未实现数组的缩容,暂时这样处理
                data[N] = default(int);
                return del;
            }
            /// <summary>
            /// 重写tosting,按照指定的方式输出
            /// </summary>
            /// <returns></returns>
            public override string ToString()
            {
                //按照自己的喜好重写
                return "";
            }
    
            #endregion
        }

    下面实现自定义数组的扩容,缩容功能  下面在增加元素和删除元素的时候都自动进行判断是否需要进行扩容和缩容

        public class MyArray
        {
            //设置私有,防止用户私自查看更改。
            private int[] data;
            //表示此数组目前数组实际存储元素数量
            private int N;
    
    
            #region  设置外部可以查看数组信息的属性方法
    
            /// <summary>
            /// 在这里构造整个数组的长度
            /// </summary>
            /// <param name="capacity"></param>
            public MyArray(int capacity)
            {
                data = new int[capacity];
                N = 0;
            }
            /// <summary>
            /// 因为目前要做动态数组,所以我们可以在无参构造函数这里
            /// 先默认一个长度,比如10。
            /// </summary>
            //public MyArray()
            //{
            //    data = new int[10];
            //    N = 0;
            //}
    
            //注意这个写法和上面注释的无参构造函数一样,
            //只不过是借用了有参构造函数,往里面传入了一个定死的值。
            public MyArray() : this(10)
            {
            }
            /// <summary>
            /// 数组长度
            /// </summary>
            public int Length
            {
                get
                {
                    return data.Length;
                }
            }
            /// <summary>
            /// 数组实际存储数量
            /// </summary>
            public int Count
            {
                get
                {
                    return N;
                }
            }
            /// <summary>
            /// 可以看数组元素是否为空
            /// </summary>
            public bool IsNull
            {
                get
                {
                    return N == 0;
                }
            }
            #endregion
    
    
            #region 添加数组
            /// <summary>
            /// 添加方法
            /// </summary>
            /// <param name="index"></param>
            /// <param name="v"></param>
            public void Add(int index, int v)
            {
                //前提要看长度是否足够
                if (index < 0 || index > N)
                {
                    throw new Exception("数组索引越界上");
                }
                if (N == data.Length)
                {
                    //扩大一倍
                    ResetCapacity(N * 2);
                    //  throw new Exception("数组已满");
                }
    
                //首先要将index后面的值依次往后移动一位,防止值被覆盖
                for (int i = N - 1; i >= index; i--)
                {
                    data[i + 1] = data[i];
                }
    
                //赋值
                data[index] = v;
                N++;//元素数量加一
    
            }
            /// <summary>
            /// 末尾添加
            /// </summary>
            /// <param name="v"></param>
            public void AddLast(int v)
            {
                Add(N, v);
            }
            /// <summary>
            /// 头部添加
            /// </summary>
            /// <param name="v"></param>
            public void AddFirst(int v)
            {
                Add(0, v);
            }
    
            #endregion
    
            #region 获取  修改  删除
    
            public int Get(int index)
            {
                //确认索引合法性
                if (index < 0 || index >= N)
                {
                    throw new Exception("索引超出数组长度");
                }
    
                return data[index];
            }
    
            public int RemoveAt(int index)
            {
                if (index < 0 || index >= N)
                {
                    throw new Exception("索引超出数组长度");
                }
                //如果元素数量不足长度4分之一,进行缩容,减少空间使用。
                if (N != data.Length / 4)
                {
                    //缩小一半
                    ResetCapacity(data.Length / 2);
                }
    
    
                int del = data[index];
                //被删除当前元素的后面值依次向前回退一步
                for (int i = index - 1; i <= N - 1; i++)
                {
                    data[i - 1] = data[i];
                }
    
                N--;
                //给最高位默认值,因为此时还未实现数组的缩容,暂时这样处理
                data[N] = default(int);
                return del;
            }
            /// <summary>
            /// 重写tosting,按照指定的方式输出
            /// </summary>
            /// <returns></returns>
            public override string ToString()
            {
                //按照自己的喜好重写
                return "";
            }
    
            #endregion
    
            #region 动态扩容 缩容
    
            private void ResetCapacity(int newLength)
            {
                int[] newData = new int[newLength];
                //将旧有数据复制到扩容后的新数组中
                data.CopyTo(newData, 0);
                //赋值给原有数组 注意此时给data的是引用,data中数据更改newData同样会变
                data = newData; 
            }
    
    
            #endregion
    
    
        }

    但是上面的代码只能int,所以用泛型实现多类型。类似List泛型类

     public class MyArray<T>
        {
            //设置私有,防止用户私自查看更改。
            private T[] data;
            //表示此数组目前数组实际存储元素数量
            private int N;
    
    
            #region  设置外部可以查看数组信息的属性方法
    
            /// <summary>
            /// 在这里构造整个数组的长度
            /// </summary>
            /// <param name="capacity"></param>
            public MyArray(int capacity)
            {
                data = new T[capacity];
                N = 0;
            }
            /// <summary>
            /// 因为目前要做动态数组,所以我们可以在无参构造函数这里
            /// 先默认一个长度,比如10。
            /// </summary>
            //public MyArray()
            //{
            //    data = new int[10];
            //    N = 0;
            //}
    
            //注意这个写法和上面注释的无参构造函数一样,
            //只不过是借用了有参构造函数,往里面传入了一个定死的值。
            public MyArray() : this(10)
            {
            }
            /// <summary>
            /// 数组长度
            /// </summary>
            public int Length
            {
                get
                {
                    return data.Length;
                }
            }
            /// <summary>
            /// 数组实际存储数量
            /// </summary>
            public int Count
            {
                get
                {
                    return N;
                }
            }
            /// <summary>
            /// 可以看数组元素是否为空
            /// </summary>
            public bool IsNull
            {
                get
                {
                    return N == 0;
                }
            }
            #endregion
    
    
            #region 添加数组
            /// <summary>
            /// 添加方法
            /// </summary>
            /// <param name="index"></param>
            /// <param name="v"></param>
            public void Add(int index, T v)
            {
                //前提要看长度是否足够
                if (index < 0 || index > N)
                {
                    throw new Exception("数组索引越界上");
                }
                if (N == data.Length)
                {
                    //扩大一倍
                    ResetCapacity(N * 2);
                    //  throw new Exception("数组已满");
                }
    
                //首先要将index后面的值依次往后移动一位,防止值被覆盖
                for (int i = N - 1; i >= index; i--)
                {
                    data[i + 1] = data[i];
                }
    
                //赋值
                data[index] = v;
                N++;//元素数量加一
    
            }
            /// <summary>
            /// 末尾添加
            /// </summary>
            /// <param name="v"></param>
            public void AddLast(T v)
            {
                Add(N, v);
            }
            /// <summary>
            /// 头部添加
            /// </summary>
            /// <param name="v"></param>
            public void AddFirst(T v)
            {
                Add(0, v);
            }
    
            #endregion
    
            #region 获取  修改  删除
    
            public T Get(int index)
            {
                //确认索引合法性
                if (index < 0 || index >= N)
                {
                    throw new Exception("索引超出数组长度");
                }
    
                return data[index];
            }
    
            public T RemoveAt(int index)
            {
                if (index < 0 || index >= N)
                {
                    throw new Exception("索引超出数组长度");
                }
                //如果元素数量不足长度4分之一,进行缩容,减少空间使用。
                if (N != data.Length / 4)
                {
                    //缩小一半
                    ResetCapacity(data.Length / 2);
                }
    
    
                T del = data[index];
                //被删除当前元素的后面值依次向前回退一步
                for (int i = index - 1; i <= N - 1; i++)
                {
                    data[i - 1] = data[i];
                }
    
                N--;
                //给最高位默认值,因为此时还未实现数组的缩容,暂时这样处理
                data[N] = default(T);
                return del;
            }
            /// <summary>
            /// 重写tosting,按照指定的方式输出
            /// </summary>
            /// <returns></returns>
            public override string ToString()
            {
                //按照自己的喜好重写
                return "";
            }
    
            #endregion
    
            #region 动态扩容 缩容
    
            private void ResetCapacity(int newLength)
            {
                T[] newData = new T[newLength];
                //将旧有数据复制到扩容后的新数组中
                data.CopyTo(newData, 0);
                //赋值给原有数组 注意此时给data的是引用,data中数据更改newData同样会变
                data = newData; 
            }
    
    
            #endregion
    
    
        }
  • 相关阅读:
    How to print GETDATE() in SQL Server with milliseconds in time?
    StarLink卫星网络如何工作
    Chinasat16
    天线增益计算
    Schemachine
    源代码之整洁代码
    关于进程内缓存与分布式缓存
    IOT物联网时代测试演化
    互联网大促运维实践案例
    Kubernetes应用场景
  • 原文地址:https://www.cnblogs.com/anjingdian/p/15164783.html
Copyright © 2011-2022 走看看