数组是我们经常用到的数据结构,创建数组时,我们需要定义数组的长度,计算机会在内存中开辟对应长度的一段连续的空间来存放数组,所以一般数组的长度是固定的,但是有些时候我们不能确定数组的长度,所以固定长度的数组就不太方便了。为了解决这个问题,像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);
}
}
