• 【Go数据结构】静态链表 Static List


    和链表一样,只是针对没有指针的语言。添加一个数据存储下一个元素的游标。

    image.png

    可以看到,A的游标是1,指向的下一个元素在2,就是C。

    image.png

    插入的时候,就把A下个元素指向5,就是B,B的下个元素是2,就是C。

    • 优点:
      • 插入不用移动元素。(申请内存很困难的情况)
    • 缺点:
      • 和数组一样,不知道长度。
      • 失去了数组的随机访问特性。
    • 总结:基本不会使用,但是是一种思路。(现在内存都不是瓶颈了)

    Go实现:

    package static_list
    
    import (
       "fmt"
       "my_go/dataStructure/list"
    )
    
    //静态链表
    type StaticList struct {
       Element [list.MAXSIZE]StaticNode
       Length  int
    }
    
    type StaticNode struct {
       Data list.ElemType //数据
       Cur  int           //游标
    }
    
    //静态链表理论上是要用参数传递的。
    
    //初始化列表
    func (l *StaticList) InitList() {
       l.Length = 0
       for i := 0; i < list.MAXSIZE; i++ {
          l.Element[i] = StaticNode{list.EmptyElement, i + 1}
       }
       //初始化使还没有数据,所以这时头结点指针指向0,代表空
       l.Element[list.MAXSIZE-1].Cur = 0
    }
    
    //清空列表 就是将首尾两个数组设置为原始的1和0
    func (l *StaticList) ClearList() {
       l.Element[0].Cur = 1
       l.Element[list.MAXSIZE-1].Cur = 0
    }
    
    //判断是否为空
    func (l *StaticList) ListEmpty() bool {
       if l.Length > 0 {
          return false
       }
       return true
    }
    
    //获取长度
    func (l *StaticList) ListLength() int {
       return l.Length
    }
    
    //获取指定位置的元素,返回在指针元素中
    func (l *StaticList) GetElem(index int, e *list.ElemType) bool {
    
       if l.Length == 0 {
          fmt.Println("获取失败,队列为空")
          return false
       }
       if index < 1 || index > l.Length {
          fmt.Println("获取失败,位置错误")
          return false
       }
    
       //获取头结点
       index_first := l.Element[list.MAXSIZE-1].Cur
    
       for j := 1; index_first != 0; j++ {
          if j == index {
             *e = l.Element[index_first].Data
             break
          }
          index_first = l.Element[index_first].Cur
       }
    
       return true
    }
    
    //查找元素在线性表中的位置
    func (l *StaticList) LocateElem(value list.ElemType) int {
    
       if l.Length == 0 {
          fmt.Println("获取失败,队列为空")
          return 0
       }
    
       //获取头结点
       index_first := l.Element[list.MAXSIZE-1].Cur
    
       j := 1
       for ; j < list.MAXSIZE; j++ {
          if l.Element[index_first].Data == value {
             break
          }
          index_first = l.Element[index_first].Cur
       }
    
       return j
    }
    
    //获取备份链表的第一个可用下标
    func (l *StaticList) Malloc_SLL() int {
    
       //获取当前数组的第一个元素中存放的可用下标
       i := l.Element[0].Cur
    
       //若是下标可用,若是指向0,数组空间全部用尽
       if l.Element[0].Cur != 0 {
          l.Element[0].Cur = l.Element[i].Cur
       }
    
       return i
    }
    
    //增
    func (l *StaticList) ListInsert(index int, value list.ElemType) bool {
    
       if l.Length == list.MAXSIZE { //满了
          fmt.Println("插入失败,队列已满")
          return false
       }
       if index < 1 || index > l.Length+1 {
          fmt.Println("插入失败,位置错误")
          return false
       }
    
       //获取空闲分量的下标
       free_index := l.Malloc_SLL()
    
       k := list.MAXSIZE - 1 //k首先是最后一个元素的下标
       if free_index != 0 {
          l.Element[free_index].Data = value
          for i := 1; i < index-1; i++ { //找到第i个元素的之前的位置
             k = l.Element[k].Cur
          }
          //把第i个元素之前的cur赋值给新的元素的cur
          l.Element[free_index].Cur = l.Element[k].Cur
          l.Element[k].Cur = free_index
    
          l.Length++
          return true
       }
    
       return false
    }
    
    //将回退首数组的数据,指向我们删除的那个空间,不会造成内存碎片
    func (l *StaticList) Free_SLL(k int) {
    
       //将我们删除的这个元素游标指向原来的下一个空闲分量,方便一会回到原来的位置
       l.Element[k].Cur = l.Element[0].Cur
    
       //将我们删除的那个元素放入到0下标的游标中,在下一次插入时会被调用,存放数据,节约空间
       l.Element[0].Cur = k
    }
    
    //删
    func (l *StaticList) ListDelete(index int, e *list.ElemType) bool {
       if l.Length == 0 {
          fmt.Println("获取失败,队列为空")
          return false
       }
       if index < 1 || index > l.Length {
          fmt.Println("获取失败,位置错误")
          return false
       }
    
       first_index := list.MAXSIZE - 1 //头结点位置
    
       //注意下标index开始和j的关系,我们要删除第三个,j会循环两次,
       // 我们若是从index = space[MAXSIZE-1].cur(是指向第一个)开始,
       // 循环两次会直接指向我们要删除的那个,而不是我们想要的前一个
       j := 0
    
       //找到我们要删除的元素的前一个i-1元素的下标
       for j = 1; j < index; j++ {
          first_index = l.Element[first_index].Cur
       }
       //用来保存原来删除的那个元素下标
       j = l.Element[first_index].Cur
       *e = l.Element[j].Data
       //使前一个元素游标指向要删除元素下一个元素的下标,跳过中间这个要删除的
       l.Element[first_index].Cur = l.Element[j].Cur
       //将我们删除的那个元素下标放入到备用链表中
       l.Free_SLL(j)
    
       l.Length--
       return true
    }
    
    //输出
    func (l *StaticList) Echo() {
       start := l.Element[list.MAXSIZE-1].Cur
       index := start
       for index != 0 {
          fmt.Print(l.Element[index].Data, " ")
          index = l.Element[index].Cur
       }
       fmt.Println()
    }
    
    package static_list
    
    import (
       "fmt"
       "my_go/dataStructure/list"
       "testing"
    )
    
    func Test(t *testing.T) {
       fmt.Println("测试开始")
    
       my_list := new(StaticList)
       my_list.InitList()
    
       for i := 1; i <= 10; i++ {
          my_list.ListInsert(i, list.ElemType(i*i+1))
          my_list.Echo()
       }
    
       fmt.Println("第5个这里插入256")
       my_list.ListInsert(5, 256)
       my_list.Echo()
       my_list.ListInsert(199, 99)
    
       var e list.ElemType
    
       my_list.ListDelete(1, &e)
       fmt.Println("删除头元素:", e)
       my_list.Echo()
    
       my_list.ListDelete(my_list.ListLength(), &e)
       fmt.Println("删除尾元素:", e)
       my_list.Echo()
    
       my_list.GetElem(6, &e)
       fmt.Println("获取第6个:", e)
    
       fmt.Println("256的位置:", my_list.LocateElem(256))
    
       fmt.Println("长度:", my_list.ListLength())
    
       fmt.Println("开始清空")
       my_list.ClearList()
       if my_list.ListEmpty() {
          fmt.Println("已清空")
          my_list.Echo()
       }
    
    
       fmt.Println("测试完成")
    }
    
  • 相关阅读:
    PHP zip_entry_read() 函数
    PHP zip_entry_open() 函数
    PHP zip_entry_name() 函数
    PHP zip_entry_filesize() 函数
    PHP zip_entry_compressionmethod() 函数
    混合模式 | mix-blend-mode (Compositing & Blending)
    混合模式 | blend-mode (Compositing & Blending)
    浮动 | float (Basic Box Model)
    浏览器兼容性表 | @document (Miscellaneous)
    沿着内联轴溢出初始包含块 | @media.overflow-inline (Media Queries)
  • 原文地址:https://www.cnblogs.com/HappyTeemo/p/16283596.html
Copyright © 2020-2023  润新知