范文健康探索娱乐情感热点
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

golang2021数据格式(74)list原理分析

  本文为"Goalng全面深入系列"中的标准库部分。
   
  1. 什么是双向链表
  (引用)
          和单链表比较,双向链表的元素不但知道自己的下线,还知道自己的上线(越来越像传销组织了)。小煤车开起来,图里面可以看出,每个车厢除了一个指向后面车厢的箭头外,还有一个指向前面车厢的箭头(车头、车尾除外)。车头只有指向后面车厢的箭头,车尾只有指向前面车厢的箭头。
  2. 和单向链表相比的优势
      1. 插入删除不需要移动元素外,可以原地插入删除
      2. 可以双向遍历
      插入数据到中间
  删除中间数据
  3、双向链表与Go的对应结构
  1.节点分析
  我们先把车厢分解开来。每节车厢都由煤炭、车体、拉前车厢绳索、拉后车厢绳索这4部分组成。车体是我们的运输工具,在Go语言里我们用结构提DNode表示;煤炭代表运的货物,用data变量表示;拉前车厢绳索和拉后车厢绳索我们分别用指针prev和next表示。这样一节车厢,用Go语言描述如下:
  type DNode struct {
   data Object
   prev *DNode
   next *DNode
  }
  2、双向链表
  一个运煤车队就是一个双向链表。车队要有车头、车厢、车尾,作为车队的负责人还得知道车队有多长。在Go语言里,车队用结构体DList表示,车头用head变量表示,车位用tail变量表示,车队长度就用size来表示,把这些表示合起来:
  type DList struct {
   size uint64
   head *DNode
   tail *DNode
  }
  通过找到其中一个节点,就可以通过prev 或 next指向得到指向的数据。
   
  4. Go自定义实现链表
  1.初始化Init
      双向链表的初始化,可以理解成大卫哥准备买一个车队准备运煤。第一步,得获得国家有关部门的批准,有了批准大卫哥就可以买车厢运煤了。但是,批准下来的时候,大卫哥的车队啥都没有,没有车头、车尾,连一节车厢也没有。Go语言代码实现:
  package main
  //节点数据结构
  type DNode struct {
          data interface{}
          prev *DNode
          next *DNode
  }
  // 链表数据结构
  type DList struct {
          size uint64
          head *DNode
          tail *DNode
  }
  // 链表的初始化
  func InitList() (list *DList) {
          list = *(DList)
          list.size = 0
          list.head = nil
          list.tail = nil
          return
  }
  // 新增数据
  func (dlist *DList) Append(data interface{}) {
          // 创建一个节点
          newNode := &DNode{data: data}
  if (*dlist).GetSize() == 0 { //只有一个节点
                  (*dlist).head = newNode
                  (*dlist).tail = newNode // 头尾节点都是自己
                  (*newNode).prev = nil   // 但是头尾的指向是nil
                  (*newNode).next = nil
          } else { // 接到尾部
                  // 新节点的指向修改
                  (*newNode).prev = (*dlist).tail
                  (*newNode).next = nil
  // 之前尾节点的指向修改
                  (*(*dlist).tail).next = newNode // 将之前的尾节点的next指向新增节点
  // 更新链表的尾节点
                  (*dlist).tail = newNode
          }
  // 更新链表的节点计数
          (*dlist).size++
  }
  // 在节点后面插入数据InsertNext
  //param
  //        - ele 所要插入的位置
  //        - data 所要插入的节点数据
  //
  func (dlist *DList) InsertNext(ele *DNode, data interface{}) bool {
          if ele == nil {
                  return false
          }
  if dlist.isTail(ele) { //正好在尾部
                  dlist.Append(data)
          } else { // 在中间插入
                  //构造新节点
                  newNode := new(DNode)
                  (*newNode).data = data
                  (*newNode).prev = ele         // 上一个节点就是ele
                  (*newNode).next = (*ele).next // 下一个节点就是ele原来的下一个节点
  // ele的下一个指向新节点
                  (*ele).next = newNode
  // ele之前下节点的prev重新指向新节点
                  *((*newNode).next).prev = newNode
  // 更新链表计数
                  (*dlist).size++
          }
  }
  //*====
  节点之前插入接口都是类似的方式:
          1. 首先根据数据创建新节点, 并设置指向
          2. 更新位置节点的指向数据
          3. 更新链表head , tail ,size数据
  删除节点:
          1. 首先获取要删除节点指向数据
          (验证头尾)
          2. 更新要删除节点的prev节点的next为要删除节点的next节点( 有点乱啊!!)
          3. 更新链表数据
  记得return要删除的节点数据(否则数据丢失)
  查找节点:
          type MatchFun func (data1 interface{}, data2 interface{}) int
          func (dList *DList) Search(data Object, yourMatch MatchFun) *DNode
  *=====*//
  // 获取链表长度GetSize
  func (dList *DList) GetSize() uint64 {
          return (*dList).size
  }
  //获取头部节点GetHead
  func (dList *DList) GetHead() *DNode {
          return (*dList).head
  }
  //获取尾部节点GetTail
  func (dList *DList) GetTail() *DNode {
          return (*dList).tail
  }
   
  通过自己实现链表,来更深入了解链表的结构后, 我们使用go的 container/list 库实现。
   
  5.Go库container/list 实现链表操作
  关于库的成员函数,我就不一一列举了, 看一看文档很详细,也很简单。
  下面直接上案例:
  func main() {
          link := list.New()
  // 循环插入到头部
          for i := 0; i <= 10; i++ {
                  link.PushBack(i)
          }
  // 遍历链表
          for p := link.Front(); p != link.Back(); p = p.Next() {
                  fmt.Println("Number", p.Value)
          }
  }
   
  6. slice和list的性能比较
  1. 创建、 添加元素的比较
  package main
  import (
          "container/list"
          "fmt"
          "time"
  )
  func main(){
    T1()
  }
  func T1() {
          t := time.Now()
          //1亿创建添加测试
          // slice 创建
  slice := make([]int, 10)
          for i := 0; i < 1*100000*1000; i++ {
                  slice = append(slice, i)
          }
          fmt.Println("slice 创建成功:", time.Now().Sub(t).String())
  // list创建添加
          t = time.Now()
          l := list.New()
          for i := 0; i < 1*100000*1000; i++ {
                  l.PushBack(i)
          }
          fmt.Println("list创建成功:", time.Now().Sub(t).String())
  }
  func T2() {
          sli := make([]int, 10)
          for i := 0; i < 1*100000*1000; i++ {
                  sli = append(sli, 1)
          }
  l := list.New()
          for i := 0; i < 1*100000*1000; i++ {
                  l.PushBack(1)
          }
          // 比较遍历
          t := time.Now()
          for _, _ = range sli {
                  //fmt.Printf("values[%d]=%d ", i, item)
          }
          fmt.Println("遍历slice的速度:" + time.Now().Sub(t).String())
          t = time.Now()
          for e := l.Front(); e != nil; e = e.Next() {
                  //fmt.Println(e.Value)
          }
          fmt.Println("遍历list的速度:" + time.Now().Sub(t).String())
  }
  func T3() {
          sli := make([]int, 10)
          for i := 0; i < 1*100000*1000; i++ {
                  sli = append(sli, 1)
          }
  l := list.New()
          for i := 0; i < 1*100000*1000; i++ {
                  l.PushBack(1)
          }
          //比较插入
          t := time.Now()
          slif := sli[:100000*500]
          slib := sli[100000*500:]
          slif = append(slif, 10)
          slif = append(slif, slib...)
          fmt.Println("slice 的插入速度" + time.Now().Sub(t).String())
  var em *list.Element
          len := l.Len()
          var i int
          for e := l.Front(); e != nil; e = e.Next() {
                  i++
                  if i == len/2 {
                          em = e
                          break
                  }
          }
          //忽略掉找中间元素的速度。
          t = time.Now()
          ef := l.PushBack(2)
          l.MoveBefore(ef, em)
          fmt.Println("list: " + time.Now().Sub(t).String())
  }
  简单的测试下,如果频繁的插入和删除建议用list,频繁的遍历查询选slice。
  由于container/list不是并发安全的,所以需要自己手动添加一层并发的包装。

一体机怎么换电池?一体式手机要换电池的话只能将手机前面板或者后盖拆开,然后将内部的电池电源排线断开分离电池与主板的连线,然后就可以把电池取下来了。不过因为更换过程中存在危险,并且极端情况下还有可能出用变压器将220v改变成12v,经过整流能给12v的锂电池充电吗?你怎么看?用变压器将220V改成12V经过整流能给12V的锂电池充电吗?你怎么看?完全可以!我折解了几个老手机充电器,里面除了变压器就是二极管,有一个诺基亚的充电器,除四只整流二极管,连电容银行会监控一个人的现金流水吗?会的,而且专门有个系统。前年的时候我儿子定居北京,要买房子,我给他转钱,就被监控了一次。北京房价高的离谱,所以儿子只能在郊区大兴买房,但是大兴的房价也要四万多一平米,最后看上一套房数字助听器与模拟助听器有什么不同?哪个对听力好?自然是数字助听器比较好,两种助听器采用的是不同的压缩放大技术,数字助听器采用的是非线性放大,小声多放大,大声少放大,根据不同频率进行相应的补偿,另外还有降噪等多种功能,可以在噪音及数字人民币接入支付宝最新消息功能目前处于小范围内测中数字人民币推广节奏加快。5月8日,数字人民币APP更新,钱包运营机构中的网商银行(支付宝)已呈现可用状态。换言之,网商银行成为继工农中建交邮储六大国有银行之后,第七家参与公测试点的作业帮猿辅导被顶格处罚针对群众反映强烈的校外教育培训机构乱象,市场监管总局价监竞争局会同北京市市场监管局开展联合行动,对小船出海教育科技(北京)有限公司(作业帮)和北京猿力教育科技有限公司(猿辅导)两家Linux的常用命令就是记不住,怎么办?于是推出了这套教程1。帮助命令1。1help命令语法格式命令help作用查看某个命令的帮助信息示例lshelp查看ls命令的帮助信息netstathelp查看netstat命令的帮助信息1。2man华为鸿蒙OS2。0开启第二轮公测,支持六款nova机型,附报名教程20210509,HarmonyOS2。0开发者Beta公测招募第二期正式开启Beta公测招募华为HarmonyOS2。0开发者Beta公测招募第二期正式开启本次机型支持nova6马斯克再度代言狗狗币,GBTC将成加密货币掘金工具美国时间5月8日,特斯拉CEO埃隆马斯克(ElonMusk)参与主持美国老牌娱乐综艺节目周六夜现场(SaturdayNightLive)后,狗狗币暴跌。马斯克再度代言狗狗币据海外媒未央今日播报网信办通报84款App违法违规收集使用个人信息支付宝对部分用户新增数字人民币模块国家网信办通报84款App违法违规收集使用个人信息,腾讯手机管家360手机卫士等在内5月10日消息,国家网信办发布关于腾讯手机管家等84款App违法违规收集使用个人信息情况的通报称手机圈大地震开始啦,鸿蒙必然导致安卓阵营分化华为鸿蒙OS2。0已经开始公测啦,老马身边的朋友已经有成功申请到公测资格,开始使用鸿蒙2。0系统啦,很可惜啊,老马自己的手机没有申请到。那么,鸿蒙是伪安卓吗?很多升级到了鸿蒙系统的
HTC手机告别中国大陆市场谦和之中见卓越。你还记得这句广告词么?它来自中国台湾手机厂商HTC,曾经的智能手机先驱者。12月13日,有消息称,HTC中国大陆官网已无手机可售。北京日报客户端记者14日登陆官网后中国邮政永远的神中国最赚钱的快递公司竟是他?你知道中国最赚钱的快递公司是哪家吗?没错,他就是中国邮政。据数据显示,中国邮政年收入高达280亿,在世界500强中排名74位,邮政行业全球第二!要知道,销量稳居全球第一,5G手机却在中国卖不动,三星在华大溃败文球子审核张子扬校正知秋12月11日,知名市场调研机构Canalys发布了2021年第三季度全球智能手机市场情况,其中三星依旧稳居全球第一,出货量达到了6940万台,抢下21的市场华为nova2好不好?入手没几天,发现最大的问题是屏幕反应迟缓,主要表现在玩游戏的时候。我玩了王者荣耀和穿越火线枪战王者两款游戏,发现搓屏时屏幕反应迟缓,基本没有办法正常操作,将游戏操作灵敏度调整到最高点击同意授权后,你的信息还安全吗?专家提醒这四种情况要注意安装或使用一款App时,常常会跳出一篇长的看不到头的文章密密麻麻的小字复杂难懂的条款,还有一个同意按钮等在最后,诱惑着你按下去。这些文章的名字常常是使用声明或是同意条款,它们代表着倡导智能向善,中国向联合国呼吁规范人工智能军事应用中国青年报客户端北京12月14日电(中青报中青网记者马子倩)人工智能是各国高度关注的新兴科技领域。当地时间12月13日,中国特命全权裁军事务大使李松率团出席在日内瓦召开的联合国特定中国非游戏厂商11月出海收入榜赤子城科技位列第4,两款应用稳居前20中国非游戏厂商11月出海收入榜赤子城科技位列第4,两款应用稳居前2012月14日,AppAnnie发布11月中国非游戏厂商及应用出海收入30强榜单,出海行业头部厂商及应用登榜。凭借盘中宝发展新能源汽车重要细分赛道,行业盈利拐点有望提速,较目前市场规模有56倍增长空间财联社资讯获悉,在全球碳中和背景下,充电基础设施建设尤其是发展公共充电桩,成为发展新能源汽车的重要细分赛道。近期,国家发展改革委工业和信息化部发布关于振作工业经济运行推动工业高质量京东七鲜扩张提速,未来57年力求跻身中国连锁零售行业第一阵营记者于浩经历一年沉寂之后,成立四年多的京东七鲜再次有了新消息。12月22日,京东旗下美食生鲜超市品牌七鲜对外披露了阶段性的业务发展成绩。据七鲜总裁郑锋介绍,七鲜超市截至目前在全国1生鲜电商渗透率不足15行业再掀融资潮本报记者李乔宇生鲜电商市场正重新热闹起来。日前,T11生鲜超市宣布完成一亿美元B轮融资,此轮融资由阿里巴巴领投,鸿为资本跟投,A轮独家领投方和玉资本(MSA)本轮继续加注。据介绍,炬光科技将登陆科创板助推行业大规模商业化应用中证网讯(王珞)12月24日,西安炬光科技股份有限公司将在上交所科创板挂牌上市,公司成功发行2249万股,发行价格为78。69元股,合计募资17。7亿元。炬光科技表示,募集资金在扣