5.2 Go 数组进阶学习笔记(多维、排序、搜索)
2026/8/25 12:36:32 网站建设 项目流程

5.2 Go 数组进阶学习笔记(多维、排序、搜索)

1. 多维数组 — 声明与访问

多维数组是"数组的数组",Go 通过[行][列]语法定义:

packagemainimport"fmt"funcmain(){// 声明 3x3 矩阵,元素全部为零值 0varmatrix[3][3]int// 初始化 2x4 数组(2行4列)grades:=[2][4]int{{85,92,78,96},{88,91,84,87}}// 修改元素:matrix[行][列]matrix[1][1]=5// 第2行第2列设为5// 打印矩阵:嵌套 for 循环fmt.Println("Matrix:")fori:=0;i<len(matrix);i++{forj:=0;j<len(matrix[i]);j++{fmt.Printf("%3d ",matrix[i][j])// %3d 右对齐,宽度3}fmt.Println()// 每行末尾换行}}

执行结果:

Matrix: 0 0 0 0 5 0 0 0 0

要点

  • [3][3]int— 3x3 的二维数组,类型是"3个[3]int的数组"
  • var matrix [3][3]int— 未初始化,所有元素为零值 0
  • matrix[1][1] = 5— 先选行(索引1),再选列(索引1),设为5
  • len(matrix)= 3(行数),len(matrix[i])= 3(每行的列数)
  • %3d— 右对齐,宽度3,保证矩阵格式整齐(05
  • Go 没有专门的矩阵类型,多维数组就是"数组的数组"

2. 多维数组 — range 遍历与统计

用嵌套 range 遍历多维数组更简洁:

packagemainimport"fmt"funcmain(){grades:=[2][4]int{{85,92,78,96},{88,91,84,87}}// range 遍历:外层遍历行,内层遍历每行的元素fmt.Println("Grades:")fori,row:=rangegrades{fmt.Printf("Student %d: ",i+1)for_,grade:=rangerow{fmt.Printf("%d ",grade)}fmt.Println()}// 求所有元素总和:嵌套 for 循环vartotalSumintfori:=0;i<len(grades);i++{forj:=0;j<len(grades[i]);j++{totalSum+=grades[i][j]}}fmt.Println("Total sum of grades:",totalSum)// 获取维度:行数 × 列数rows:=len(grades)varcolsintifrows>0{cols=len(grades[0])}fmt.Printf("Grades array dimensions: %dx%d\n",rows,cols)}

执行结果:

Grades: Student 1: 85 92 78 96 Student 2: 88 91 84 87 Total sum of grades: 701 Grades array dimensions: 2x4

要点

  • for i, row := range gradesrow是一整行(类型[4]int),i是行号
  • for _, grade := range row— 遍历每行的每个成绩
  • 求和:嵌套 for 遍历所有元素,grades[i][j]用双重索引访问
  • 维度:len(grades)= 行数 = 2,len(grades[0])= 列数 = 4
  • 注意:grades的类型是[2][4]int,所以所有行的列数固定为4(数组长度是类型的一部分)

3. 数组排序 — sort 包

Go 的sort包提供排序函数,但只能对切片排序,需要用[:]把数组转为切片:

packagemainimport("fmt""sort")funcmain(){numbers:=[5]int{64,34,25,12,22}names:=[4]string{"Charlie","Alice","Bob","David"}prices:=[6]float64{19.99,9.99,29.99,4.99,39.99,14.99}fmt.Println("Before sorting:")fmt.Println("Numbers:",numbers)fmt.Println("Names:",names)fmt.Println("Prices:",prices)// sort.Ints() 排序 int 切片(升序)sort.Ints(numbers[:])// numbers[:] 把数组转为切片// sort.Strings() 排序 string 切片(升序)sort.Strings(names[:])// sort.Float64s() 排序 float64 切片(升序)sort.Float64s(prices[:])fmt.Println("\nAfter sorting:")fmt.Println("Numbers:",numbers)fmt.Println("Names:",names)fmt.Println("Prices:",prices)// 检查是否已排序isSorted:=sort.IntsAreSorted(numbers[:])fmt.Println("Numbers array is sorted:",isSorted)}

执行结果:

Before sorting: Numbers: [64 34 25 12 22] Names: [Charlie Alice Bob David] Prices: [19.99 9.99 29.99 4.99 39.99 14.99] After sorting: Numbers: [12 22 25 34 64] Names: [Alice Bob Charlie David] Prices: [4.99 9.99 14.99 19.99 29.99 39.99] Numbers array is sorted: true

要点

  • sort.Ints(numbers[:])numbers[:][5]int数组转为[]int切片(切片引用数组的底层内存)
  • 排序后数组本身也被修改了!因为切片和数组共享同一块内存
  • sort.Ints— int 升序排序,sort.Strings— string 按字典序,sort.Float64s— float64 升序
  • sort.IntsAreSorted(numbers[:])— 检查切片是否已排序,返回 bool
  • 数组不能直接排序:sort.Ints(numbers)编译报错,必须转为切片

4. 逆序排序 — sort.Reverse

sort.Sort(sort.Reverse(sort.IntSlice(slice)))实现降序排序:

packagemainimport("fmt""sort")funcmain(){descNumbers:=[5]int{1,2,3,4,5}fmt.Println("Before reverse sort:",descNumbers)// 降序排序:sort.Sort + sort.Reverse + sort.IntSlicesort.Sort(sort.Reverse(sort.IntSlice(descNumbers[:])))fmt.Println("After reverse sort:",descNumbers)}

执行结果:

Before reverse sort: [1 2 3 4 5] After reverse sort: [5 4 3 2 1]

要点

  • sort.IntSlice(descNumbers[:])— 把切片包装为IntSlice类型(实现 sort.Interface 接口)
  • sort.Reverse(...)— 反转排序顺序(把升序变为降序)
  • sort.Sort(...)— 执行自定义排序
  • 三层包装:sort.Sort(sort.Reverse(sort.IntSlice(slice)))
  • 同理:sort.Reverse(sort.StringSlice(slice))— string 降序
  • sort.Reverse(sort.Float64Slice(slice))— float64 降序
  • 排序同样修改原数组(切片与数组共享内存)

5. 线性搜索 — 逐个遍历查找

线性搜索从头到尾逐个比较,适用于未排序的数组,时间复杂度 O(n):

packagemainimport"fmt"funcmain(){numbers:=[10]int{64,34,25,12,22,11,90,88,76,50}target:=22foundIndex:=-1// -1 表示未找到fori,value:=rangenumbers{ifvalue==target{foundIndex=ibreak// 找到后立即退出}}iffoundIndex!=-1{fmt.Printf("Linear search: Found %d at index %d\n",target,foundIndex)}else{fmt.Printf("Linear search: %d not found\n",target)}}

执行结果:

Linear search: Found 22 at index 4

要点

  • foundIndex = -1— 用 -1 表示"未找到"(索引不会是负数)
  • range numbers遍历每个元素,value == target比较是否匹配
  • break— 找到目标后立即停止遍历,不必检查剩余元素
  • 线性搜索适用于任何数组(排序或未排序),但效率较低:n 个元素最多比较 n 次
  • Go 没有内置的线性搜索函数,需要手动实现

6. 二分搜索 — sort.SearchInts

二分搜索只在已排序数组上有效,时间复杂度 O(log n):

packagemainimport("fmt""sort")funcmain(){sortedNumbers:=[8]int{5,12,23,34,45,67,78,89}binaryTarget:=45// sort.SearchInts 在已排序切片中查找目标binaryIndex:=sort.SearchInts(sortedNumbers[:],binaryTarget)// 必须验证:SearchInts 返回的可能是"应插入的位置",而非找到的位置ifbinaryIndex<len(sortedNumbers)&&sortedNumbers[binaryIndex]==binaryTarget{fmt.Printf("Binary search: Found %d at index %d\n",binaryTarget,binaryIndex)}else{fmt.Printf("Binary search: %d not found\n",binaryTarget)}}

执行结果:

Binary search: Found 45 at index 4

要点

  • sort.SearchInts(sortedNumbers[:], 45)— 在已排序切片中二分查找
  • 返回值含义:如果找到,返回目标索引;如果未找到,返回目标应插入的位置
  • 所以必须验证:binaryIndex < len(sortedNumbers) && sortedNumbers[binaryIndex] == binaryTarget
  • 如果不验证,未找到时也会返回一个索引(插入位置),可能误判为"找到"
  • 类似函数:sort.SearchStrings(slice, target)sort.SearchFloat64s(slice, target)
  • 前提:数组必须已排序!在未排序数组上使用二分搜索结果不正确
  • 效率:8个元素最多比较3次(log₂8=3),远优于线性搜索

7. 搜索进阶 — 最值、计数、收集索引

packagemainimport"fmt"funcmain(){numbers:=[10]int{64,34,25,12,22,11,90,88,76,50}// 求最小值和最大值(同时)min:=numbers[0]max:=numbers[0]minIndex:=0maxIndex:=0fori,value:=rangenumbers{ifvalue<min{min=value minIndex=i}ifvalue>max{max=value maxIndex=i}}fmt.Printf("Minimum: %d at index %d\n",min,minIndex)fmt.Printf("Maximum: %d at index %d\n",max,maxIndex)// 计数:统计某值出现的次数countTarget:=12count:=0for_,value:=rangenumbers{ifvalue==countTarget{count++}}fmt.Printf("Number %d appears %d times\n",countTarget,count)// 收集所有匹配的索引searchValue:=34varindices[]intfori,value:=rangenumbers{ifvalue==searchValue{indices=append(indices,i)}}fmt.Printf("Value %d found at indices: %v\n",searchValue,indices)}

执行结果:

Minimum: 11 at index 5 Maximum: 90 at index 6 Number 12 appears 1 times Value 34 found at indices: [1]

要点

  • 求最值:从numbers[0]开始,逐个比较更新 min/max 和对应的索引
  • 计数:遍历所有元素,匹配目标值时count++
  • 收集索引:var indices []int创建空切片,append(indices, i)追加匹配的索引
  • %v— 切片的默认格式输出:[1]
  • 这些操作都是 O(n) 线性扫描,无法用二分搜索优化(除非需要的是排序后的位置)
  • 实际场景:数据分析、过滤、统计等

知识点总结

知识点关键概念
多维数组[3][3]int— “数组的数组”,len取行数和列数
多维数组遍历嵌套 for/range,外层遍历行,内层遍历每行元素
sort 包排序sort.Ints(slice)— 数组需用[:]转切片,排序修改原数组
逆序排序sort.Sort(sort.Reverse(sort.IntSlice(slice)))— 三层包装
线性搜索逐个比较 O(n),适用于未排序数组
二分搜索sort.SearchIntsO(log n),只适用于已排序数组,需验证结果
最值/计数/索引收集遍历统计,append收集匹配索引

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询