注:本文仅供菜鸟和初级入门者参考,欢迎高手指导,切勿拍砖,兄弟身子骨单薄,承受不起。博客园原创文章,转载请注明作者和出处!
下面的代码包装了一个静态数组,它实现了上一节中 IList<T> 接口的全部功能;为了具有排序功能,同时实现了 ISortable<T> 接口。关于 IList<T> 接口和 ISortable<T> 接口请参见上一部分 数据结构入门(一)基本接口的设计。类名起为 FixedList<T> 表明数组的大小在对象构造后就不可改变,可自动扩展大小的数组会在下一节实现。
FixedList<T> 只具有一些最基本的功能。代码都有注释,十分简单。
在客户端测试 FixedList<T> 的时候,为数组设置了一个冒泡排序算法 ,排序的具体实现将在后面给出。
Arrays.cs 文件:
using System;
using System.Collections.Generic;
using System.Text;
namespace My
{
namespace Collections
{
/// <summary>
/// 固定容量数组
/// </summary>
/// <typeparam name="T">实现了 Equals() 方法的数据类型</typeparam>
public class FixedList<T> : IList<T>, ISortable<T>
{
/// <summary>
/// 被包装的数组
/// </summary>
private T[] elements;
/// <summary>
/// 数组的最大容量
/// </summary>
private int capacity;
/// <summary>
/// 当前数组存储的数据个数
/// </summary>
private int count;
/// <summary>
/// 选择的排序类,运用策略模式,选择不同的排序类会调用不同的排序方法
/// </summary>
private ISort<T> sort;
/// <summary>
/// 验证容量是否有效,无效抛出异常
/// </summary>
/// <param name="capacity">数组的最大容量,应该大于等于零</param>
private void CapacityCheck(int capacity)
{
if (capacity < 0)
{
string str = String.Format("无效的数组容量: {0}", capacity);
throw new CollectionsException(str);
}
}
/// <summary>
/// 检查数组是否已满,已满则抛出异常
/// </summary>
/// <param name="capacity">数组的最大容量,应该大于等于零</param>
/// <param name="count">当前数组存储的数据个数,范围从 0 到 capacity - 1</param>
private void FullCheck(int capacity, int count)
{
if (count == capacity)
{
string str = String.Format("数组已满,无法继续添加数据。当前数组容量为 {0} !", capacity);
throw new CollectionsException(str);
}
}
/// <summary>
/// 检查索引是否有效,无效则抛出异常
/// </summary>
/// <param name="index">索引,范围从 0 到 count - 1</param>
/// <param name="count">当前数组存储的数据个数,范围从 0 到 capacity - 1</param>
private void IndexCheck(int index, int count)
{
if ((index > count - 1) || (index < 0))
{
string str = String.Format("访问越界:当前数组有 {0} 个元素,试图访问索引为号 {1} 的元素!", count, index);
throw new CollectionsException(str);
}
}
/// <summary>
/// 构造函数,申请数组空间
/// </summary>
/// <param name="capacity">设定数组的最大容量</param>
public FixedList(int capacity)
{
CapacityCheck(capacity);
this.capacity = capacity;
elements = new T[capacity];
count = 0;
}
/// <summary>
/// 返回数组容量
/// </summary>
public int Capacity
{
get { return capacity; }
}
/// <summary>
///返回当前数组内元素个数
/// </summary>
public int Count
{
get { return count; }
}
/// <summary>
/// 判断数组是否为空
/// </summary>
public bool IsEmpty
{
get { return (count == 0); }
}
/// <summary>
/// 判断数组是否已满
/// </summary>
public bool IsFull
{
get { return (count == capacity); }
}
/// <summary>
/// 设定一个排序类,数组将会用此类包装的排序方法进行排序
/// </summary>
public ISort<T> Sort
{
set { this.sort = value; }
}
/// <summary>
/// 发出排序动作
/// </summary>
public void DoSort()
{
this.sort.Do(this);
}
/// <summary>
/// 遍历数组,将所有元素的值设为默认值
/// </summary>
public void Clear()
{
for (int i = 0; i < count; i++)
{
elements[i] = default(T);
}
count = 0;
}
/// <summary>
/// 将数据添加到数组的尾部,数组已满则抛出异常
/// </summary>
/// <param name="data">需要添加的数据</param>
public void Add(T data)
{
FullCheck(capacity, count);
elements[count] = data;
count++;
}
/// <summary>
/// 在某一位置插入数据,并向后移动其他数据,数组已满则抛出异常
/// </summary>
/// <param name="index">数据插入的位置,无效则抛出异常</param>
/// <param name="data">需要插入的数据</param>
public void Insert(int index, T data)
{
FullCheck(capacity, count);
IndexCheck(index, count);
System.Array.Copy(elements, index, elements, index + 1, count - index);
elements[index] = data;
count++;
}
/// <summary>
/// 从位置 fromIndex 开始查找第一个符合的数据,并返回其的位置
/// </summary>
/// <param name="data">要查找的数据</param>
/// <param name="fromIndex">开始查找的位置</param>
/// <returns>找到则返回数据所在位置,没找到则返回 -1</returns>
private int IndexOf(T data, int fromIndex)
{
IndexCheck(fromIndex, count);
for (int i = fromIndex; i < count; i++)
if (data.Equals(elements[i]))
{
return i;
}
return -1;
}
/// <summary>
/// 从头开始查找,直到找到第一个符合的数据,并返回其的位置
/// </summary>
/// <param name="data">要查找的数据</param>
/// <returns>找到则返回数据所在位置,没找到则返回 -1</returns>
public int IndexOf(T data)
{
return IndexOf(data, 0);
}
/// <summary>
/// 判断一个数据是否在数组中存在
/// </summary>
/// <param name="data">要查找的数据</param>
/// <returns>找到则返回 true ,没找到则返回 false</returns>
public bool Find(T data)
{
return IndexOf(data) >= 0;
}
/// <summary>
/// 返回和设置某一位置的数据
/// </summary>
/// <param name="index">位置</param>
/// <returns>数据元素</returns>
public T this[int index]
{
get
{
IndexCheck(index, count);
return elements[index];
}
set
{
IndexCheck(index, count);
elements[index] = value;
}
}
/// <summary>
/// 删除某一位置的数据,并前移动其后数据,以填充留出的空位
/// </summary>
/// <param name="index">要删除数据的位置</param>
public void RemoveAt(int index)
{
IndexCheck(index, count);
if (index < count - 1)
{
System.Array.Copy(elements, index + 1, elements, index, count - index - 1);
}
// 如果要删除的数据是最后一项,则不需要移动,直接 count-- 丢弃他就行了
count--;
}
/// <summary>
/// 查找第一个符合的数据并删除,并向前移动其后数据,以填充留出的空位
/// </summary>
/// <param name="data">要删除的数据</param>
public void Remove(T data)
{
int index = IndexOf(data);
if (index >= 0) RemoveAt(index);
}
/// <summary>
/// 删除所有符合的数据,并前移动其后数据,以填充留出的空位
/// </summary>
/// <param name="data">要删除的数据</param>
public void RemoveAll(T data)
{
int index = IndexOf(data, 0);
while (index >= 0)
{
RemoveAt(index);
index = IndexOf(data, index);
}
}
/// <summary>
/// 枚举器
/// </summary>
/// <returns></returns>
public IEnumerator<T> GetEnumerator()
{
for (int i = 0; i < count; i++)
yield return elements[i];
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
throw new Exception("未实现的方法!");
}
}
}
}
using System.Collections.Generic;
using System.Text;
namespace My
{
namespace Collections
{
/// <summary>
/// 固定容量数组
/// </summary>
/// <typeparam name="T">实现了 Equals() 方法的数据类型</typeparam>
public class FixedList<T> : IList<T>, ISortable<T>
{
/// <summary>
/// 被包装的数组
/// </summary>
private T[] elements;
/// <summary>
/// 数组的最大容量
/// </summary>
private int capacity;
/// <summary>
/// 当前数组存储的数据个数
/// </summary>
private int count;
/// <summary>
/// 选择的排序类,运用策略模式,选择不同的排序类会调用不同的排序方法
/// </summary>
private ISort<T> sort;
/// <summary>
/// 验证容量是否有效,无效抛出异常
/// </summary>
/// <param name="capacity">数组的最大容量,应该大于等于零</param>
private void CapacityCheck(int capacity)
{
if (capacity < 0)
{
string str = String.Format("无效的数组容量: {0}", capacity);
throw new CollectionsException(str);
}
}
/// <summary>
/// 检查数组是否已满,已满则抛出异常
/// </summary>
/// <param name="capacity">数组的最大容量,应该大于等于零</param>
/// <param name="count">当前数组存储的数据个数,范围从 0 到 capacity - 1</param>
private void FullCheck(int capacity, int count)
{
if (count == capacity)
{
string str = String.Format("数组已满,无法继续添加数据。当前数组容量为 {0} !", capacity);
throw new CollectionsException(str);
}
}
/// <summary>
/// 检查索引是否有效,无效则抛出异常
/// </summary>
/// <param name="index">索引,范围从 0 到 count - 1</param>
/// <param name="count">当前数组存储的数据个数,范围从 0 到 capacity - 1</param>
private void IndexCheck(int index, int count)
{
if ((index > count - 1) || (index < 0))
{
string str = String.Format("访问越界:当前数组有 {0} 个元素,试图访问索引为号 {1} 的元素!", count, index);
throw new CollectionsException(str);
}
}
/// <summary>
/// 构造函数,申请数组空间
/// </summary>
/// <param name="capacity">设定数组的最大容量</param>
public FixedList(int capacity)
{
CapacityCheck(capacity);
this.capacity = capacity;
elements = new T[capacity];
count = 0;
}
/// <summary>
/// 返回数组容量
/// </summary>
public int Capacity
{
get { return capacity; }
}
/// <summary>
///返回当前数组内元素个数
/// </summary>
public int Count
{
get { return count; }
}
/// <summary>
/// 判断数组是否为空
/// </summary>
public bool IsEmpty
{
get { return (count == 0); }
}
/// <summary>
/// 判断数组是否已满
/// </summary>
public bool IsFull
{
get { return (count == capacity); }
}
/// <summary>
/// 设定一个排序类,数组将会用此类包装的排序方法进行排序
/// </summary>
public ISort<T> Sort
{
set { this.sort = value; }
}
/// <summary>
/// 发出排序动作
/// </summary>
public void DoSort()
{
this.sort.Do(this);
}
/// <summary>
/// 遍历数组,将所有元素的值设为默认值
/// </summary>
public void Clear()
{
for (int i = 0; i < count; i++)
{
elements[i] = default(T);
}
count = 0;
}
/// <summary>
/// 将数据添加到数组的尾部,数组已满则抛出异常
/// </summary>
/// <param name="data">需要添加的数据</param>
public void Add(T data)
{
FullCheck(capacity, count);
elements[count] = data;
count++;
}
/// <summary>
/// 在某一位置插入数据,并向后移动其他数据,数组已满则抛出异常
/// </summary>
/// <param name="index">数据插入的位置,无效则抛出异常</param>
/// <param name="data">需要插入的数据</param>
public void Insert(int index, T data)
{
FullCheck(capacity, count);
IndexCheck(index, count);
System.Array.Copy(elements, index, elements, index + 1, count - index);
elements[index] = data;
count++;
}
/// <summary>
/// 从位置 fromIndex 开始查找第一个符合的数据,并返回其的位置
/// </summary>
/// <param name="data">要查找的数据</param>
/// <param name="fromIndex">开始查找的位置</param>
/// <returns>找到则返回数据所在位置,没找到则返回 -1</returns>
private int IndexOf(T data, int fromIndex)
{
IndexCheck(fromIndex, count);
for (int i = fromIndex; i < count; i++)
if (data.Equals(elements[i]))
{
return i;
}
return -1;
}
/// <summary>
/// 从头开始查找,直到找到第一个符合的数据,并返回其的位置
/// </summary>
/// <param name="data">要查找的数据</param>
/// <returns>找到则返回数据所在位置,没找到则返回 -1</returns>
public int IndexOf(T data)
{
return IndexOf(data, 0);
}
/// <summary>
/// 判断一个数据是否在数组中存在
/// </summary>
/// <param name="data">要查找的数据</param>
/// <returns>找到则返回 true ,没找到则返回 false</returns>
public bool Find(T data)
{
return IndexOf(data) >= 0;
}
/// <summary>
/// 返回和设置某一位置的数据
/// </summary>
/// <param name="index">位置</param>
/// <returns>数据元素</returns>
public T this[int index]
{
get
{
IndexCheck(index, count);
return elements[index];
}
set
{
IndexCheck(index, count);
elements[index] = value;
}
}
/// <summary>
/// 删除某一位置的数据,并前移动其后数据,以填充留出的空位
/// </summary>
/// <param name="index">要删除数据的位置</param>
public void RemoveAt(int index)
{
IndexCheck(index, count);
if (index < count - 1)
{
System.Array.Copy(elements, index + 1, elements, index, count - index - 1);
}
// 如果要删除的数据是最后一项,则不需要移动,直接 count-- 丢弃他就行了
count--;
}
/// <summary>
/// 查找第一个符合的数据并删除,并向前移动其后数据,以填充留出的空位
/// </summary>
/// <param name="data">要删除的数据</param>
public void Remove(T data)
{
int index = IndexOf(data);
if (index >= 0) RemoveAt(index);
}
/// <summary>
/// 删除所有符合的数据,并前移动其后数据,以填充留出的空位
/// </summary>
/// <param name="data">要删除的数据</param>
public void RemoveAll(T data)
{
int index = IndexOf(data, 0);
while (index >= 0)
{
RemoveAt(index);
index = IndexOf(data, index);
}
}
/// <summary>
/// 枚举器
/// </summary>
/// <returns></returns>
public IEnumerator<T> GetEnumerator()
{
for (int i = 0; i < count; i++)
yield return elements[i];
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
throw new Exception("未实现的方法!");
}
}
}
}
客户端测试文件:Client.cs
using System;
using System.Collections.Generic;
using System.Text;
using My.Collections;
namespace Client
{
class Program
{
static void Main(string[] args)
{
try
{
FixedList<int> arr = new FixedList<int>(18);
arr.Add(36);
arr.Add(16);
arr.Add(36);
arr.Add(36);
arr.Add(27);
arr.Add(36);
arr.Add(36);
arr.Add(36);
arr.Add(99);
arr.Add(36);
arr.Add(16);
arr.Add(36);
arr.Add(999);
arr.Add(1);
Console.Write("显示当前数据:");
foreach (int i in arr)
Console.Write(i + " ");
Console.WriteLine("\n");
Console.WriteLine("数组容量:" + arr.Capacity);
Console.WriteLine("元素个数:" + arr.Count);
Console.WriteLine("查找数据27:" + arr.Find(27));
Console.WriteLine("查找数据72:" + arr.Find(72));
Console.WriteLine("定位数据99:" + arr.IndexOf(99));
Console.WriteLine("定位数据123:" + arr.IndexOf(123));
Console.WriteLine("删除所有36");
arr.RemoveAll(36);
Console.Write("显示当前数据:");
foreach (int i in arr)
Console.Write(i + " ");
Console.WriteLine("\n");
Console.WriteLine("删除最后一个数据");
arr.RemoveAt(arr.Count - 1);
Console.Write("显示当前数据:");
foreach (int i in arr)
Console.Write(i + " ");
Console.WriteLine("\n");
Console.WriteLine("数组容量:" + arr.Capacity);
Console.WriteLine("元素个数:" + arr.Count);
//注意:这里用到了一个 BubleSort<T> 的排序类,
//它仅仅是一个包装了冒泡排序算法的类,实现了 ISort<T> 接口,后面将会介绍它
Console.WriteLine("用冒泡法排序");
arr.Sort=new BubbleSort<int>();
arr.DoSort();
Console.Write("显示当前数据:");
foreach (int i in arr)
Console.Write(i + " ");
Console.WriteLine("\n");
Console.WriteLine("当前数组是否为空::" + arr.IsEmpty);
Console.WriteLine("清空数组");
arr.Clear();
Console.WriteLine("当前数组是否为空::" + arr.IsEmpty);
Console.Write("显示当前数据:");
foreach (int i in arr)
Console.Write(i + " ");
Console.WriteLine("\n");
}
catch (Exception e)
{
Console.WriteLine(e.Message );
}
Console.Read();
}
}
}
using System.Collections.Generic;
using System.Text;
using My.Collections;
namespace Client
{
class Program
{
static void Main(string[] args)
{
try
{
FixedList<int> arr = new FixedList<int>(18);
arr.Add(36);
arr.Add(16);
arr.Add(36);
arr.Add(36);
arr.Add(27);
arr.Add(36);
arr.Add(36);
arr.Add(36);
arr.Add(99);
arr.Add(36);
arr.Add(16);
arr.Add(36);
arr.Add(999);
arr.Add(1);
Console.Write("显示当前数据:");
foreach (int i in arr)
Console.Write(i + " ");
Console.WriteLine("\n");
Console.WriteLine("数组容量:" + arr.Capacity);
Console.WriteLine("元素个数:" + arr.Count);
Console.WriteLine("查找数据27:" + arr.Find(27));
Console.WriteLine("查找数据72:" + arr.Find(72));
Console.WriteLine("定位数据99:" + arr.IndexOf(99));
Console.WriteLine("定位数据123:" + arr.IndexOf(123));
Console.WriteLine("删除所有36");
arr.RemoveAll(36);
Console.Write("显示当前数据:");
foreach (int i in arr)
Console.Write(i + " ");
Console.WriteLine("\n");
Console.WriteLine("删除最后一个数据");
arr.RemoveAt(arr.Count - 1);
Console.Write("显示当前数据:");
foreach (int i in arr)
Console.Write(i + " ");
Console.WriteLine("\n");
Console.WriteLine("数组容量:" + arr.Capacity);
Console.WriteLine("元素个数:" + arr.Count);
//注意:这里用到了一个 BubleSort<T> 的排序类,
//它仅仅是一个包装了冒泡排序算法的类,实现了 ISort<T> 接口,后面将会介绍它
Console.WriteLine("用冒泡法排序");
arr.Sort=new BubbleSort<int>();
arr.DoSort();
Console.Write("显示当前数据:");
foreach (int i in arr)
Console.Write(i + " ");
Console.WriteLine("\n");
Console.WriteLine("当前数组是否为空::" + arr.IsEmpty);
Console.WriteLine("清空数组");
arr.Clear();
Console.WriteLine("当前数组是否为空::" + arr.IsEmpty);
Console.Write("显示当前数据:");
foreach (int i in arr)
Console.Write(i + " ");
Console.WriteLine("\n");
}
catch (Exception e)
{
Console.WriteLine(e.Message );
}
Console.Read();
}
}
}
运行效果如下:
本文转自左洸博客园博客,原文链接:http://www.cnblogs.com/myqiao/archive/2006/01/21/321141.html,如需转载请自行联系原作者