IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> Go学习:切片 -> 正文阅读

[数据结构与算法]Go学习:切片

创建Slice

切片(Slice)是对数组一个连续片段的引用(该数组我们称之为相关数组,通常是匿名的),所以切片是一个引用类型(因此更类似于 C/C++ 中的数组类型).这个片段可以是整个数组.

func main() {
	arr := [...]int{0,1,2,3,4,5,6,7}
	a := arr[2:6]
	fmt.Println("a =>", a) // a => [2 3 4 5]
	a0 := arr[:6]
	fmt.Println("a0 =>", a0) // a0 => [0 1 2 3 4 5]
	a1 := arr[2:]
	fmt.Println("a1 =>", a1) // a1 => [2 3 4 5 6 7]
	a2 := arr[:]
	fmt.Println("a2 =>", a2) // a2 => [0 1 2 3 4 5 6 7]
}

Slice属于半开半闭区间的,包头不包尾,:左右两边不写,相当于从下标0开始,到最后一个元素结束

slice作为参数

func main() {
	arr := [...]int{0,1,2,3,4,5,6,7}
	a1 := arr[2:]
	fmt.Println("a1 =>", a1) // a1 => [2 3 4 5 6 7]
	updateSlices(a1)
	fmt.Println("arr =>", arr) // arr => [0 1 100 3 4 5 6 7]
}
func updateSlices(s []int){
	s[0] = 100;
}
  • go语言一般不会使用数组作为参数,大多数情况下都是使用切片
  • Slice本身没有数据的,是对底层array的一个view.
  • 对Slice中元素的修改会影响array的元素

Reslice

func main() {
	arr := [...]int{0,1,2,3,4,5,6,7}
	s := arr[2:]
	fmt.Println("s =>",s) // s => [2 3 4 5 6 7]
	s = s[:5]
	fmt.Println("s =>",s) // s => [2 3 4 5 6]
	s = s[:3]
	fmt.Println("s =>",s) // s => [2 3 4]
}
  • slice上面可以再建立slice
  • 这些不同的slice都是view的同一个array

Slice的扩展

func main() {
	arr := [...]int{0,1,2,3,4,5,6,7}
	s1 := arr[2:6]
	fmt.Println("s1 =>",s1) // s1 => [2 3 4 5]
	s2 := s1[3:5]
	fmt.Println("s2 =>",s2) // s2 => [5 6]
}

在这里插入图片描述

  • s2把不属于s1的元素6也取出来了,说明Slice是可以进行扩展的,但是如果直接使用s1[4]还是会索引越界

Slice的实现

在这里插入图片描述

func main() {
	arr := [...]int{0,1,2,3,4,5,6,7}
	s1 := arr[2:6]
	// s1 =[2 3 4 5], len(s1)=4, cap(s1)=6
	fmt.Printf("s1 =%v, len(s1)=%d, cap(s1)=%d\n",s1,len(s1),cap(s1))//
	s2 := s1[3:5]
	// s2 =[5 6], len(s2)=2, cap(s2)=3
	fmt.Printf("s2 =%v, len(s2)=%d, cap(s2)=%d\n",s2,len(s2),cap(s2))
	// panic: runtime error: slice bounds out of range [:4] with capacity 3
	fmt.Println(s2[:4])
}
  • Slice内部有三个变量

    • ptr指向Slice开头的元素
    • len是Slice的长度
    • cap是代表ptr到整个array最后
  • Slice可以向后扩展,不可以向前扩展

  • s[i]不可以超过len(s),向后扩展不可以超越底层数组cap(s)

Slice的操作

append

func main() {
	arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
	s1 := arr[2:6]
	// s1 =[2 3 4 5], len(s1)=4, cap(s1)=6
	fmt.Printf("s1 =%v, len(s1)=%d, cap(s1)=%d\n", s1, len(s1), cap(s1))
	s2 := s1[3:5]
	// s2 =[5 6], len(s2)=2, cap(s2)=3
	fmt.Printf("s2 =%v, len(s2)=%d, cap(s2)=%d\n", s2, len(s2), cap(s2))
	s3 := append(s2, 10)
	s4 := append(s3, 11)
	s5 := append(s4, 12)
	fmt.Println("s3 =>", s3) // s3 => [5 6 10]
	fmt.Println("s4 =>", s4) // s4 => [5 6 10 11]
	fmt.Println("s5 =>", s5) // s5 => [5 6 10 11 12]
	fmt.Println("arr =>", arr) // arr => [0 1 2 3 4 5 6 10]
}
  • 添加元素时如果超越cap,系统会重新分配更大的底层数组(s4,s5不再是对arr的view,是系统分配更大的底层数组的view);原来的数组如果有引用,它就还在,如果没有引用就会被垃圾回收
  • 由于值传递的关系,必须接收append的返回值
  • s = append(s,val)

Slice的扩容

func printSlice(s []int){
	fmt.Printf("len=%d,cap=%d\n",len(s),cap(s))
}

func main() {
	var s [] int
	fmt.Println(s)
	for i:=0; i<10;i++{
		printSlice(s)
		s = append(s,i)
	}
	// [0 1 2 3 4 5 6 7 8 9]
	fmt.Println(s)
}
//len=0,cap=0
//len=1,cap=1
//len=2,cap=2
//len=3,cap=4
//len=4,cap=4
//len=5,cap=8
//len=6,cap=8
//len=7,cap=8
//len=8,cap=8
//len=9,cap=16

当len为0时,cap也为0,当len开始添加元素时,cap从开始扩容为1,以后每次添加不了元素时都进行2倍的扩容

func main() {
	s1 := []int{2,4,6,8}
	// [2 4 6 8] len=4,cap=4
	printSlice(s1)
	s2 := make([]int,16)
	// [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] len=16,cap=16
	printSlice(s2)
	// [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] len=16,cap=32
	s3 := make([]int, 16, 32)
	printSlice(s3)
}

func printSlice(s []int){
	fmt.Printf("%v len=%d,cap=%d\n",s,len(s),cap(s))
}

CopySlice

func main() {
	arr1 := []int{1,3,5,7,9}
	arr2 :=make([]int,10);
	// [0 0 0 0 0 0 0 0 0 0] len=10,cap=10
	printSlice(arr2)
	copy(arr2,arr1)
	// [1 3 5 7 9 0 0 0 0 0] len=10,cap=10
	printSlice(arr2)
}

func printSlice(s []int){
	fmt.Printf("%v len=%d,cap=%d\n",s,len(s),cap(s))
}

删除元素

删除中间的元素

func main() {
	arr1 := []int{1,3,5,7,9}
	//[1 3 5 7 9] len=5,cap=5
	printSlice(arr1)
	arr1 = append(arr1[:1],arr1[2:]...)
	//[1 5 7 9] len=4,cap=5
	printSlice(arr1)

}

func printSlice(s []int){
	fmt.Printf("%v len=%d,cap=%d\n",s,len(s),cap(s))
}

删除头元素

func main() {
	arr1 := []int{1,3,5,7,9}
	//[1 3 5 7 9] len=5,cap=5
	printSlice(arr1)
	head := arr1[0]
	arr1 = arr1[1:]
	//[3 5 7 9] len=4,cap=4
	printSlice(arr1)
	//head => 1
	fmt.Println("head =>",head)
}

func printSlice(s []int){
	fmt.Printf("%v len=%d,cap=%d\n",s,len(s),cap(s))
}

删除尾元素

func main() {

	arr1 := []int{1,3,5,7,9}
	//[1 3 5 7 9] len=5,cap=5
	printSlice(arr1)
	tail := arr1[len(arr1)-1]
	arr1 = arr1[:len(arr1)-1]
	//[1 3 5 7] len=4,cap=5
	printSlice(arr1)
	//tail => 9
	fmt.Println("tail =>",tail)
}

func printSlice(s []int){
	fmt.Printf("%v len=%d,cap=%d\n",s,len(s),cap(s))
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-02-24 15:33:08  更:2022-02-24 15:33:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 15:42:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码