一、数组

1、定义

数组是值类型,存放多个同一类型的数据类型,go中数组是值类型。
数组定义过程:声明就开辟了内存空间,之后操作都是给数据各个元素赋值

var names [2]string;
names[0] = "zhangsan"
names[1] = "lisi"
var ages = [...]int{1,2,3,4,5,6,7,8}
// 或者
ages := [...]int{1,2,3,4,5,6,7,8}

2、注意

var name [10]bool
// 输出 =》[false false false false false false false false false false]
var age [10]int
// 输出 =》[0 0 0 0 0 0 0 0 0 0]

// 依次类推
func main(){
	a := [2]int{1,2} // [1 2]
	setArray(&a)
	fmt.Println(a) // 输出 =》[34 2]
}

// 指针修改数组地址对应的值
func setArray1(arr *[2]int)  {
	fmt.Println(len(arr))
	arr[0] = 34
}

3、案例

var zimu [26]byte
for i := 0; i < 26; i++ {
	zimu[i] = 'A' + byte(i)
}
fmt.Printf("%c\n",zimu)
// 最大值
var maxItem int
// 下标
var maxIndex int
arr := [...]int{1,2,4,5,1,-1,0,5,6}
for i := 0; i < len(arr); i++ {
	if arr[i] > maxItem {
		maxItem = arr[i]
		maxIndex = i
	}
}
fmt.Println(maxItem, maxIndex)
func RandReverse() {
	var arr [5]int
	for i := 0; i < len(arr); i++ {
		rand.Seed(time.Now().UnixNano())
		arr[i] = rand.Intn(10)
	}
	fmt.Println(arr)

	// 倒叙输出	
	for i := len(arr)-1; i >= 0; i-- {
		fmt.Printf("%v",arr[i])
	}

	// 交换首位和末尾
	var temp int
	for i := 0; i < len(arr)/2; i++ {
		temp = arr[len(arr)-i-1]
		arr[i] = temp
		arr[len(arr)-i-1] = arr[i]
	}
	fmt.Println(arr)

}

二、切片

  1. 切片是数据的引用类型,长度可变(可以理解为动态数组)。
  2. 在传递时是引用传递,不会产生值拷贝。

1、切片定义方式

// 定义数组
arr := [5]int{1,2,3,4,5}
// 引用数组1~4的元素
slice := arr[1:5]

// 输出数组第二位的内存地址
fmt.Println(&arr[1])
// 输出切片的内存地址
fmt.Println(&slice[0])
// 输出地址都为:0xc000136038
// 参数1:切片类型
// 参数2:切片长度
// 参数3:分配空间(最大长度,超过最大长度会指数倍增加)
slice := make([]int, 6, 6)
fmt.PrintLn(slice)
// 输出:[0,0,0,0,0,0]

// 修改分配的元素
slict[0] = 1
// slict:[1,0,0,0,0,0]

// 使用append追加元素
slice = append(slice, 2)
// // slict:[1,0,0,0,0,0,2]
slict := []int{1,2,4,3,4,5}
var slict []int = []int{1,2,4,3,4,5}

2、append:向切片中动态追加元素

// 创建新的数组,将slice, slice2拷贝到新的数组
// 将slice4的指针,指向新的数组
slice4 := append(slice, slice2...)
fmt.Println(slice4)

3、copy:复制

copy(切片1, 切片2)
	num1 := []int{1,2,45,6,7,7}
	
	num2 := make([]int, 10)
	copy(num2, num1)
	fmt.Println(num2)
	// 输出 =》*[10]int[1 2 45 6 7 7 0 0 0 0]
	
    num2 := make([]int, 10)
	copy(num2, num1)
	fmt.Println(num2)
	// 输出 =》*[10]int[1 2 45]

三、排序和查找

1、冒泡排序

func mpSort(arr []int) {
	for i := 0; i < len(arr); i++ {
		for j := i + 1; j < len(arr); j++ {
			if arr[i] > arr[j] {
				arr[i], arr[j] = arr[j], arr[i]
			}
		}
	}
}

2、快速排序

快速排序思想:选一个基准数,然后分别起两个指针,从最左开始循环找比基准大的数字,最右找比基本小的数字,找到两个数组交换,继续循环,直到左指针下标与右指针下标重合,最后递归,左边排左边,右边排右边,分而治之。
需要注意⚠️:循环应该先从最右边开始;如果从左边开始,则不能保证指针指的是最小值

// 参数1:需要排序的数组
// 参数2:最左下标
// 参数3:最右下标
func ksSort(arr []int, left int, right int) {
	// 如果左指针下标大于右指针下标,弹出
	if left > right {
		return
	}
	base := arr[left]
	i := left
	j := right
	
	for i != j {
		// 先从右-》左遍历数组,找到比基准大的数子,停止,开始左边循环
		for arr[j] >= base && i < j{
			j--
		}
		for arr[i] <= base && i < j{
			i++
		}
		// 将比基准数大的数与比基准数小的数字交换
		arr[i], arr[j] = arr[j], arr[i]
	}
	// 将基准和左右指针重合位置交换,,,,此时第一次循环结束后,左边都是比基准数小,右边都比基准数大
	arr[left], arr[i] = arr[i], arr[left]
	
	// 递归, 先将左边排序
	ksSort(arr, left, i-1)
	// 在将右边排序
	ksSort(arr, i+1, right)
}

3、二分查找

前提:有序数组
思想:笔者觉得核心的思想还是和快排一样,递归调用,拆分查找!

// 参数1:需要排序的数组
// 参数2:最左下标
// 参数3:最右下标
// 参数4:需要查找的数
func EfFind(arr []int, left int, right int, findVal int)  {
	if left > right {
		fmt.Println("找不到哦")
		return
	}
	// 找到中位数指针
	median := (left + right) / 2
	// 如果中间的数大于查找的数字,则查找的数字必定在该中位数的左边
	if arr[median] > findVal {
		EfFind(arr, left, median - 1, findVal)
	// 如果中间的数小于查找的数字,则查找的数字必定在该中位数的右边
	} else if arr[median] < findVal {
		EfFind(arr, median + 1, right, findVal)
	} else {
		fmt.Println("找到了", arr[median], left, right)
	}
}

四、二维数组

// 方式1
arr := [4][4]int{{1,2,3,4},{1,2,3,4},{1,2,3,4},{1,2,3,4}}
// 方式2
var arr = [4][4]int{{1,2,3,4},{1,2,3,4},{1,2,3,4},{1,2,3,4}}
// 方式3
var arr [4][4]int = [4][4]int{{1,2,3,4},{1,2,3,4},{1,2,3,4},{1,2,3,4}}

五、案例

import (
	"fmt"
	"math/rand"
	"time"
)

func main() {
	randSort()
}
func randSort() {
	// 随机生成100个数字
	rand.Seed(time.Now().UnixNano())
	var arr [100]int
	for i := 0; i < len(arr); i++ {
		arr[i] = rand.Intn(100)
	}

	// 排序
	sortBy(&arr, 0, len(arr)-1)
	fmt.Println(arr)
	// 查找
	findBy(&arr, 0, len(arr)-1,55)
}
// 查找
func findBy(arr *[100]int, left int, right int, findVal int)  {
	if left > right {
		fmt.Println("该数字不存在")
		return
	}
	median := (left + right)/2
	if arr[median] > findVal {
		findBy(arr, left, median-1, findVal)
	} else if arr[median] < findVal {
		findBy(arr, median + 1, right, findVal)
	} else {
		fmt.Println("中位数index:",median)
		return
	}
}
// 排序
func sortBy(arr *[100]int, left int, right int) {
	if left > right {
		return
	}
	base := arr[left]
	i := left
	j := right

	for i != j {
		for arr[j] >= base && i < j {
			j--
		}
		for arr[i] <= base && i< j {
			i++
		}
		arr[i], arr[j] = arr[j], arr[i]
	}
	arr[i], arr[left] = arr[left], arr[i]

	sortBy(arr, left, i-1)
	sortBy(arr, i+1, right)
}
// 核心代码
func insertBy(arr [100]int, insertVal int) {
	slice := arr[:len(arr)]
	for i := 0; i < len(arr); i++ {
		if arr[i] > insertVal{
			// golang中间插入一个元素
			slice = append(arr[:i], append([]int{insertVal}, arr[i:]...)...)
			fmt.Println(slice)
			break
		}
	}
}
func zeroBy(arr [][]int) {
	for i := 0; i < len(arr); i++ {
		for j := 0; j < len(arr[i]); j++ {
			if i == 0 || i == len(arr)-1 {
				arr[i][j] = 0
			}
			if j == 0 || j == len(arr[i]) - 1 {
				arr[i][j] = 0
			}
		}
	}
	// 输出二维数组
	for i := 0; i < len(arr); i++ {
		fmt.Println(arr[i])
	}
}