1、排序算法之go實現golang
1.冒泡排序算法
func bubbleSort(slice []int){ for i := 0; i < len(slice); i++{ ctn := 0 for j := 0; j < len(slice) - i - 1; j++{ if slice[j] > slice[j+1]{ slice[j], slice[j+1] = slice[j+1], slice[j] ctn ++ } } if ctn == 0{ break } } } func main(){ slice := []int{2,6,4,3,1,7,9,12,31,15} bubbleSort(slice) fmt.Println(slice) }
2.選擇排序json
func selectSort(slice []int){ var min_ind int for i := 0; i < len(slice); i++{ min_ind = i for j := i + 1; j < len(slice); j++{ if slice[j] < slice[min_ind]{ slice[j], slice[min_ind] = slice[min_ind], slice[j] } } } } func main(){ slice := []int{2,6,4,3,1,7,9,12,31,15} selectSort(slice) fmt.Println(slice) }
3.插入排序數據結構
func insertSort(slice []int){ for i := 1; i < len(slice); i++{ for j := i; j > 0; j--{ if slice[j] > slice[j - 1]{ break } slice[j], slice[j - 1] = slice[j - 1], slice[j] } } } func main(){ slice := []int{2,6,4,3,1,7,9,12,31,15} insertSort(slice) fmt.Println(slice) }
4.快速排序ide
func quickSort(slice []int, first int, last int){ if first >= last{ return } mid_val := slice[first] low := first high := last for low < high{ for (low < high && slice[high] >= mid_val){ high-- } slice[low] = slice[high] for (low < high && slice[low] <= mid_val){ low++ } slice[high] = slice[low] } slice[low] = mid_val quickSort(slice, first, low - 1) quickSort(slice, high + 1, last) } func main(){ slice := []int{2,6,4,3,1,7,9,12,31,15} quickSort(slice, 0, len(slice) - 1) fmt.Println(slice) }
2、go中的struct函數
1.用來自定義複雜數據結構佈局
2.struct裏面能夠包含多個字段(屬性)ui
3.struct類型能夠定義方法(注意和函數的區分)this
4.struct類型是值類型spa
5.struct類型能夠嵌套
6.go語言沒有calss類型,只有struct類型
struct的定義
1.struct聲明
type 標識符 struct{ field1 type
field2 type }
2.struct中字段訪問,和其它語言同樣,使用點
3.struct定義的三種形式
var stu Student var stu *Student = new(Student) var stu *Student = &Student{} //其中b和c返回的都是指向結構體的指針,訪問形式以下: (*stu).Name,能夠簡寫成stu.Name
4.struct的內存佈局:struct中的全部字段在內存中是連續的,佈局以下:
type Student struct{ Name string Age int } func main(){ var stu1 = Student{ Name: "bob", Age: 18, } var stu2 Student stu2.Name = "tony" stu2.Age = 18 fmt.Println(stu1) fmt.Println(stu2) fmt.Println(stu1.Name) fmt.Printf("addr:%p\n",&stu1.Name) fmt.Printf("addr:%p\n",&stu1.Age) }
鏈表定義
每一個節點包含下一個節點的地址,一般把鏈表中的第一個節點叫作鏈表頭
type Student struct{ Name string Next *Student }
type Student struct{ Name string Age int Next *Student } func trans(p *Student){ for p != nil{ fmt.Println(*p) p = p.Next } } func main(){ head := Student{ Name: "b1", Age: 18, } stu1 := Student{ Name: "b2", Age: 32, } head.Next = &stu1 trans(&head) }
package main import "fmt" type Student struct{ Name string Age int Next *Student } func forAppend(p *Student, n int){ tail := p for i := 0; i < n; i++{ stu := Student{ Name: fmt.Sprintf("b%d",i), Age: 19 + i, } tail.Next = &stu tail = &stu } } func trans(p *Student){ for p != nil{ fmt.Println(*p) p = p.Next } } func main(){ head := Student{ Name: "b", Age: 18, } forAppend(&head,10) trans(&head) }
package main import "fmt" type Student struct{ Name string Age int Next *Student } func forInsert2(p *Student, n int) *Student{ for i := 0; i < n; i++{ stu := Student{ Name: fmt.Sprintf("b%d",i), Age: 19 + i, } stu.Next = p p = &stu //只是更改了指針的副本 } return p } func trans(p *Student){ for p != nil{ fmt.Println(*p) p = p.Next } } func main(){ head := Student{ Name: "b", Age: 18, } p := forInsert2(&head, 10) trans(p) }
package main import "fmt" type Student struct{ Name string Age int Next *Student } func forInsert1(p **Student, n int){ //傳入指針的地址 for i := 0; i < n; i++{ stu := Student{ Name: fmt.Sprintf("b%d",i), Age: 19 + i, } //更改指針的地址 stu.Next = *p *p = &stu } } func trans(p *Student){ for p != nil{ fmt.Println(*p) p = p.Next } } func main(){ // head := Student{ // Name: "b", // Age: 18, // } // p := forInsert2(&head, 10) // trans(p) var head *Student = new(Student) head.Name = "b" head.Age = 18 forInsert1(&head, 10) trans(head) }
//刪除屬性Name爲b8的節點 func del(p *Student, name string){ prev := p for p != nil{ if p.Name == name{ prev.Next = p.Next } prev = p p = p.Next } } //沒法刪除頭節點 //改寫 func del(p **Student, name string){ //前一個節點 var prev *Student //當前節點 cur := *p for cur != nil{ if cur.Name == name{ //若是是刪除頭節點,就更改頭節點的地址 if cur == *p{ *p = (*p).Next }else{ prev.Next = cur.Next } break } prev = cur cur = cur.Next } } func main(){ var head *Student = new(Student) head.Name = "b" head.Age = 18 forInsert1(&head, 10) del(&head, "b8") trans(head) }
雙鏈表的定義
兩個指針分別指向前一個節點和後一個節點
type Student struct{ Name string Next *Student }
二叉樹定義:
兩個指針分別指向左子樹和右子樹
type Student struct{ Name string Left *Student Right *Student }
//二叉樹 package main import "fmt" type Student struct{ Name string Age int Left *Student Right *Student } func trans(root *Student){ if root == nil{ return } fmt.Println(root.Name) trans(root.Left) trans(root.Right) } func main(){ var root = new(Student) root.Name = "stu0" root.Age = 18 var left01 = new(Student) left01.Name = "stu1" left01.Age = 20 var right01 = new(Student) right01.Name = "stud2" right01.Age = 25 var right02 = new(Student) right02.Name = "stud3" right02.Age = 30 root.Left = left01 root.Right = right01 right01.Left = right02 trans(root) }
5.結構體是用戶單獨定義的類型
type integer int var i integer = 1 var j int = 2 //i,j是屬於不一樣類型
package main import "fmt" type myInt int func main(){ var a myInt = 10 var b int = 20 //編譯不經過,a和b是不一樣的類型 a = b fmt.Println(a) } func main(){ var a myInt = 10 var b int = 20 //須要強制轉換 a = myInt(b) fmt.Println(a) }
golang沒有構造函數,可使用工廠模式解決這個問題
package model type Student struct{ Name string Age int } func NewStudent(name string, age int)*student{ return &student{ Name: name Age: age } } packeage main //s := new(Student) s := model.NewStudent("tony",20)
6.struct中的tag
咱們能夠爲struct中的每一個字段,寫上一個tag,這個tag能夠經過反射的機制獲取到,最經常使用的場景就是json的序列化與反序列化
type Student struct{ Name string "this is name field" Age int "this is age field" }
package main import ( "fmt" "encoding/json" ) type Student struct{ Name string `json:"name"` Age int `json:"age"` } func main(){ stu := Student{ Name: "bob", Age: 18, } data, err := json.Marshal(stu) if err != nil{ fmt.Println("json encode faile") return } fmt.Println(string(data)) }
7.結構體中字段能夠沒有名字,即匿名字段
type Train struct{ Car Start time.Time int }
package main import "fmt" type Student struct{ Name string Age int } type Class struct{ Name string Student } func main(){ var c1 Class //當結構體中有該字段,直接訪問 c1.Name = "T1" //經過類型點的方式訪問匿名字段 c1.Student.Name = "bob" c1.Student.Age = 18 //不能同時出現相同類型的兩個匿名字段 fmt.Println(c1) }
方法
golang中的方法是做用在特定類型的變量上,所以自定義類型均可以有方法,不單單是struct
1.定義
func(recevier type) methodName(參數列表)(返回值列表){
}
type Student struct{ Name string Age int } //this就是stu,init爲方法名 func (this *Student) init(name string, age int){ this.Name = name this.Age = age } func main(){ var stu Student }
2.方法的調用
func (this *Student) init(name string, age int){ this.Name = name this.Age = age } func main(){ var stu Student //其實本質是(&stu).init("bob", 18),go作了簡化 stu.init("bob", 18) fmt.Println(stu) }
3.指針receiver和值receiver:本質上和函數的值傳遞和地址傳遞是同樣的
4.方法的訪問控制,經過大小寫控制
5.繼承:若是一個struct嵌套了另外一個匿名結構體,那麼這個結構體能夠直接訪問匿名結構體的方法,從而實現繼承;組合:若是一個struct嵌套了另外一個有名結構體,那麼這個模式就叫作組合
package main import "fmt" type Animal struct{ Name string } func (this Animal) Speak(){ fmt.Printf("%v正在咆哮...\n",this.Name) } type Dog struct{ Animal } type Zoo struct{ Name string D Dog } func main(){ var d1 Dog d1.Name = "大黃" d1.Speak() var zoo Zoo zoo.Name = "1th" zoo.D.Speak() }
6.多重繼承:若是一個struct嵌套了多個匿名結構體,那麼這個結構體能夠直接訪問多個匿名結構體的方法,從而實現了多重繼承
接口實現String():
若是一個變量實現了String()這個方法,那麼fmt.Printf默認會調用這個變量的String()進行輸出
package main import "fmt" type Animal struct{ Name string } func (this Animal) String() string{ str := fmt.Sprintf("name=[%s]",this.Name) return str } type Dog struct{ Animal } func main(){ var d1 Dog d1.Name = "大黃" fmt.Printf("%s",d1) }