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) }