Blink

纸上得来终觉浅,绝知此事要躬行

数据结构:动态数组

数组是我们经常用到的数据结构,创建数组时,我们需要定义数组的长度,计算机会在内存中开辟对应长度的一段连续的空间来存放数组,所以一般数组的长度是固定的,但是有些时候我们不能确定数组的长度,所以固定长度的数组就不太方便了。为了解决这个问题,像C#,Java等语言都提供了ArrayList供我们使用。

下面使用C#对原生数组进行封装,实现了一个DynamicArray(动态数组),主要实现了数组的增删改查基本功能,以及对数组进行动态扩容缩容

核心代码实现

using System;

public class DynamicArray<T>
{
    private T[] data = null;    // 存储数据的数组
    private int count = 0;      // 数组当前元素个数

    public DynamicArray(int capacity){
        data = new T[capacity];
        count = 0;
    }

    public DynamicArray() : this(10){}

    /// <summary>
    /// 数组中元素的个数
    /// </summary>
    public int Count{
        get{return count;}
    }

    /// <summary>
    /// 数组的容量
    /// </summary>
    public int Capacity{
        get{return data.Length;}
    }

    /// <summary>
    /// 数组是否为空
    /// </summary>
    public bool IsEmpty{
        get{return count == 0;}
    }

    /// <summary>
    /// 添加元素
    /// </summary>
    /// <param name="index">目标索引</param>
    /// <param name="value">需要添加的元素</param>
    public void Add(int index, T value){
        if(index < 0 || index > count) throw new IndexOutOfRangeException("数组索引越界");

        // 如果数组已满,就进行两倍扩容
        if(count == data.Length) 
            ResetCapacity(2 * data.Length);
        for(int i = count-1; i >= index; i--)
            data[i+1] = data[i];
        data[index] = value;
        count++;
    }

    /// <summary>
    /// 添加到数组头部
    /// </summary>
    /// <param name="value"></param>
    public void AddFirst(T value){
        Add(0,value);
    }

    /// <summary>
    /// 添加到数组尾部
    /// </summary>
    /// <param name="value"></param>
    public void AddLast(T value){
        Add(count,value);
    }

    /// <summary>
    /// 根据索引获取元素
    /// </summary>
    /// <param name="index"></param>
    /// <returns></returns>
    public T Get(int index){
        if(index < 0 || index >= count) throw new IndexOutOfRangeException("数组索引越界");
        return data[index];
    }

    /// <summary>
    /// 获取头部元素
    /// </summary>
    /// <returns></returns>
    public T GetFirst(){
        return data[0];
    }

    /// <summary>
    /// 获取尾部元素
    /// </summary>
    /// <returns></returns>
    public T GetLast(){
        return data[count-1];
    }

    /// <summary>
    /// 根据索引修改元素
    /// </summary>
    /// <param name="index"></param>
    /// <param name="newValue"></param>
    public void Set(int index,T newValue){
        if(index < 0 || index >= count) throw new IndexOutOfRangeException("数组索引越界");
        data[index] = newValue;
    }

    /// <summary>
    /// 数组是否包含元素
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    public bool Contains(T value){
        for (int i = 0; i < count; i++) {
            if(data[i].Equals(value)) return true;
        }
        return false;
    }

    /// <summary>
    /// 查找元素在数组中的位置
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    public int IndexOf(T value){
        for (int i = 0; i < count; i++) {
            if(data[i].Equals(value)) return i;
        }
        return -1;
    }

    /// <summary>
    /// 删除索引位置上的元素
    /// </summary>
    /// <param name="index"></param>
    /// <returns>删除的元素 </returns>
    public T RemoveAt(int index){
        if(index < 0 || index >= count) throw new IndexOutOfRangeException("数组索引越界");
        T delValue = data[index];
        for(int i = index; i < count - 1; i++){
            data[i] = data[i + 1];
        }
        count--;
        data[count] = default(T);

        // 如果数组元素个数只有容量的四分之一,就进行缩容操作
        // 防止频繁缩容扩容
        if(count == data.Length / 4)
            ResetCapacity(data.Length/2);

        return delValue;
    }

    /// <summary>
    /// 删除头部元素
    /// </summary>
    /// <returns></returns>
    public T RemoveFirst(){
        return RemoveAt(0);
    }

    /// <summary>
    /// 删除尾部元素
    /// </summary>
    /// <returns></returns>
    public T RemoveLast(){
        return RemoveAt(count - 1);
    }

    /// <summary>
    /// 删除元素
    /// </summary>
    /// <param name="value"></param>
    public void Remove(T value){
        int index = IndexOf(value);
        if(index != -1){
            RemoveAt(index);
        }
    }

    // 重置数组容量
    private void ResetCapacity(int newCapacity){
        T[] newData = new T[newCapacity];
        for(int i = 0; i < count; i++){
            newData[i] = data[i];
        }
        data = newData;
    }

    /// <summary>
    /// 重写ToString函数,方便打印信息
    /// </summary>
    /// <returns></returns>
    public override string ToString(){
        System.Text.StringBuilder strb = new System.Text.StringBuilder();
        strb.AppendFormat("DynamicArray: Count={0}  Capacity={1}\n",count,data.Length);
        strb.Append("[");
        for (int i = 0; i < count; i++) {
            strb.Append(data[i]);
            if(i != count-1)
                strb.Append(", ");
        }
        strb.Append("]");
        return strb.ToString();
    }
}

测试

class Program
{
    public static void Main(string[] args)
    {
        DynamicArray<int> arr = new DynamicArray<int>(10);
        for(int i = 1; i < 15; i++)
        {
            arr.AddFirst(i);
        }
        arr.AddLast(66);
        arr.Add(2,10);

        Console.WriteLine(arr);
        Console.WriteLine(arr.GetFirst());
        Console.WriteLine(arr.GetLast());
        Console.WriteLine(arr.Get(3));
        arr.Set(4,100);
        Console.WriteLine(arr);
        arr.RemoveAt(4);
        Console.WriteLine(arr); 
        Console.ReadKey(true);
    }
}

《数据结构:动态数组》

点赞

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注