一、排序算法之go实现

1.冒泡排序

go func结构体 go 结构体方法_go func结构体

go func结构体 go 结构体方法_字段_02

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

View Code

2.选择排序

go func结构体 go 结构体方法_go func结构体

go func结构体 go 结构体方法_字段_02

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

View Code

3.插入排序

go func结构体 go 结构体方法_go func结构体

go func结构体 go 结构体方法_字段_02

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

View Code

4.快速排序

go func结构体 go 结构体方法_go func结构体

go func结构体 go 结构体方法_字段_02

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

View Code

二、go中的struct

1.用来自定义复杂数据结构

2.struct里面可以包含多个字段(属性)

3.struct类型可以定义方法(注意和函数的区分)

4.struct类型是值类型

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中的所有字段在内存中是连续的,布局如下:

go func结构体 go 结构体方法_go func结构体_09

go func结构体 go 结构体方法_go func结构体

go func结构体 go 结构体方法_字段_02

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

View Code

链表定义

每个节点包含下一个节点的地址,通常把链表中的第一个节点叫做链表头

type Student struct{
    Name string
    Next *Student
}

go func结构体 go 结构体方法_go func结构体

go func结构体 go 结构体方法_字段_02

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

链表实现

go func结构体 go 结构体方法_go func结构体

go func结构体 go 结构体方法_字段_02

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

循环后插

go func结构体 go 结构体方法_go func结构体

go func结构体 go 结构体方法_字段_02

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

循环头插1

go func结构体 go 结构体方法_go func结构体

go func结构体 go 结构体方法_字段_02

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

循环头插2

go func结构体 go 结构体方法_go func结构体

go func结构体 go 结构体方法_字段_02

//删除属性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
}

go func结构体 go 结构体方法_go func结构体

go func结构体 go 结构体方法_字段_02

//二叉树

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

View Code

 5.结构体是用户单独定义的类型

type integer int
var i integer = 1
var j int = 2
//i,j是属于不同类型

go func结构体 go 结构体方法_go func结构体

go func结构体 go 结构体方法_字段_02

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

View Code

golang没有构造函数,可以使用工厂模式解决这个问题

go func结构体 go 结构体方法_go func结构体

go func结构体 go 结构体方法_字段_02

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)

View Code

6.struct中的tag

我们可以为struct中的每个字段,写上一个tag,这个tag可以通过反射的机制获取到,最常用的场景就是json的序列化与反序列化

type Student struct{
    Name string "this is name field"
    Age int    "this is age field"
}

go func结构体 go 结构体方法_go func结构体

go func结构体 go 结构体方法_字段_02

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

View Code

7.结构体中字段可以没有名字,即匿名字段

type Train struct{
    Car
    Start time.Time
    int
}

go func结构体 go 结构体方法_go func结构体

go func结构体 go 结构体方法_字段_02

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

View Code

方法

golang中的方法是作用在特定类型的变量上,因此自定义类型都可以有方法,不仅仅是struct

1.定义

func(recevier type) methodName(参数列表)(返回值列表){

}

go func结构体 go 结构体方法_go func结构体

go func结构体 go 结构体方法_字段_02

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
}

View Code

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嵌套了另一个有名结构体,那么这个模式就叫做组合

go func结构体 go 结构体方法_go func结构体

go func结构体 go 结构体方法_字段_02

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

View Code

6.多重继承:如果一个struct嵌套了多个匿名结构体,那么这个结构体可以直接访问多个匿名结构体的方法,从而实现了多重继承

接口实现String():

如果一个变量实现了String()这个方法,那么fmt.Printf默认会调用这个变量的String()进行输出

go func结构体 go 结构体方法_go func结构体

go func结构体 go 结构体方法_字段_02

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

View Code