【Golang】五、基础篇 -- 数组和切片 - Go语言中文社区

【Golang】五、基础篇 -- 数组和切片


一、数组

1、定义

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

  1. 定义定长数组
    var names [2]string;
    names[0] = "zhangsan"
    names[1] = "lisi"
    
  2. 类型推导定义
    var ages = [...]int{1,2,3,4,5,6,7,8}
    // 或者
    ages := [...]int{1,2,3,4,5,6,7,8}
    

2、注意

  1. 数据中必须是相同类型的数据
  2. 一旦声明,长度固定,不可以动态添加元素
  3. 数据声明之后会有默认值
    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]
    
    // 依次类推
    
  4. 下标从0开始
  5. 数组是值类型,所以在方法传递过程中是值拷贝
  6. 定义数组不声明空间,是切片,不是数组,比如arr []int
  7. 使用指针传递值,是引用类型,直接修改栈中的值,不会发生值拷贝
    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、案例

  1. 打印出A-Z所有的字母
    var zimu [26]byte
    for i := 0; i < 26; i++ {
    	zimu[i] = 'A' + byte(i)
    }
    fmt.Printf("%cn",zimu)
    
  2. 数组中最大值和下标
    // 最大值
    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)
    
  3. 数组反转
    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、切片定义方式

  1. 方式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:make分配内存空间
    // 参数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]
    

在这里插入图片描述

  1. 方式3:类型推导
    slict := []int{1,2,4,3,4,5}
    var slict []int = []int{1,2,4,3,4,5}
    
  2. 方式1和方式2区别:
    1. 方式1是直接引用数组,值可见,可通过数组修改切片的值
    2. 方式2是用make创建切片,底层也是创建一个数组(该数组不可见没有名称),只有通过切片去引用访问。

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

  1. 流程:
    1. 内存中创建一个数组newarr
    2. 将切片1中的数复制给newarr
    3. 将追加的元素追加到newarr
    4. 将切片指向新的newarr的首地址
  2. 案例:
    // 创建新的数组,将slice, slice2拷贝到新的数组
    // 将slice4的指针,指向新的数组
    slice4 := append(slice, slice2...)
    fmt.Println(slice4)
    

3、copy:复制

  1. 作用
    1. 将切片1的值复制给切片2
    2. 两个切片相互独立
    3. 切片复制长度以切片1为准(copy(切片1, 切片2)
  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. 定义:
    // 方式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}}
    
  2. 内存布局
    在这里插入图片描述

五、案例

  1. 随机生成100个数字,并且排序,并且找出90这个数字的下标

    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)
    }
    
  2. 在一个升序数组中插入60,插入后依旧保持升序

    // 核心代码
    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
    		}
    	}
    }
    
  3. 二维数组周围变0,并且输出

    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])
    	}
    }
    
版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/m0_46537958/article/details/115270432
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢