(4-1)容器(Container):数组

在Go语言中,变量在一定程度上能满足简易程序功能的要求。但是如果编写一些复杂的程序,例如涉及到算法、结构和逻辑时就需要更复杂的类型来实现。这类复杂类型一般情况下具有各种形式的存储和处理数据的功能,将它们称为“容器(Container)”。Go语言中的容器包含数组、切片、映射以及列表,在本章的内容中,将详细讲解Go语言容器的知识和用法。

4.1  数组

在Go程序中,数组是一个的重要的容器之一。在一个数组中可以拥有多个元素,这些元素都拥有相同的数据类型。按照数组元素类型的不同,数组可以分为数值数组、字符数组、指针数组、结构数组等各种类型

4.1.1  声明数组

在Go程序中,声明数组的语法格式如下所示。

var name [元素数量]Type 

对上述格式的具体说明如下所示:

  1. name:数组的名字。
  2. 元素数量:数组的元素数量,可以是一个表达式,但最终通过编译期计算的结果必须是整型数值,元素数量不能含有到运行时才能确认大小的数值。
  3. Type:可以是任意基本类型,包括数组本身,类型为数组本身时,可以实现多维数组。

例如以下定义了float32类型的数组balance,数组的长度为10。

var balance [10] float32

4.1.2  数组的初始化

数组的初始化是指为数组设置初始值,在初始化数组的时候需要规定数组的大小,也可以初始化数组中的每一个元素。例如在下面的代码中,初始化数组中的5个元素的值分别是1000.0、2.0、3.4、7.0和50.0。

var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

另外,在声明数组的同时也可以通过字面量快速初始化数组:

balance := [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

上述两段代码的功能是完全等效的,如果不确定某个数组的长度,可以使用“...”代替数组的长度,此时编译器会根据元素的个数自行推断数组的长度,例如下面的代码:

var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

或:

balance := [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

在数组中,数组的每个元素都可以通过索引(下标)号来访问,索引号下标的范围是从 0 开始到数组长度减 1 的位置。数组中的每一个元素都拥有一个索引号,在使用数组时,只需要指定索引号就可以取出对应数组元素的值。请看下面的代码

var a =[7]int {1,2,3,5,8,9,10}//n 是一个长度为 10 的数组,然后初始化赋值

上述代码创建了一个名为a的int型数组,但是为了访问数组中的元素,应该指定数组的元素的位置,也就是索引和下标,数组a的具体结构如图4-1所示。

图4-1  一维数组内部结构

在图4-1中,数组的名称是a,中括号中的数值0到6是数组元素的索引号,通过索引号可以很清楚地表示每一个数组元素的值。例如数组a中的第一个元素的值用a[0]表示,第2个元素的值用a[1]表示,依次类推。

另外,我们还可以通过指定索引的方式来初始化数组元素,例如在下面的代码中,初始化了数组balance中索引号分别为1和为3的元素。

balance := [5]float32{1:2.0,3:7.0}

注意:在初始化数组的过程中,{}中的元素个数不能大于[]中的数字。

如果忽略 []中的数字不设置数组大小,Go 语言会根据元素的个数来设置数组的大小:

balance[4] = 50.0

上述代码读取了数组balance中的第5个元素。

实例4-1:遍历输出数组中的元素(源码路径:Go-codes\4\arry01.go

实例文件arry01.go的具体实现代码如下所示。

package main
import "fmt"
func main() {
	var a =[7]int {1,2,3,5,8,9,10}//a 是一个长度为 7的数组.然后初始化赋值
	var j int
	//输出每个数组元素的值
	for j = 0; j < 7; j++ {
		fmt.Printf("Element[%d] = %d\n", j, a[j] )
	}
}

在上述代码中,首先创建了一个长度为7的数组a,然后使用for循环遍历输出了数组a中每个元素的值。执行后会输出:

Element[0] = 1
Element[1] = 2
Element[2] = 3
Element[3] = 5
Element[4] = 8
Element[5] = 9
Element[6] = 10

4.1.3  二维数组

在本章前面学习的数组是一维数组,一维数组是呈线性排布的。如果我们需要存储矩阵这样的数据结构时,该如何实现呢?此时可以使用二维数组实现。在Go语言中,二维数组本质上是以数组作为数组元素的数组,即“数组的数组。我们可以将二维数组看做是一个特殊的一维数组,其每一个元素又是一个数组。初学者可以将二维数组看作是一个围棋的棋盘,要描述一个元素的位置,必须通过纵向和横向两个坐标来描述。

(1)声明二维数组

在Go程序中,声明二维数组的方法和声明一维数组的方法相似,具体语法格式如下:

var array_name [rows][cols]type

各个参数的具体说明如下:

  1. array_name:是声明的数组变量名;
  2. rows和cols:是要声明的数组的行和列的数量;
  3. type:是数组要存储的数据类型。

例如在下面的代码中,声明了一个包含 3 行和 4 列的二维整数数组array_2d。

var array_2d [3][4]int

上述二维数组array_2d的结构是3行4列,具体说明如表4-1所示。

表4-1  二维数组内部结构表

列1

列2

列3

列4

行0

A[0] [0]

A[0] [1]

A[0] [2]

A[0] [3]

行1

A[1] [0]

A[1] [1]

A[1] [2]

A[1] [3]

行2

A[2] [0]

A[2] [1]

A[2] [2]

A[2] [3]

(2)二维数组的初始化

在Go程序中,初始化二维数组的方法和初始化一维数组的方法相同。可以使用以下方式初始化二维数组:

array_name := [rows][cols]type {
   {value1, value2, value3, value4},
   {value5, value6, value7, value8},
   {value9, value10, value11, value12},
   // ...
}

各个参数的具体说明如下:

  1. array_name:是要声明的数组的变量名;
  2. rows和cols:是要声明的数组的行和列的数量;
  3. type:是数组要存储的数据类型。

例如在下面的代码中,声明并初始化一个包含 2 行和 3 列的二维整数数组array_2d。

array_2d := [2][3]int{

   {1, 2, 3},

   {4, 5, 6},

}

上述代码创建了一个名为 array_2d 的变量,它将占用2行和3列的空间,并且每个元素都是整数类型。数组的第一行包含值 1、2 和 3,而第二行包含值 4、5 和 6。

另外,还可以使用以下方式来初始化只指定部分元素的二维数组:

array_name := [rows][cols]type {
   {value1, value2, value3},
   {value4, value5},
   {value6, value7, value8},
   // ...
}

在上述代码中,第二行的第三个元素没有被初始化,其默认值为 0。

(3)访问二维数组中的元素

在Go语言中,可以使用索引(下标)号来访问二维数组中的元素。例如,如果 arr 是一个 n 行 m 列的二维数组,则可以使用以下语法来访问第 i 行、第 j 列的元素:

arr[i][j]

其中 i 和 j 分别是要访问的元素在数组中的行和列索引。请注意,Go 中的数组是从 0 开始索引的,因此第一行的索引是 0,最后一行的索引是 n-1,第一列的索引是 0,最后一列的索引是 m-1。例如有一个 3 行 4 列的二维数组 arr,我们可以使用以下代码来访问第 2 行、第 3 列的元素:

arr := [][]int{
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12},
}
val := arr[1][2] // 第二行第三列的元素,值为 7

注意:数组中的每个元素都可以是任意类型,例如 int、string 或自定义类型。因此,访问组中的元素的语法是通用的,适用于任何类型的数组。

实例4-2:输出杨辉三角(源码路径:Go-codes\4\yang.go

杨辉三角,是二项式系数在三角形中的一种几何排列,中国南宋数学家杨辉1261年所著的《详解九章算法》一书中出现。在欧洲,帕斯卡(1623----1662)在1654年发现这一规律,所以这个表又叫做帕斯卡三角形。帕斯卡的发现比杨辉要迟393年,比贾宪要迟600年。杨辉三角的基本性质如图6-2所示。

图6-2  杨辉三角的基本性质

使用二维数组可以输出杨辉三角中的数值,我们可以分析出数组每个元素YangHui[i][j]的规则:

  1. 行的数量等于每行的元素数量, 行数=列数。
  2. 每一行的第1个元素和末尾元素都是1。
  3. 从第3行开始,“首个元素和最后那个元素之间”的每一个元素(i>1,0<j<i)=上一行本列元素+上一行前一列元素,即有:
 YangHui[i][j] = YangHui[i-1][j] + YangHui[i-1][j-1];

在实例文件yang.go中定义了1个二维整型数组triangle来存储杨辉三角的元素,然后根据上述分析输出杨辉三角的前10行。实例文件yang.go的具体实现代码如下所示。

package main
import "fmt"
func main() {
	rows := 10 // 杨辉三角的行数
	// 声明并初始化二维数组
	triangle := make([][]int, rows)
	for i := range triangle {
		triangle[i] = make([]int, i+1)
		triangle[i][0], triangle[i][i] = 1, 1 // 每行的首尾元素为1
	}
	// 填充杨辉三角中的数字
	for i := 2; i < rows; i++ {
		for j := 1; j < i; j++ {
			triangle[i][j] = triangle[i-1][j-1] + triangle[i-1][j]
		}
	}
	// 打印杨辉三角
	for i := 0; i < rows; i++ {
		for j := 0; j < i+1; j++ {
			fmt.Printf("%d ", triangle[i][j])
		}
		fmt.Println()
	}
}

在上述代码中,首先声明并初始化一个二维数组 triangle,它包含 rows 行和 rows 列,每个元素的值都是 0。然后,我们使用两个嵌套的循环来填充杨辉三角中的数字。最后,我们打印出杨辉三角的前10行。执行后会输出:

1 
1 1 
1 2 1 
1 3 3 1 
1 4 6 4 1 
1 5 10 10 5 1 
1 6 15 20 15 6 1 
1 7 21 35 35 21 7 1 
1 8 28 56 70 56 28 8 1 
1 9 36 84 126 126 84 36 9 1

如果要求输出结果中的杨辉三角中数字以等腰梯形的形式排列,此时可以使用如下代码(源码路径:Go-codes\4\dengyang.go)实现这一功能。

package main

import "fmt"

func main() {
	rows := 10
	arr := make([][]int, rows)
	for i := range arr {
		arr[i] = make([]int, i+1)
		for j := range arr[i] {
			if j == 0 || j == len(arr[i])-1 {
				arr[i][j] = 1
			} else {
				arr[i][j] = arr[i-1][j-1] + arr[i-1][j]
			}
		}
	}
	for i := range arr {
		for j := 0; j < rows-i; j++ {
			fmt.Print(" ")
		}
		for j := range arr[i] {
			fmt.Print(arr[i][j], " ")
		}
		fmt.Println()
	}
}

在上述代码中,使用了额外的循环来控制每一行的前导空格数量,从而实现等腰三角形式的输出。执行后会输出:

          1 
         1 1 
        1 2 1 
       1 3 3 1 
      1 4 6 4 1 
     1 5 10 10 5 1 
    1 6 15 20 15 6 1 
   1 7 21 35 35 21 7 1 
  1 8 28 56 70 56 28 8 1 
 1 9 36 84 126 126 84 36 9 1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农三叔

感谢鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值