Golang - Part04 数组和切片

数组

Go语言中的数组是一种固定长度且类型相同的数据结构。数组中存储的元素可以通过索引来访问,索引从0开始,最大值为数组长度-1。数组的长度在创建时指定,并且无法更改。

初始化数组

  1. 声明一个具有3个整数的数组:
1
var arr [3]int
  1. 声明并初始化一个具有5个整数的数组:
1
arr := [5]int{1, 2, 3, 4, 5}
  1. 声明并初始化一个具有5个整数的数组,其中第2个和第4个元素被省略:
1
arr := [5]int{1, , 3, , 5}
  1. 使用”…”语法声明并初始化一个具有5个整数的数组:
1
arr := [...]int{1, 2, 3, 4, 5}

相关用法

遍历数组

直接for循环遍历数组:

1
2
3
4
arr := [5]int{1, 2, 3, 4, 5}
for i := 0; i < len(arr); i++ {
fmt.Println(arr[i])
}

可以使用range关键字来遍历数组:

1
2
3
4
arr := [5]int{1, 2, 3, 4, 5}
for index, value := range arr {
fmt.Println(index, value)
}

数组也支持多维数组:

1
2
3
4
5
6
7
8
var arr [3][2]int
arr = [3][2]int{
{1, 2},
{3, 4},
{5, 6},
}
fmt.Println(arr[0][0]) //输出:1
fmt.Println(arr[1][1]) //输出:4

以下是使用数组和切片实现斐波那契数列的例子:

1
2
3
4
5
6
7
8
9
//使用数组实现斐波那契数列
func FibonacciArray(n int) []int {
arr := make([]int, n)
arr[0], arr[1] = 1, 1
for i := 2; i < n; i++ {
arr[i] = arr[i-1] + arr[i-2]
}
return arr
}

切片

切片(slice)是对数组的一个连续片段的引用。切片可以动态增长,并且支持所有原生的数组操作。

image-20230328221534729

初始化切片

  1. 声明一个空的整数切片:
1
var slice []int
  1. 声明并初始化一个整数切片:
1
slice := []int{1, 2, 3, 4, 5}
  1. 使用make函数创建一个长度为5的整数切片:
1
slice := make([]int, 5)
  1. 使用make函数创建一个长度为5,容量为10的整数切片:
1
slice := make([]int, 5, 10)
  1. 多维切片
1
2
s9 := [][]int{{1, 2, 3}, {11, 12, 13, 14}}
fmt.Printf("s9 的长度:%d,容量:%d\n", len(s9), cap(s9))

在Go语言中,切片可以通过索引来访问、修改元素:

1
2
3
4
5
slice := []int{1, 2, 3, 4, 5}
fmt.Println(slice[0]) //输出:1

slice[0] = 10
fmt.Println(slice) //输出:[10 2 3 4 5]

相关用法

切片还支持使用append函数动态增加元素:

1
2
3
4
5
slice := make([]int, 3, 5)
slice[0], slice[1], slice[2] = 1, 2, 3

slice = append(slice, 4, 5)
fmt.Println(slice) //输出:[1 2 3 4 5]

可以使用len和cap函数获取切片的长度和容量:

1
2
3
slice := make([]int, 3, 5)
fmt.Println(len(slice)) //输出:3
fmt.Println(cap(slice)) //输出:5

切片还支持使用内置的copy函数复制切片:

1
2
3
4
slice1 := []int{1, 2, 3}
slice2 := make([]int, len(slice1))
copy(slice2, slice1)
fmt.Println(slice2) //输出:[1 2 3]

在Go语言中,可以使用切片来实现栈和队列等数据结构。

以下是使用切片实现栈的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
type Stack []int

func (s *Stack) Push(value int) {
*s = append(*s, value)
}

func (s *Stack) Pop() int {
if s.IsEmpty() {
return -1
}
index := len(*s) - 1
result := (*s)[index]
*s = (*s)[:index]
return result
}

func (s *Stack) IsEmpty() bool {
return len(*s) == 0
}

stack := make(Stack, 0)
stack.Push(1)
stack.Push(2)
stack.Push(3)
fmt.Println(stack.Pop()) //输出:3
fmt.Println(stack.Pop()) //输出:2
fmt.Println(stack.Pop()) //输出:1
fmt.Println(stack.IsEmpty()) //输出:true

去重排序查找

可以使用sort包对切片进行排序。sort包支持对int、float64、string等类型的切片进行排序。

1
2
3
4
5
6
7
8
9
10
import (
"fmt"
"sort"
)

func main() {
slice := []int{5, 1, 3, 2, 4}
sort.Ints(slice)
fmt.Println(slice) //输出:[1 2 3 4 5]
}

sort包还支持对自定义类型的切片进行排序,只需要实现sort.Interface接口中的三个方法:Len()、Less()和Swap()。

切片排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import (
"fmt"
"sort"
)

type Person struct {
Name string
Age int
}

type PersonSlice []Person

func (p PersonSlice) Len() int {
return len(p)
}

func (p PersonSlice) Less(i, j int) bool {
return p[i].Age < p[j].Age
}

func (p PersonSlice) Swap(i, j int) {
p[i], p[j] = p[j], p[i]
}

func main() {
persons := PersonSlice{
{"Tom", 20},
{"John", 18},
{"Mary", 25},
}
sort.Sort(persons)
fmt.Println(persons) //输出:[{John 18} {Tom 20} {Mary 25}]
}

切片查找

在Go语言中,可以使用sort.Search函数对有序切片进行二分查找。

以下是对有序整数切片进行二分查找的例子:

1
2
3
4
5
6
7
8
9
10
11
12
import (
"fmt"
"sort"
)

func main() {
slice := []int{1, 2, 3, 4, 5}
index := sort.Search(len(slice), func(i int) bool {
return slice[i] >= 3
})
fmt.Println(index) //输出:2
}

如果切片中不存在要查找的元素,则返回元素应该插入的位置。

以下是对有序字符串切片进行二分查找的例子:

1
2
3
4
5
6
7
8
9
10
11
12
import (
"fmt"
"sort"
)

func main() {
slice := []string{"apple", "banana", "orange", "peach"}
index := sort.Search(len(slice), func(i int) bool {
return slice[i] >= "orange"
})
fmt.Println(index) //输出:2
}

切片去重

在Go语言中,可以使用map实现对切片进行去重。

以下是对整数切片进行去重的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import (
"fmt"
)

func RemoveDuplicates(slice []int) []int {
tempMap := make(map[int]bool)
tempSlice := []int{}
for _, value := range slice {
if !tempMap[value] {
tempMap[value] = true
tempSlice = append(tempSlice, value)
}
}
return tempSlice
}

func main() {
slice := []int{1, 2, 3, 1, 4, 2, 5}
slice = RemoveDuplicates(slice)
fmt.Println(slice) //输出:[1 2 3 4 5]
}