Go语言学习教程(九)

一、双向链表概述

* 双向链表结构中元素在内存中不是紧邻空间,而是每个元素中存放上一个元素和后一个元素的地址

    * 第一个元素称为头(head)元素,前连接(前置指针域)为nil

    * 最后一个元素称为尾(foot)元素,后连接(后置指针域)为nil

* 双向链表的优点:

    * 在执行新增元素或删除元素时效率高,获取任意一个元素,可以方便的在这个元素前后插入元素

    * 充分利用内存空间,实现内存灵活管理

    * 可实现正序和逆序遍历

    * 头元素和尾元素新增或删除时效率较高

* 双向链表的缺点

    * 链表增加了元素的指针域,空间开销比较大

    * 遍历时跳跃性查找内容,大量数据遍历性能低

二、双向链表容器List

* 在Go语言标准库的container/list 包提供了双向链表List

* List结构体定义如下

    * root表示根元素

    * len表示链表中有多少个元素

    type List struct {

        root Element 

        len  int     

    }

* 其中Element结构体定义如下

    * next表示下一个元素,使用Next()可以获取到

    * prev表示上一个元素,使用Prev()可以获取到

    * list表示元素属于哪个链表

    * Value表示元素的值,interface{}在Go语言中表示任意类型

    type Element struct {

          next, prev *Element

          list *List

          Value interface{}

     }

三、操作List

* 直接使用container/list包下的New()新建一个空的List

    mylist := list.New()

    fmt.Println(mylist)       //输出list中内容

    fmt.Println(mylist.Len()) //查看链表中元素的个数

    fmt.Printf("%p", mylist)  //输出地址

* Go语言标准库中提供了很多向双向链表中添加元素的函数

    //添加到最后,List["a"]

    mylist.PushBack("a")

    //添加到最前面,List["b","a"]

    mylist.PushFront("b")

    //向第一个元素后面添加元素,List["b","c","a"]

    mylist.InsertAfter("c", mylist.Front())

    //向最后一个元素前面添加元素,List["b","c","d","a"]

    mylist.InsertBefore("d", mylist.Back())

* 取出链表中的元素

    fmt.Println(mylist.Back().Value)  //最后一个元素的值

    fmt.Println(mylist.Front().Value) //第一个元素的值

    //只能从头向后找,或从后往前找,获取元素内容

    n := 5

    var curr *list.Element

    if n > 0 && n <= mylist.Len() {

        if n == 1 {

            curr = mylist.Front()

        } else if n == mylist.Len() {

            curr = mylist.Back()

        } else {

            curr = mylist.Front()

            for i := 1; i < n; i++ {

                curr = curr.Next()

            }

        }

    } else {

        fmt.Println("n的数值不对")

    }

    //遍历所有值

    for e := mylist.Front(); e != nil; e = e.Next() {

        fmt.Println(e.Value)

    }

* 删除元素

mylist.Remove(mylist.Front())

四、双向循环链表

* 循环链表的特点是没有节点的指针域为nil,通过任何一个元素都可以找到其他元素

* 双向循环链表和双向链表区别

    * 双向循环链表没有严格意义上的头元素和尾元素

    * 没有元素的前连接和后连接为nil

    * 一个长度为n的双向循环链表,通过某个元素向某个方向移动,在查找最多n-1次后一定会找到另一个元素

* Go语言标准库中对container/ring包提供的API如下

type Ring

        //实例化长度为n的环形链表

        func New(n int) *Ring

        //长度

        func (r *Ring) Len() int

        //下一个元素

        func (r *Ring) Next() *Ring

        //上一个元素

        func (r *Ring) Prev() *Ring

        //移动n次,支持负数

        func (r *Ring) Move(n int) *Ring

        //合并s和r

        func (r *Ring) Link(s *Ring) *Ring

        //删除r后面n%r.Len()元素,删除多个,当前元素前面的不删除

        func (r *Ring) Unlink(n int) *Ring

        //循环遍历,i是当前元素的值

        func (r *Ring) Do(f func(interface{}))

五、函数

* 函数:一段代码块

* 所有的流程控制代码和业务代码都只能写在函数内部

* 为什么使用函数:

    * 把一个功能提取出来作为一个函数,这样便于后期维护,结构清晰

* 函数声明的语法

    * 函数声明后不会执行,必须调用后才会执行

    func 函数名(参数列表) 返回值{

      //函数体

    }

* 函数调用的语法

    返回值:=函数名(参数)

* 函数可以有参数也可以没有参数,可以有返回值也可以没有返回值

* 函数的参数可以有多个,且每个参数类型都可以不同

* 参数表示调用函数方想要给函数内部传递的值,是给函数使用的值.

* 声明函数时的参数叫做形参,调用函数时的参数叫做实参

func main() {

    i:=5

    s:="smallming"

    show(s,i)

}

func show(name string,age int){

    fmt.Println("姓名:",name,"年龄",age)

}

* 函数的返回值是给调用方返回的数据,给调用方使用的.

* 具有返回值的函数,必须要有return

* 也可以在返回值类型前面添加变量,return关键字后不写内容,表示变量是什么返回值什么

六、多返回值函数

* 在Go语言中每个函数声明时都可以定义成多返回值函数

* Go语言中所有的错误都是通过返回值返回的

* 声明多返回值函数的语法

func 函数名(参数列表) (返回值,返回值){

  //函数体

}

* 调用函数的语法

    变量,变量:=函数名(参数)

* 调用函数时如果不想接收返回值可以使用下划线占位

    变量,_:=函数名(参数)

* 理论上函数返回值个数可以无限多个,但是一般不去定义特别多个返回值(用结构体代替多返回值)

* 函数的返回值可以不接收,表示执行函数

* 函数的返回值如果接收,用于接收返回值的变量个数与返回值个数相同

* 不想接收的使用占位符(_)占位

func main() {

    //不接收函数返回值

    demo()

    //每个返回值都接收

    a, b := demo()

    fmt.Println(a, b)

    //不希望接收的返回值使用下划线占位

    c, _ := demo()

    fmt.Println(c)

}

func demo() (string, int) {

    return "smallming", 17

}

七、可变参数函数

* Go语言支持可变参数函数

* 可变参数指调用参数时,参数的个数可以是任意个

* 可变参数必须在参数列表最后的位置,在参数名和类型之间添加三个点表示可变参数函数

func 函数(参数,参数,名称 ... 类型 ){

    //函数体

}

* 可变参数必须存在其他参数后面,一个函数不能有多个可变参数.

func demo(hover ... string) {

    for a, b := range hover {

        fmt.Println(a, b)

    }

}

你可能感兴趣的:(Go语言学习教程(九))