欢迎光临散文网 会员登陆 & 注册

Go语言数组、切片、排序、查找、map

2022-10-22 21:00 作者:苦茶今天断更了吗  | 我要投稿

Go语言数组、切片、排序、查找、map

数组定义:

var数组名[数组大小]数据类型:var a [5]int

赋初值a[0]=1  a[1]= 30 ....

内存布局【重要】:

①数组的地址可以通过数组名来获取&intArr

②数组的第一个元素的地址,就是数组的首地址

③数组的各个元素的地址间隔是依据数组的类型决定,比如 int64 ->8;int32->4...

④4种初始化数组的方式:

var numArre1 [3] int = [3]int{1, 2,3}

var numArre2 = [3]int{5,6,7}

var numArre3 =[...]int{8,9,10}

var numArre4 =[...]int{1: 800, 0: 900,2:999}

strArre5 :=[...]string{1: "tom", 0: "jack",2 : "many"}

⑤数组的遍历:

常规遍历;

for-range遍历:

for index, value := range array01 {…}

A.第一个返回值index是数组的下标

B.第二个value是在该下标位置的

C.他们都是仅在for循环内部可见的局部变量

D.遍历数组元素的时候,如果不想使用下标index,可以直接把下标index标为下划线_

E.index和value的名称不是固定的,即程序员可以自行指定。

⑥注意事项

A.数组一旦声明,长度固定,无法动态改变。

B.var arr []int:这时arr就是一个slice 切片。数组中的元素可以是任何数据类型,包括值类型和引用类型,但是不能混用。

C.数组创建后,如果没有赋值,有默认值。

D.数组下标从0开始。

E.数组下标必须在指定范围内使用,否则报panic数组越界

F.Go的数组属值类型,默认情况下是值传递,因此会进行值拷贝。数组间不会相互影响。

G.如想在其它函数中,去修改原来的数组,可以使用引用传递(指针方式)。

H.在传递函数参数时需要考虑数组的长度:不能把[3]int传递给[]int

 

切片slice:

①切片是数组的一个引用,因此切片是引用类型,在进行传递时,遵守引用传递的机制。

②切片的使用和数组类似,遍历切片、访问切片的元素和求切片长度len(slice)都一样。

③切片的长度是可以变化的,因此切片是一个可以动态变化数组

④切片定义的基本语法:var 切片名 类型

slice从底层来说,其实就是一个数据结构(struct结构体)

type slice struct {

ptr *[2]int

len int

cap int

}

切片的使用:

①定义一个切片,让切片去引用一个已经创建好的数组。(程序员可见)

 

②make创建切片:var切片名 []type = make([]type, len, [cap])

如果分配了cap,则要求cap≥len

默认值int , float → 0;string → "";bool → false

通过make方式创建的切片对应的数组是由make底层维护,(程序员不可见)对外不可见,即只能通过 slice去访问各个元素

 

③定义一个切片,直接就指定具体数组。


切片的遍历:for循环、for-range结构

①切片初始化时var slice = arr[stantIndex : endIndex]

从arr数组下标为startIndex,取到下标为endIndex的元素(不含arr[endIndex])

②切片初始化时,仍然不能越界。但是可以动态增长。

var slice = arr[0:end]可以简写var slice = arr[:end]

var slice= arr[start:len(arr)]可以简写var slice = arr[start:]

var slice =arr[0:len(arr)]可以简写var slice = arr[:]

③cap是一个内置函数,用于统计切片的容量,即最大可以存放多少个元素。

切片定义完后,还不能使用,因为本身是一个空的,需要让其引用到一个数组,或者make一个空间供切片来使用

切片可以继续切片。(如上图slice2)

⑥用append内置函数,可以对切片进行动态追加。(如上图slice3)

append原理:

本质是对数组扩容;

go底层会创建一下新的数组newArr(安装扩容后大小);

将slice原来包含的元素拷贝到新的数组newArr;

slice重新引用到newArr;

newArr是在底层来维护的,程序员不可见。

⑦切片的拷贝操作

copy(para1, para2)参数的数据类型是切片

slice4和slice5的数据空间是独立的,slice4[0]=999,slice5[0]=1

⑧切片是引用类型,传递时遵守引用传递机制。

 


String和slice:

①string底层是一个byte数组,可以进行切片处理。

②string是不可变的,不能通过st[0]=’z’来修改字符串。

如果需要修改字符串,可以先将string→[] byte或[]rune→修改→重写转成string

 


排序

①内部排序:指将需要处理的所有数据都加载到内部存储器中进行排序。(交换式排序法、选择式排序法、插入式排序法)

②外部排序法:数据量过大,借助外部存储进行排序。(合并排序法、直接合并排序法)。

 

冒泡排序Bubble Sorting)

基本思想:通过对待排序序列从后向前(从下标较大的元素开始),依次比较相邻元素的排序码,若发现逆序则交换,使排序码较小的元素逐渐从后部移向前部。

如果一趟比较下来没有进行交换就说明序列有序。因此要在排序过程中设置一个标志flag判断元素是否进行过交换。从而减少不必要的比较(优化)。

查找:

顺序查找:

二分查找(该数组是有序的)

思路:要找的数是findval

①arr是一个有序数组,从小到大排序

②先找到中间的下标middle=(leftlndex+rightIndex)/2,让middle对应的值和findval进行比较 如果arr[middle]> findval,令leftIndex = middle - 1

如果arr[middle]< findval,令rightlndex = middle+1

如果arr[middle]= findval,就找到

上面的逻辑会递归执行

如果 leftIndex>rightIndex,则找不到

 

二维数组

四种声明/定义写法:

var数组名 [大小][大小]类型 = [大小][大小]类型{{初值..},{初值..}}

var数组名 [大小][大小]类型 = [...][大小]类型{{初值..},{初值..}}

var数组名 = [大小][大小]类型{{初值..},{初值..}}

var数组名 = [...][大小]类型{{初值..},{初值..}}

 

二位数组的遍历:for循环遍历、for-range遍历


map

map是key-value数据结构,又称为字段或者关联数组

var map变量名map[keytype]valuetype.

 

golang中的map的key可以是很多种类型,比如 bool,数字,string,指针,channel,还可以是只包含前面几个类型的接口,结构体,数组。通常key为int 、string

Slice、map、function不可以,因为这几个没法用 == 来判断

 

valuetype的类型和key基本一样,通常为:数字(整数,浮点数),string,map,struct

 

map声明:

var a map[string]string

var a map[string]int

var a map[int]string

var a map[string]map[string]string

声明是不会分配内存的,初始化需要make,分配内存后才能赋值和使用。

②map的key是不能重复,如果重复了,则以最后这个key-value为准。

③map的value是可以相同的。

④map的key-value是无序的

⑤make内置函数数目

 

内建函数make分配并初始化一个类型为切片、映射、或通道的对象。

其第一个实参为类型,而非值。make的返回类型与其参数相同,而非指向它的指针。

切片:size指定了其长度。该切片的容量等于其长度。切片支持第二个整数实参可用来指定不同的容量;它必须不小于其长度,因此make([]int,0,10)会分配一个长度为0,容里为10的切片。

映射:初始分配的创建取决于size,但产生的映射长度为0。size可以省略,这种情况下就会分配一个小的起始大小。

通道:通道的缓存根据指定的缓存容量初始化。若size为零或被省略,该信道即为无缓存的。

 

map的使用:

①增加和更新:

map[ "key"]= value。如果key还没有,就是增加,如果 key存在就是修改。

 

②删除:

delete(map,"key"),delete是一个内置函数,如果key存在,就删除该key-value,如果key不存在,不操作,但是也不会报错

如果要删除map的所有key 可以遍历一下key逐个删除或者map = make(...),make一个新的,让原来的成为垃圾,被g回收

 

③查找:


④map的长度:

func len(v Type) int

内建函数len返回v的长度,这取决于具体类型:

数组:v中元素的数量

数组指针:v中元素的数量(v为ni1时panic)

切片、映射:v中元素的数量:若v为nil,len(v)即为零

字符串:v中字节的数量

通道:通道缓存中队列(未读取)元素的数量;若v为nil,len(v)即为零

 

⑤遍历:使用for-range

map切片:map个数可以动态变化了

案例:使用一个map来记录monster的信息name和age。一个monster对应一个map,并且妖怪的个数可以动态的增加 → map切片


Map排序:

①golang中没有一个专门的方法针对map 的key进行排序。

②golang中的map默认是无序的,不是按照添加的顺序存放的,你每次遍历,得到的输出可能不一样。

③golang中map的排序,是先将key进行排序,然后根据key值遍历输出即可。

 Map使用细节:

① map是引用类型,遵守引用类型传递的机制,在一个函数接收 map,修改后,会直接修改原来的map。

②map的容量达到后,再想map增加元素,会自动扩容,并不会发生panic,也就是说 map能动态的增长键值对(key-value)

③map的value也经常使用struct类型,更适合管理复杂的数据。

 

练习:

①使用map[string]map[string]sting的map类型

②key:表示用户名,是唯一的,不可以重复

③如果某个用户名存在,就将其密码修改"888888",如果不存在就增加这个用户信息:(包括昵称nickname和密码pwd) 。

④编写一个函数modifyUser(users map[string]map[string]sting, name string)完成上述功能。

 

 


Go语言数组、切片、排序、查找、map的评论 (共 条)

分享到微博请遵守国家法律