「这是我参与2022首次更文挑战的第4天,活动详情查看:2022首次更文挑战」
Array(数组)
数组是同一种数据类型元素的集合。和其他语言一样,数组的地址空间是连续的。
在Go语言中,数组从声明时就确定,使用时可以修改数组成员,但是数组大小不可变化。
数组的定义
var 数组变量名 [元素数量]T
比如:var a [3]int, 数组的长度必须是常量,并且长度是数组类型的一部分。一旦定义,长度不能变。 [3]int和[4]int是不同的类型。
func arrayDemo() {
var a1 [3]int
var a2 [4]int
fmt.Printf("a1: %T,a2:%T", a1, a2)
}
结果为
a1: [3]int,a2:[4]int
如此也可以发现,数组的长度是数组的一部分
数组可以通过下标进行访问,下标是从0开始,最后一个元素下标是:len-1,访问越界(下标在合法范围之外),则触发访问越界,会panic(错误,后面会讲解)。
数组的初始化
静态初始化 初始化的时候指定长度
动态初始化 不指定长度,根据初始化值来自动判断长度
数组的遍历
数组的遍历有两种方法,for i 与 for range(推荐)
多维数组
多维数组 也可以看作数学领域的矩阵。
注意: 多维数组只有第一层可以使用...来让编译器推导数组长度。
//支持的写法
a := [...][2]string{
{"北京", "上海"},
{"广州", "深圳"},
{"成都", "重庆"},
}
//不支持多维数组的内层使用...
b := [3][...]string{
{"北京", "上海"},
{"广州", "深圳"},
{"成都", "重庆"},
}
数组的应用
冒泡排序
冒泡排序(Bubble Sort)是一个很经典的排序算法,它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。动图示例(来源于网络):
下面详细分析一下常规版的冒泡排序,整个算法流程其实就是上面实例所分析的过程。可以看出,我们在进行每一次大循环的时候,还要进行一个小循环来遍历相邻元素并交换。所以我们的代码中首先要有两层循环。
外层循环:需要辅助我们找到当前第 i 小的元素来让它归位。所以我们会一直遍历 n-1 次,这样可以保证前 n-1 个元素都在正确的位置上,那么最后一个也可以落在正确的位置上了。
内层循环:需要辅助我们进行相邻元素之间的比较和换位,把大的或者小的浮到水面上。所以我们会一直遍历 n-1-i 次这样可以保证没有归位的尽量归位,而归位的就不用再比较了。
接下来我们按照动图中排序的方式来进行编码
第一次优化 上面的情况当我们用测试用例 已经有序的时候会发现 还会经过多次无效循环 所以我们要加入一个标记位,如果上次内层循环没有发生过交换,则证明已经有序,直接退出即可
第二次优化
当用测试用例5,2,4,3,8 会发现第三次循环完全没必要出现,而出现的原因是因为在第二次循环第一次就已经完成了排序,标志位为true,所以还会经过无效循环。引起这个问题的原因还是内层循环。
内层循环在已经完成循环后没有及时退出导致进行了冗余循环
我们只需要记录上次最后发生循环的位置就可以知道应该最多循环多少次。
总结
需要注意的是,数组在创建是就是固定的长度,无法改变。