数组理论基础
经过之前的学习我们已经了解了如何评判一个算法的好坏,今天我们开始真正进入到算法的学习中。欲盖高楼先打地基,让我们先来了解下地基中的第一块砖石(数据结构) -- 数组。
数组是什么,其实就是字面意思一组数据。定义如下:
数组是存放在连续内存空间上的相同类型数据的集合。
请注意定义中有两点需要注意下:
1.存放在连续的内存空间上,注意这里强调连续。
2.相同数据类型的集合,这里强调相同数据类型。
其实,很容易理解这种数据结构的出现,当我们想要操作一连串大量相同类型的数据时,我们总不能为每一个数据进行一次单独的声明吧。例如我们想要操作10个整型数据,我们总不能声明10个int类型的变量:int a0,int a1,int a2 ...... int a9。这样做不仅不美观,而且如果想对这十个变量进行操作的话就需要一一赋值,把每个变量名在你的编译器上打一遍,例子中是十个变量也许我们还能打一下,100个呢,1000个呢,10000个呢?
所以数组诞生了,数组不仅可以只声明一次就能创建多个相同数据类型的变量空间,还可以方便的通过下标索引的方式获取到下标下对应的数据。
Carl神给了一个字符数组的例子,我这里拿过来用下(小声的~):
需要两点注意的是
- 数组下标都是从0开始的。
- 数组内存空间的地址是连续的
Java声明数组变量
//通用表达
dataType[] arrayRefVar; // 首选的方法
或
dataType arrayRefVar[]; // 效果相同,但不是首选方法
//例子
double[] myList; // 首选的方法
或
double myList[]; // 效果相同,但不是首选方法
Java创建数组
//Java语言使用new操作符来创建数组,语法如下:
arrayRefVar = new dataType[arraySize];
/**
上面的语法语句做了两件事:
一、使用 dataType[arraySize] 创建了一个数组。
二、把新创建的数组的引用赋值给变量 arrayRefVar。
**/
// 数组变量的声明,和创建数组可以用一条语句完成,如下所示:
dataType[] arrayRefVar = new dataType[arraySize];
// 另外,你还可以使用如下的方式创建数组。
dataType[] arrayRefVar = {value0, value1, ..., valuek};
下面的语句首先声明了一个数组变量 myList,接着创建了一个包含 10 个 double 类型元素的数组,并且把它的引用赋值给 myList 变量。
public class TestArray { public static void main(String[] args) { // 数组大小 int size = 10; // 定义数组 double[] myList = new double[size]; myList[0] = 5.6; myList[1] = 4.5; myList[2] = 3.3; myList[3] = 13.2; myList[4] = 4.0; myList[5] = 34.33; myList[6] = 34.0; myList[7] = 45.45; myList[8] = 99.993; myList[9] = 11123; // 计算所有元素的总和 double total = 0; for (int i = 0; i < size; i++) { total += myList[i]; } System.out.println("总和为: " + total); } }
输出结果为
总和为: 11367.373
有关数组的深入讨论
由于数组的在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动被删除位置之后的元素来添补删除后留下的空白位置。例如Carl神给出的例子:
删除下标为3的元素,需要对下标为3的元素后面的所有元素都要做移动操作,如图所示:
由于这种特性导致数组的元素不能删除,只能覆盖。
想必看到这里童鞋们应该已经能够举一反三了,二维数组的画面就算我不说是不是也已经出现在各位的脑海中了呢?来吧上画面--二维数组(依旧是Carl神的图)。
好啦,冷知识登场了!!前面一直有提到数组是连续的,一维数组已经能够肯定一定是连续存在与计算机的内存空间中的,那二维数组呢?
答案是 No!二维数组地址不一定连续,极少情况下连续
凭着谨慎求证的态度,我在我自己的计算机上进行了验证,本博文主要以Java为例,上才艺:
public class Test {
public static void main(String[] args) {
int[][] arr = {{1, 2, 3}, {3, 4, 5}, {6, 7, 8}, {9,9,9}};
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr[3]);
}
}
运行结果如下:
结果确实如此,二维数组的存储地址并不是连续的。Java 里二维数组的存储空间到底是什么样的呢?巧了我还真找到张图!!
如此看来在java中每一行的地址都不在同一地址空间上,但是根据这张图每一行数据中的两个相邻元素应该在连续的地址空间上! 但是由于Java是没有指针的,同时也不对程序员暴露其元素的地址,寻址操作完全交给虚拟机,所以博主也没办法对这一点进行验证。
但是事实上并不是所有编程语言中的二维数组都不存储在连续的内存空间上,例如Carl神在其书中证明了在C++中二维数组就是存储在连续空间上的。