1、何为数组
数组是一片连续的内存空间,里面存放的元素是有序地排放着的。
2、何为索引
对于使用数组来说,一个非常重要的内容就是数字的这个索引,这个索引是可以有语意的也可以没有语意的,这是什么意思呢?换句话说data[2]我这样来写这个二可以有一个实际的意义。比如说对于这八个同学他们是有学号的他们的学号分别是01234567。那么我调用是data[2],其实就相当于我看学号是二的这个同学他得了多少分。这个2有实际的语意的。当然也可以没有语意,也就是说我这个data 01234567就是简单的它存放在第几个元素而已。他不代表这个学生的学号,也不代表任何东西,就是恰好在二这个位置存了一个分,这个分可能是66分,他们这个66分存在三的位置也可以,存在七的位置也可以。事实上存在这个数组的任何一个位置都可以。这是因为这个索引是没有语意的,我们可能只需要把这样的一个66分存起来存在我的数组中而已,这就是我们的索引没有语意。
3、数组的优点
对于我们使用数组他最大的优点就是,可以快速查询,我们如果知道我们要查看的是索引为二在数组中的元素是多少,我们直接调data[2]就好了。也正是因为这个原因,我们如果使用数组的话,最好应用于这个索引有语意的情况。换句话说我们知道在查什么,我们在查学号为二的这个同学她相应的成绩是多少,直接使用这种方括号的查询方式就好了。如果我们的应用场景这个索引没有语意的话,很有可能使用别的数据结构是一个更好的选择。在这这里中后续会讲非常多的数据结构,等大家积累多了数据结构相关的知识,可以到时候再把他们放在一起比较一下,看看再什么场景使用什么样的数据结构是最好的
4、如何使用索引
但是虽然如此,要知道我们计算机处理的问题千千万万,有很多场景即使我们能给这个索引定义出来语意,但是他有可能不适用于使用数组。举个最简单的例子,就是身份证号,比如说我可以设计一个数组,这个数组存放不同的人相应的这个工资情况,我想索引到不同的人可能使用身份账号就是一个非常好的索引方式。比如说可能我的身份证号是这样的一个身份证号120103168512166666。这个看起来是一个数,但是它不能作为数组的索引,为什么?这是因为这个数字太大了,我们要想到数组使用这个数字,所以我们至少就要开辟这么大的一个空间,在一般的计算机来说开劈这样大的一个空间是不实际的,甚至是不可能的。更重要的是我们就算开辟了这么大的一个空间,很有可能对于很多空间都是浪费的,有可能我现在的程序就想考察一个工作小组里面只有十个人他们相应的工资情况,为了这十个人十个元素,我们就要开辟这么大的空间,显然是不合理的。而另外一方面我们开辟了这么大一个空间,很多空间明显被浪费的,比如说没有任何一个合法的身份证号是6666,也没有任何一个合法的身份证号是42等等。其实对于这种情况我们也可以使用数组进行处理,毕竟他只是一个承载元素的工具,怎么使用使用是由我们开发者来决定的。
5、自定义数组类
我们在这里做的主要工作,其实也是处理索引没有语意的情况下面我们应该怎样使用数组。毕竟如果我们的索引有语意了,使用数组太简单了,我们就直接用索引去查询相应的那个元素或者修改它就好了。但是如果我们的这个索引没有语意的话,就会产生很多新的问题。那么在此时要注意,我们的数组他只是一个待存放我们要考察的这些元素的这样的一个空间。比如说我们开了一个有八个元素这样的一个数组,但是可能当前我们只考察三个元素,那么此时就有问题了,剩下的空间里并没有元素,可能访问剩下的空间就是非法的。因为从用户的角度来看是没有34567这些元素的,只有012这些元素。此时,我们如何表示这些没有的元素呢,而与此同时在这种情况下,还会往数组中添加元素或者删除元素,这些操作要如何做呢。其实还会有更多的问题,最典型的就是在添加元素的时候,都知道我们数组的大小在我们创建的时候就已经固定下来了,如果我们添加的元素超过了八个,此时应该怎么做呢?对于这些问题我们在接下来中一一的进行解决。但是在这里要注意,C++为我们提供的数据是没有这些功能的,我们必须编写属于自己的方法来为数组中添加元素或者删除元素,如此我们需要基于C++的数组来二次封装一个属于我们自己的数组。最后看到我会把这个数组叫做动态数组,而原本的数组属于静态数组。到最后也会涉及到简单的复杂度分析,到那个时候就会发现我们自己做的这个动态数组其实它的性能并不差,具体而言我们在这小结只设计非常简单的,我们这个数组相应的成员变量的一个设计,我把我们的这个类就叫做AMGArray,在这个数组中将封装一个C++的数组我把它定义为data。我们针对这个C++的数组要进行增删改查等等的工作,可能接触过使用计算机来完成一些业务逻辑,尤其是在网页开发中,那么操作数据库的时候就经常涉及增删改查四个工作,其实对于我们的数据结构来说它的本质跟数据库是一样的,也是存储数据之后进行高效的对这些数据操作。只不过我们设计的数据结构会把这些数据存储在内存中,所以我们针对这些数据结构所添加的操作在大的类别的划分上也是增删改查,不过在这个的过程中,可能就会体会到针对不同的数据结构我们增删改查的方式是截然不同的。有一些数据结构可能会忽略这四个动作中的某一个动作,但是不管怎样增删改查这四个动作可以作为我们研究一个数据结构相应的这样的一个脉络。那么由于数组本身是静态的,也就是我们在创建的时候就必须指定它的大小,这个大小叫做容量,相应的用capacity也就是我们的数组空间最多可以装多少个元素。
6、代码实现数组类
但是要注意我们的数组空间最多可以装多少个元素和数组中实际装了多少个元素是没有关系的,这是两回事。我们数组中实际有多少个元素我用一个叫做size这样的一个变量来控制。可以想象在初始化的时候我们数组中一个元素都没有,此时这个size应该等于零,这个零其实也相当于是指向了在我们这个数组中,第一个没有元素的相应的这个索引空间。在初始化的时候我的数组一个元素都没有等于零,他其实就指向了第一个没有元素的索引,也就是零这个位置。后续为我们的这个类来设计相应的方法,比如增加元素或者删除元素的时候,就会看到我们需要维护size这个变量他相应的值是多少,我们就先来写代码完成这些基本的设计。
我们有了这样的一个构造函数,我们也可以为用户提供一个默认的构造函数,他们有的时候用户可能也不知道自己生成的这个属性想要装多少元素,在初始化的时候,用户就不要非传一个开辟这个参数了,此时这个没有参数的这个构造函数,在逻辑上我们也要给他声明一个容量的一个指值,我给他传进去的是一个十。这个时可能不够用此时让我们先不考虑这个问题,在后续我们会解决这个问题。在这里呢就暂时写两个构造函数,其实可以根据情况添加更多的构造函数。