注:本文仅供菜鸟和初级入门者参考,欢迎高手指导,切勿拍砖,兄弟身子骨单薄,承受不起。博客园原创文章,转载请注明作者和出处!

下面的代码包装了一个静态数组,它实现了上一节中 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("未实现的方法!");
            }

        }
    }
}

客户端测试文件: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();
        }
    }


}

运行效果如下:

未完待续........

数据结构入门(二)固定容量数组相关推荐

  1. 基础数据结构【二】————动态数组,单向链表及链表的反转

    DEMO1:     动态分配变量(链表,而静态数组是线性表,意味着动态数组访问和遍历复杂度为O(n),而插入和删除复杂度为O(1),而静态数组线性表则完全相反) int* intptr = new ...

  2. 【java进阶06:数组】使用一维数组模拟栈数据结构 使用二维数组模拟酒店,酒店管理系统 Arrays工具类 冒泡排序算法、选择排序算法、二分法

    目录 数组 二维数组 总结 作业 Arrays工具类 数组 数组总结 及 静态初始化一维数组 /* Array:1.java语言中的数组是一种引用数据类型,不属于基本数据类型,数组的父类是Object ...

  3. 29、数据结构笔记之二十九数组之硬币抛掷模拟

    29.数据结构笔记之二十九数组之硬币抛掷模拟 "人生是各种不同的变故.循环不已的痛苦和欢乐组成的.那种永远不变的蓝天只存在于心灵中间,向现实的人生去要求未免是奢望.-- 巴尔扎克" ...

  4. 数据结构入门(8) ——查找

    数据结构入门 --查找 文章目录 数据结构入门 --查找 前言 一.线性表查找 顺序查找 有序表的二分查找 对半(折半)查找 二叉判定树 对半查找总结 一致对半查找 斐波那契查找 插值查找 二.查找树 ...

  5. 数据结构入门(一级)

    数据结构和算法的入门:在这里我们先回答大家三个问题1. 为什么要学习数据结构2. 有哪些数据结构3. 学习数据结构的四种境界知道了这三个问题之后呢,再来进行具体内容的一个学习,先看第一个,为什么要学些 ...

  6. Java数据结构(1.1):数据结构入门+线性表、算法时间复杂度与空间复杂度、线性表、顺序表、单双链表实现、Java线性表、栈、队列、Java栈与队列。

    数据结构与算法入门 问题1:为什么要学习数据结构          如果说学习语文的最终目的是写小说的话,那么能不能在识字.组词.造句后就直接写小说了,肯定是不行的, 中间还有一个必经的阶段:就是写作 ...

  7. 《LeetCode》数据结构入门板块

    文章目录 <LeetCode题>数据结构入门板块 第1天 数组 217.存在重复元素[简单,哈希表] 53.最大子序和[简单,动态规划,贪心] 第2天 数组 1.两数之和[简单,哈希表] ...

  8. IM开发者的零基础通信技术入门(二):通信交换技术的百年发展史(下)

    1.系列文章引言 1.1 适合谁来阅读? 本系列文章尽量使用最浅显易懂的文字.图片来组织内容,力求通信技术零基础的人群也能看懂.但个人建议,至少稍微了解过网络通信方面的知识后再看,会更有收获.如果您大 ...

  9. Leetcode数据结构入门

    在预习数据结构,所以写了力扣的数据入门题单,做个整理. Leetcode数据结构入门 第一天--第五天:数组 第六天:字符串 第七天--第八天:链表 第九天:队列/栈 第十天--第十四天:树 第一天 ...

  10. 【数据结构入门】栈(Stack)的实现(定义、销毁、入栈、出栈等) | 图解数据结构,超详细哦~

    文章目录 (1)前言 1)栈的概念 2)进栈出栈的形式 3)栈的存储结构 (2)栈的实现(顺序栈) 1)栈的定义 2)栈的初始化 3)栈的销毁 4)入栈 5)出栈 6)检测栈是否为空 7)获取栈中有效 ...

最新文章

  1. pyinstaller打包exe文件闪退解决方案
  2. UC伯克利给四足机器人加Buff:瞬间适应各种真实地形,抹了油的地面也能hold住...
  3. C#设计模式学习笔记-单例模式
  4. 二阶偏微分方程组 龙格库塔法_深度科普---电磁波(三):无激励下的真空中的Maxwell方程组的解...
  5. php 图像编程库,PHP图像处理开发库
  6. Bailian2925 大整数的因子【模除】
  7. NoSuchObjectException(message:ods_db.event table not found)
  8. 从零实现深度学习框架——实现常见运算的计算图(上)
  9. Xen和KVM的guest主机热添加硬盘
  10. [c++]小数处理ceil, floor, round
  11. 阿里云企业邮箱2019
  12. 笔记本运行php的快捷键是啥,雷神笔记本u盘启动快捷键是什么|雷神笔记本按哪个键进u盘启动...
  13. kmeans python interation flag_机器学习经典算法-logistic回归代码详解
  14. python保存不了_python文件无法保存怎么解决
  15. HDU-1493 QQpet exploratory park(概率+二维dp)
  16. 阅读笔记之《守破离》
  17. 实验9、键盘扫描及数码管显示实验
  18. O_DIRECT打开文件失败
  19. 强化学习(一) - 基础认知
  20. 给想报考CISP的朋友

热门文章

  1. 警告:MySQL-server-5.6.26-1.el7.x86_64.rpm: 头V3 DSA/SHA1 Signature, 密钥 ID 5072e1f5: NOKEY
  2. 大型架构之科普工具篇
  3. 哲学家就餐问题 C语言实现
  4. 转iOS深拷贝与浅拷贝 附NSSet讲解
  5. 一个C#控制台小游戏(源码解析)
  6. CAS、AQS、锁以及并发工具
  7. 辗转相除法求最小公约数
  8. “adb server is out of date.
  9. 网站左边栏制作的小技巧
  10. vue.js实现联动效果