Go語言數(shù)組、切片、排序、查找、map
Go語言數(shù)組、切片、排序、查找、map
數(shù)組定義:
var數(shù)組名[數(shù)組大小]數(shù)據(jù)類型:var a [5]int
賦初值a[0]=1??a[1]= 30 ....
內(nèi)存布局【重要】:
①數(shù)組的地址可以通過數(shù)組名來獲取&intArr
②數(shù)組的第一個元素的地址,就是數(shù)組的首地址
③數(shù)組的各個元素的地址間隔是依據(jù)數(shù)組的類型決定,比如 int64 ->8;int32->4...
④4種初始化數(shù)組的方式:
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"}
⑤數(shù)組的遍歷:
常規(guī)遍歷;
for-range遍歷:
for?index, value?:= range array01 {…}
A.第一個返回值index是數(shù)組的下標(biāo)
B.第二個value是在該下標(biāo)位置的值
C.他們都是僅在for循環(huán)內(nèi)部可見的局部變量
D.遍歷數(shù)組元素的時候,如果不想使用下標(biāo)index,可以直接把下標(biāo)index標(biāo)為下劃線_
E.index和value的名稱不是固定的,即程序員可以自行指定。
⑥注意事項
A.數(shù)組一旦聲明,長度固定,無法動態(tài)改變。
B.var arr []int:這時arr就是一個slice 切片。數(shù)組中的元素可以是任何數(shù)據(jù)類型,包括值類型和引用類型,但是不能混用。
C.數(shù)組創(chuàng)建后,如果沒有賦值,有默認(rèn)值。
D.數(shù)組下標(biāo)從0開始。
E.數(shù)組下標(biāo)必須在指定范圍內(nèi)使用,否則報panic:數(shù)組越界。
F.Go的數(shù)組屬值類型,默認(rèn)情況下是值傳遞,因此會進行值拷貝。數(shù)組間不會相互影響。
G.如想在其它函數(shù)中,去修改原來的數(shù)組,可以使用引用傳遞(指針方式)。
H.在傳遞函數(shù)參數(shù)時,需要考慮數(shù)組的長度:不能把[3]int傳遞給[]int
?
切片slice:
①切片是數(shù)組的一個引用,因此切片是引用類型,在進行傳遞時,遵守引用傳遞的機制。
②切片的使用和數(shù)組類似,遍歷切片、訪問切片的元素和求切片長度len(slice)都一樣。
③切片的長度是可以變化的,因此切片是一個可以動態(tài)變化數(shù)組。
④切片定義的基本語法:var?切片名?類型


slice從底層來說,其實就是一個數(shù)據(jù)結(jié)構(gòu)(struct結(jié)構(gòu)體)
type slice struct {
ptr *[2]int
len int
cap int
}
切片的使用:
①定義一個切片,讓切片去引用一個已經(jīng)創(chuàng)建好的數(shù)組。(程序員可見)
?

②make創(chuàng)建切片:var切片名 []type = make([]type, len, [cap])
如果分配了cap,則要求cap≥len
默認(rèn)值int , float?→ 0;string → "";bool → false
通過make方式創(chuàng)建的切片對應(yīng)的數(shù)組是由make底層維護,(程序員不可見)對外不可見,即只能通過 slice去訪問各個元素。
?
③定義一個切片,直接就指定具體數(shù)組。

切片的遍歷:for循環(huán)、for-range結(jié)構(gòu)

①切片初始化時var slice = arr[stantIndex : endIndex]
從arr數(shù)組下標(biāo)為startIndex,取到下標(biāo)為endIndex的元素(不含arr[endIndex])
②切片初始化時,仍然不能越界。但是可以動態(tài)增長。
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是一個內(nèi)置函數(shù),用于統(tǒng)計切片的容量,即最大可以存放多少個元素。
④切片定義完后,還不能使用,因為本身是一個空的,需要讓其引用到一個數(shù)組,或者make一個空間供切片來使用。
⑤切片可以繼續(xù)切片。(如上圖slice2)
⑥用append內(nèi)置函數(shù),可以對切片進行動態(tài)追加。(如上圖slice3)
append原理:
本質(zhì)是對數(shù)組擴容;
go底層會創(chuàng)建一下新的數(shù)組newArr(安裝擴容后大?。?/p>
將slice原來包含的元素拷貝到新的數(shù)組newArr;
slice重新引用到newArr;
newArr是在底層來維護的,程序員不可見。
⑦切片的拷貝操作

copy(para1, para2)參數(shù)的數(shù)據(jù)類型是切片
slice4和slice5的數(shù)據(jù)空間是獨立的,slice4[0]=999,slice5[0]=1
⑧切片是引用類型,傳遞時遵守引用傳遞機制。
?
String和slice:
①string底層是一個byte數(shù)組,可以進行切片處理。
②string是不可變的,不能通過st[0]=’z’來修改字符串。
如果需要修改字符串,可以先將string→[] byte或[]rune→修改→重寫轉(zhuǎn)成string
?
排序
①內(nèi)部排序:指將需要處理的所有數(shù)據(jù)都加載到內(nèi)部存儲器中進行排序。(交換式排序法、選擇式排序法、插入式排序法)
②外部排序法:數(shù)據(jù)量過大,借助外部存儲進行排序。(合并排序法、直接合并排序法)。
?
冒泡排序(Bubble Sorting)
基本思想:通過對待排序序列從后向前(從下標(biāo)較大的元素開始),依次比較相鄰元素的排序碼,若發(fā)現(xiàn)逆序則交換,使排序碼較小的元素逐漸從后部移向前部。
如果一趟比較下來沒有進行交換,就說明序列有序。因此要在排序過程中設(shè)置一個標(biāo)志flag判斷元素是否進行過交換。從而減少不必要的比較(優(yōu)化)。

查找:
順序查找:

二分查找(該數(shù)組是有序的)
思路:要找的數(shù)是findval
①arr是一個有序數(shù)組,從小到大排序
②先找到中間的下標(biāo)middle=(leftlndex+rightIndex)/2,讓middle對應(yīng)的值和findval進行比較 如果arr[middle]> findval,令leftIndex = middle - 1
如果arr[middle]< findval,令rightlndex = middle+1
如果arr[middle]= findval,就找到
上面的邏輯會遞歸執(zhí)行
如果 leftIndex>rightIndex,則找不到
?
二維數(shù)組

四種聲明/定義寫法:
var數(shù)組名?[大小][大小]類型?=?[大小][大小]類型{{初值..},{初值..}}
var數(shù)組名?[大小][大小]類型?=?[...][大小]類型{{初值..},{初值..}}
var數(shù)組名?=?[大小][大小]類型{{初值..},{初值..}}
var數(shù)組名?=?[...][大小]類型{{初值..},{初值..}}
?
二位數(shù)組的遍歷:for循環(huán)遍歷、for-range遍歷

map
map是key-value數(shù)據(jù)結(jié)構(gòu),又稱為字段或者關(guān)聯(lián)數(shù)組。
var map變量名map[keytype]valuetype.
?
golang中的map的key可以是很多種類型,比如 bool,數(shù)字,string,指針,channel,還可以是只包含前面幾個類型的接口,結(jié)構(gòu)體,數(shù)組。通常key為int 、string
Slice、map、function不可以,因為這幾個沒法用 == 來判斷
?
valuetype的類型和key基本一樣,通常為:數(shù)字(整數(shù),浮點數(shù)),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

①聲明是不會分配內(nèi)存的,初始化需要make,分配內(nèi)存后才能賦值和使用。
②map的key是不能重復(fù),如果重復(fù)了,則以最后這個key-value為準(zhǔn)。
③map的value是可以相同的。
④map的key-value是無序的
⑤make內(nèi)置函數(shù)數(shù)目
?
內(nèi)建函數(shù)make分配并初始化一個類型為切片、映射、或通道的對象。
其第一個實參為類型,而非值。make的返回類型與其參數(shù)相同,而非指向它的指針。
切片:size指定了其長度。該切片的容量等于其長度。切片支持第二個整數(shù)實參可用來指定不同的容量;它必須不小于其長度,因此make([]int,0,10)會分配一個長度為0,容里為10的切片。
映射:初始分配的創(chuàng)建取決于size,但產(chǎn)生的映射長度為0。size可以省略,這種情況下就會分配一個小的起始大小。
通道:通道的緩存根據(jù)指定的緩存容量初始化。若size為零或被省略,該信道即為無緩存的。
?
map的使用:

①增加和更新:
map[ "key"]= value。如果key還沒有,就是增加,如果 key存在就是修改。
?
②刪除:
delete(map,"key"),delete是一個內(nèi)置函數(shù),如果key存在,就刪除該key-value,如果key不存在,不操作,但是也不會報錯。
如果要刪除map的所有key ,可以遍歷一下key,逐個刪除或者map = make(...),make一個新的,讓原來的成為垃圾,被g回收。
?
③查找:

④map的長度:
func len(v Type) int
內(nèi)建函數(shù)len返回v的長度,這取決于具體類型:
數(shù)組:v中元素的數(shù)量
數(shù)組指針:v中元素的數(shù)量(v為ni1時panic)
切片、映射:v中元素的數(shù)量:若v為nil,len(v)即為零
字符串:v中字節(jié)的數(shù)量
通道:通道緩存中隊列(未讀?。┰氐臄?shù)量;若v為nil,len(v)即為零
?
⑤遍歷:使用for-range

map切片:map個數(shù)可以動態(tài)變化了
案例:使用一個map來記錄monster的信息name和age。一個monster對應(yīng)一個map,并且妖怪的個數(shù)可以動態(tài)的增加 → map切片

Map排序:
①golang中沒有一個專門的方法針對map 的key進行排序。
②golang中的map默認(rèn)是無序的,不是按照添加的順序存放的,你每次遍歷,得到的輸出可能不一樣。
③golang中map的排序,是先將key進行排序,然后根據(jù)key值遍歷輸出即可。

?Map使用細(xì)節(jié):
① map是引用類型,遵守引用類型傳遞的機制,在一個函數(shù)接收 map,修改后,會直接修改原來的map。
②map的容量達(dá)到后,再想map增加元素,會自動擴容,并不會發(fā)生panic,也就是說 map能動態(tài)的增長鍵值對(key-value)
③map的value也經(jīng)常使用struct類型,更適合管理復(fù)雜的數(shù)據(jù)。
?
練習(xí):
①使用map[string]map[string]sting的map類型
②key:表示用戶名,是唯一的,不可以重復(fù)
③如果某個用戶名存在,就將其密碼修改"888888",如果不存在就增加這個用戶信息:(包括昵稱nickname和密碼pwd) 。
④編寫一個函數(shù)modifyUser(users map[string]map[string]sting, name string)完成上述功能。

?
?