阿里云优惠活动,点击链接进行购买: 一年仅需89元即可以购买服务器~。我个人服务器为2核4G配置,也更加推荐购买 2核4G三年799元 配置的服务器。
你可以跟着我的笔记 当我有一台服务器时,我做了什么 来开始维护服务器并搭建应用,将引导你使用 docker 和 k8s 搭建一个自己的服务器开发集群。

# 线性表结构

数组 链表(单向、双向、循环) 特殊的线性表:栈 特殊的线性表:队列 编程技巧:递归

# 线性表分为顺序存储结构和链式存储结构

# 线性表的顺序存储结构

  • 优点:
    • 无需为表示表中元素之间的逻辑关系而增加额外的存储空间(有下标)
    • 可以快速的存\取表中任意位置的元素
  • 缺点:
    • 插入和删除操作需要移动大量的元素,耗费时间
    • 当线性表长度变化较大时,难以确定存储空间的容量
    • 容易造成存储空间的"碎片"(申请空间是一整块申请的) Golang实现线性表顺序存取结构
package main
import (
    "errors"
    "fmt"
)
const MAX_LENGTH = 20 // 常量定义线性表最大长度
// 定义一个线性表顺序存储结构体
type LineList struct {
    MaxLength  int
    Length int
    LineListContent []interface{}
}
// 初始化一个线性表
func InitLineList () *LineList{
    return &LineList{MaxLength:MAX_LENGTH, LineListContent:make([]interface{},0,MAX_LENGTH)}
}
// 判断当前线性表是否为空
func (l LineList) IsEmpty() bool {
    if l.Length == 0{
        return true
    }
    return false
}
// 判断当前线性表是否满了
func (l LineList) IsFull() bool{
    if l.Length == l.MaxLength{
        return true
    }
    return false
}
// 判断索引是否越界,越界返回true
func (l LineList) indexOver(i int) bool{
    if i < 1 || i >l.Length{
        return true
    }
    return false
}
// 获取一个node数据
func (l LineList) getData(i int )(interface{},error){
    if ok:= l.indexOver(i); ok{
        return "",errors.New("查找的索引不在线性表范围内")
    }
    return l.LineListContent[i+1],nil
}
// 任意位置删除一个node数据
func (l *LineList) Delete(i int)(interface{},error){
    if ok:= l.indexOver(i); ok{
        return "",errors.New("删除的索引不在线性表范围内")
    }
    if ok:=l.IsEmpty();ok{
        return  "",errors.New("空表没有可删除的数据")
    }
    deleteData := l.LineListContent[i-1]
    for j:=i-1; j<l.Length-1;j++{
        l.LineListContent[j] = l.LineListContent[j+1]
        fmt.Println(j,"个",l.LineListContent[j])
    }
    l.LineListContent = l.LineListContent[:l.Length-1] // 留了最后一个在,需要切除
    l.Length --
    return deleteData,nil
}
//末尾 pop 一个数据
func (l *LineList) Pop()(interface{},error){
    if ok:= l.IsEmpty();ok{
        return "",errors.New("空表,无法删除任何数据")
    }
    temp := l.LineListContent[l.Length-1]
    l.LineListContent = l.LineListContent[:l.Length-1]
    l.Length --
    return temp,nil
}
// 末尾 Append 一个数据
func (l *LineList) Append(data interface{})(bool,error){
    if ok:= l.IsFull(); ok{
        return false,errors.New("线性表已满,无法添加数据")
    }
    l.LineListContent = append(l.LineListContent, data)
    l.Length ++
    return true,nil
}
// 任意位置 insert 一个数据
func (l *LineList) Insert(i int,data interface{})(bool,error){
    if ok:= l.IsFull(); ok{
        return false,errors.New("线性表已满,无法添加数据")
    }
    if ok:= l.indexOver(i);ok{
        return false,errors.New("插入点越界")
    }
    l.Append("") // 增加一个空数据,防止下面访问越界
    for j:=l.Length-1;j>i-1;j--{
        //从后往前赋值,新增一个空node,然后把数据一个个后移,直到插入的位置
        //知道线性表从1开始,而切片是从0开始的
        l.LineListContent[j] = l.LineListContent[j-1]
    }
    l.LineListContent[i-1] = data
    return true,nil
}
func main(){
    ls := InitLineList()
    ls.Append(11)
    fmt.Println(ls.LineListContent) //[11]
    fmt.Println(ls.Length) // 1
    ls.Insert(3,"gac")
    ls.Insert(1,"gac")
    fmt.Println(ls.LineListContent) //[gac 11]
    fmt.Println(ls.Length)  //2
    ls.Delete(2)
    fmt.Println(ls.LineListContent) //[gac]
    fmt.Println(ls.Length)     // 1
    cd,err0 := ls.Pop()
    if err0==nil{
        fmt.Println(cd)      // gac
    }
    fmt.Println(ls.LineListContent) //[]
    fmt.Println(ls.Length)    // 0
}

# 线性表的链式存储结构--单链表

  • 特点:除了要存储数据元素信息外还要存储后继元素的存储地址(指针)数据域+指针域=存储映像(节点node),因为此链表的每个节点中值包含一个指针域,所以叫做单链表
package main

import (
    "fmt"
)
type Node struct {
    data interface{}
    next *Node
}
// get the first Node
func (n *Node) getFirstNode() *Node{
    if n.next == nil{
        return nil
    }
    return n.next
}
// get the end Node
func (n *Node) getEndNode() *Node{
    if n.next == nil{
        return nil
    }
    for n.next != nil{
        n = n.next
    }
    return n
}
// Append a Node to linkList
func (n *Node) Append(data interface{})bool{
    // create a Node
     tempNode := &Node{data, nil}
     //i := n
     for n.next!=nil{
         n = n.next
     }
     n.next = tempNode
     return true
}
// find a Node
func (n *Node) getOneNode(i int)*Node{
    length := 0
    for n.next!=nil{
        length ++
        if i == length{
            return n.next
        }
        n = n.next
    }
    return nil
}
// delete a Node
func (n *Node) Delete(i int)*Node{
    length:=0
    for n.next!=nil{
        length ++
        if i == length{
            temp := n.next
            n.next = n.next.next
            return temp
        }
        n = n.next
    }
    return nil
}
// insert into the LinkList everywere
func (n *Node) Insert (i int ,data interface{}) bool {
    needAppend := &Node{ data ,nil}
    if i>n.getLinkLength() || i< 1{
        panic("插入位置错误")
        return false
    }
    length := 1
    for n.next != nil{
        if i == length{
            temp := n.next
            n.next = needAppend
            needAppend.next = temp
            return true
        }
    }
    return false
}
func (n *Node)getLinkLength()int{
    length := 0
    for n.next!=nil{
        length++
        n = n.next
    }
    return length
}
// map the LinkList all data
func (n *Node) MapTheLinkList(){
    length := n.getLinkLength()
    for i:=0;i<length; i++{
        fmt.Println(n.next.data)
        n = n.next
    }
}
func (n *Node) Clear() bool{
    if n.next == nil{
        return true
    }
    n.next = nil
    return true
}
// init a linkList
func initLinkList () *Node{
    return &Node{"the head node",nil}
}
func main(){
    li := initLinkList() // 初始化一个空单链表
    fmt.Println(li)      
    li.Append("aaa")  
    fmt.Println(li)
    li.Append("bbb")
    li.Append("ccc")
    li.Append("ddd")
    fmt.Println(*li.getFirstNode()) //{aaa 0xc04204a440}
    fmt.Println(*li.getEndNode())   //{ddd <nil>}
    fmt.Println(li.getLinkLength())  // 4
    fmt.Println("delete = ", li.Delete(1)) //delete =  &{aaa 0xc04204a440}
    fmt.Println(*li.getFirstNode())  //{bbb 0xc04204a460}
    fmt.Println(*li.getEndNode())    //{ddd <nil>}
    fmt.Println(li.getLinkLength())  // 3
    li.Append("eee")
    li.Append("ggg")
    li.MapTheLinkList()  // bbb ccc ddd eee ggg
    fmt.Println(li.getLinkLength())  //5
    li.Clear()  
    fmt.Println(li) //&{the head node <nil>}
}
  • 线性表的链式存储,以及使用快慢指针找不知长度链表的中间节点
package main

import (
    "fmt"
    "strconv"
)

// 定义一个node结构体
type Node struct {
    data string
    next *Node
}
func (n *Node) Append(data string){
    createNode := &Node{data,nil}
    for n.next != nil{
        n = n.next
    }
    n.next = createNode
}
func (n *Node) GetLength() int{
    if n.next==nil{
        return 0
    }
    length:= 0
    for n.next!=nil{
        length ++
        n = n.next
    }
    return length
}
func (n *Node) MapLinkList()[]string{
    var str []string
    if n.next == nil{
        return nil
    }
    for n.next != nil{
        str = append(str,n.next.data)
        n = n.next
    }
    return str
}
// 快慢指针法求不知道长度的链表的中间值
func (n *Node)GetCenterNode()[]string{
    str := make([]string,0,2)
    if n.next==nil{
        return nil
    }
    l := n.next
    s := n.next
    for s.next!= nil{
        // 单数情况
        if l.next==nil{
             str = append(str, s.data)
             return str
        }
        // 双数情况
        if l.next != nil && l.next.next == nil{
             str = append(str,s.data)
             str = append(str,s.next.data)
             return str
        }
        s =s.next
        l = l.next.next
    }
    return str
}

// 初始化一个链表
func initLinkList ()*Node{
    return &Node{"genesis node", nil}
}
func Rand20List(n *Node){
    for i:=0;i<3;i++{
        n.Append("this is "+strconv.Itoa(i))
    }
}

func main(){
    link := initLinkList()
    var s int
    for {
        fmt.Println("1.查看链表")
        fmt.Println("2.创建链表20个数据")
        fmt.Println("3.链表长度")
        fmt.Println("4.查看中间节点值")
        fmt.Println("5.退出")
        fmt.Println("请输入选择:")
        fmt.Scan(&s)
        switch s {
        case 1:
            fmt.Println(link.MapLinkList())
        case 2:
            Rand20List(link)
        case 3:
            fmt.Println(link.GetLength())
        case 4:
            fmt.Println(link.GetCenterNode())

        case 5:
            return

        }
    }
}
Last Updated: 12/31/2019, 12:43:02 AM