初识Go语言24-数据结构与算法【链表、栈】

news2024/11/16 21:40:08

文章目录

  • 数据结构与算法
    • 链表


数据结构与算法

链表

在这里插入图片描述

---手写单链表
type Node struct {
	Info int
	Next *Node
}

type List struct {
	Head *Node
	Len  int
	Tail *Node
}

func (list *List) Add(ele int) {
	node := &Node{Info: ele, Next: nil}
	if list.Len == 0 {
		list.Head = node
		list.Tail = node //尾指针
	} else {
		// head:=list.Head
		// for i:=1;i<list.Len;i++{
		// 	head = head.Next
		// }
		list.Tail.Next = node
		list.Tail = node
	}
	list.Len += 1
}

func (list List) Travs() {
	if list.Len == 0 {
		return
	}
	head := list.Head
	fmt.Printf("%d ", head.Info)
	for i := 1; i < list.Len; i++ {
		head = head.Next
		fmt.Printf("%d ", head.Info)
	}
}

  链表的一个应用案例。LRU(Least Recently Used, 最近最少使用)缓存淘汰的总体思路:缓存的key放到链表中,头部的元素表示最近刚使用。

  • 如果命中缓存,从链表中找到对应的key,移到链表头部。

  • 如果没命中缓存:

    • 如果缓存容量没超,放入缓存,并把key放到链表头部。

    • 如果超出缓存容量,删除链表尾部元素,再把key放到链表头部。

    • 基于手写双链表粗略实现LRU算法

    ---基于双链表实现LRU算法(TODO:往链表中添加元素时的判断)
    type Node struct {
    	Info int
    	Next *Node
    	Prev *Node
    }
    
    type List struct {
    	Head *Node
    	Len  int
    	Tail *Node
    }
    
    func (list *List) Add(ele int) {
    	node := &Node{Info: ele, Next: nil, Prev: nil}
    	if list.Len == 0 {
    		list.Head = node
    		list.Tail = node //尾指针
    	} else {
    		list.Tail.Next = node
    		node.Prev = list.Tail
    		list.Tail = node
    	}
    	list.Len += 1
    }
    
    func (list List) Travs() {
    	if list.Len == 0 {
    		return
    	}
    	head := list.Head
    	fmt.Printf("%d ", head.Info)
    	for i := 1; i < list.Len; i++ {
    		head = head.Next
    		fmt.Printf("%d ", head.Info)
    	}
    	fmt.Println()
    }
    
    func (list *List) Visit(ele int) {
    	if list.Len == 0 {
    		return
    	}
    	head := list.Head
    	for {
    		if head == nil {
    			break
    		}
    		if head.Info != ele {
    			head = head.Next
    		} else {
    			break
    		}
    	}
    	if head == nil {
    		return
    	} else { // 1-->8-->7-->5  改为7-->1-->8-->5
    		post := head.Next //5
    		pre := head.Prev  //8
    
    		pre.Next = post //8-->5
    		post.Prev = pre //5-->8
    
    		head.Next = list.Head // 7-->1
    		list.Head.Prev = head // 1-->7
    		list.Head = head      //7成链表的头部
    	}
    }
    
    

go list的使用

type Element

type Element struct {
    // 元素保管的值
    Value interface{}
    // 内含隐藏或非导出字段
}

Element类型代表是双向链表的一个元素。


func (*Element) Next

func (e *Element) Next() *Element

Next返回链表的后一个元素或者nil。


func (*Element) Prev

func (e *Element) Prev() *Element

Prev返回链表的前一个元素或者nil。


type List

type List struct {
    // 内含隐藏或非导出字段
}

List代表一个双向链表。List零值为一个空的、可用的链表。


func New

func New() *List

New创建一个链表。


func (*List) Init

func (l *List) Init() *List

Init清空链表。


func (*List) Len

func (l *List) Len() int

Len返回链表中元素的个数,复杂度O(1)。


func (*List) Front

func (l *List) Front() *Element

Front返回链表第一个元素或nil。


func (*List) Back

func (l *List) Back() *Element

Back返回链表最后一个元素或nil。


func (*List) PushFront

func (l *List) PushFront(v interface{}) *Element

PushBack将一个值为v的新元素插入链表的第一个位置,返回生成的新元素。


func (*List) PushFrontList

func (l *List) PushFrontList(other *List)

PushFrontList创建链表other的拷贝,并将拷贝的最后一个位置连接到链表l的第一个位置。

func (*List) PushBack

func (l *List) PushBack(v interface{}) *Element

PushBack将一个值为v的新元素插入链表的最后一个位置,返回生成的新元素。


func (*List) PushBackList

func (l *List) PushBackList(other *List)

PushBack创建链表other的拷贝,并将链表l的最后一个位置连接到拷贝的第一个位置。


func (*List) InsertBefore

func (l *List) InsertBefore(v interface{}, mark *Element) *Element

InsertBefore将一个值为v的新元素插入到mark前面,并返回生成的新元素。如果mark不是l的元素,l不会被修改。


func (*List) InsertAfter

func (l *List) InsertAfter(v interface{}, mark *Element) *Element

InsertAfter将一个值为v的新元素插入到mark后面,并返回新生成的元素。如果mark不是l的元素,l不会被修改。


func (*List) MoveToFront

func (l *List) MoveToFront(e *Element)

MoveToFront将元素e移动到链表的第一个位置,如果e不是l的元素,l不会被修改。


func (*List) MoveToBack

func (l *List) MoveToBack(e *Element)

MoveToBack将元素e移动到链表的最后一个位置,如果e不是l的元素,l不会被修改。


func (*List) MoveBefore

func (l *List) MoveBefore(e, mark *Element)

MoveBefore将元素e移动到mark的前面。如果e或mark不是l的元素,或者e==mark,l不会被修改。


func (*List) MoveAfter

func (l *List) MoveAfter(e, mark *Element)

MoveAfter将元素e移动到mark的后面。如果e或mark不是l的元素,或者e==mark,l不会被修改。

func (*List) Remove

func (l *List) Remove(e *Element) interface{}

Remove删除链表中的元素e,并返回e.Value。

	lst := list.New() // 创建一个空的双向链表
	lst.PushBack(4)
	lst.PushBack(6)
	lst.PushBack(2)
	lst.PushFront(9)//往链表头部添加
	TravsList(lst)// 9 4 6 2

func TravsList(lst *list.List) {
	head := lst.Front()
	for head.Next() != nil {
		fmt.Printf("%v ", head.Value)
		head = head.Next()
	}
	fmt.Printf("%v \n", head.Value)
}

在这里插入图片描述

  ring的应用:基于滑动窗口的统计。比如最近100次接口调用的平均耗时、最近10笔订单的平均值、最近30个交易日股票的最高点。ring的容量即为滑动窗口的大小,把待观察变量按时间顺序不停地写入ring即可。

package main

import (
	"container/ring"
	"fmt"
)

func TraverseRing(ring *ring.Ring) {
	ring.Do(func(i interface{}) { //通过Do()来遍历ring,内部实际上调用了Next()而非Prev()
		fmt.Printf("%v ", i)
	})
	fmt.Println()
}

func main() {
	ring := ring.New(5) //必须指定长度,各元素被初始化为nil
	ring2 := ring.Prev()
	for i := 0; i < 3; i++ {
		ring.Value = i
		ring = ring.Next()
	}
	for i := 0; i < 3; i++ {
		ring2.Value = i
		ring2 = ring2.Prev()
	}
	TraverseRing(ring)
	TraverseRing(ring2) //ring和ring2当前所在的指针位置不同,所以遍历出来的顺序也不同
}

  栈是一种先进后出的数据结构,push把元素压入栈底,pop弹出栈顶的元素。编程语言的编译系统也用到了栈的思想。

在这里插入图片描述

  go自带的List已经包含了栈的功能,这里实现一个线程安全的栈。

type (
	node struct {
		value interface{}
		prev  *node
	}
	MyStack struct {
		top    *node
		length int
		lock   *sync.RWMutex
	}
)

func NewMyStack() *MyStack {
	return &MyStack{nil, 0, &sync.RWMutex{}}
}

func (stack *MyStack) Push(value interface{}) {
	stack.lock.Lock()
	defer stack.lock.Unlock()
	n := &node{value, stack.top}
	stack.top = n
	stack.length++
}

func (stack *MyStack) Pop() interface{} {
	stack.lock.Lock()
	defer stack.lock.Unlock()
	if stack.length == 0 {
		return nil
	}
	n := stack.top
	stack.top = n.prev
	stack.length--
	return n.value
}

func (stack *MyStack) Peak() interface{} {
	stack.lock.RLock()
	defer stack.lock.RUnlock()
	if stack.length == 0 {
		return nil
	}
	return stack.top.value
}

func (stack *MyStack) Len() int {
	return stack.length
}

func (stack *MyStack) Empty() bool {
	return stack.Len() == 0
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/700646.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于WebSocket的简易聊天室的基本实现梳理

一&#xff0c;前言 目前在很多网站为了实现推送技术所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔&#xff08;如每1秒&#xff09;&#xff0c;由浏览器对服务器发出HTTP请求&#xff0c;然后由服务器返回最新的数据给客户端的浏览器。HTTP 协议是一种无状态的、无连…

轨道交通车体自动化检修测量大尺寸测量仪器-CASAIM激光三维扫描仪

现今我国轨道交通高速发展&#xff0c;重大装备技术的进步离不开先进的大尺寸测量手段支持&#xff0c;CASAIM大尺寸测量在测量环境、测量精度和测量效率上明显区别于常规尺寸测量&#xff0c;可以快速检测车体表面的尺寸变形等问题&#xff0c;实现高精度、高效率的自动化车体…

(质数)牛客·Prime Distance

非质数的一个性质&#xff1a; 必定有一个因子大于它的算术平方根。 该性质有范围限制&#xff0c;一般情况下都可以使用。以后数学家们再扩张。碰到质数的一般做法&#xff1a;假定范围为[1,n] 1、预处理1-√n的质数&#xff0c;存入数组p中 2、对于[1-n]里的数&#xff0c;用…

git常用命令之Push

9. Push 命令作用延展阅读git push --set-upstream origin releasegit push -u origin release 为缩写版本1. .git/config配置文件会追加如下关联关系&#xff0c;[branch “release”] remote origin merge refs/heads/release故后续可以直接执行git push2. .git\refs\remo…

VueCli的Nuxt重构

我的博客用vuecli写的&#xff0c;SEO不忍直视。于是用Nuxt重构了代码&#xff0c;过程中踩了无数坑 一&#xff1a;body样式不生效 正常的body样式设置不能生效&#xff0c;需要在nuxt.config.js中配置 1、设置bodyAttrs的class属性&#xff0c;该属性值对应一个类名 2、该…

【Java面试题】Java基础——查找算法

文章目录 基本查找二分查找★★★插值查找斐波那契查找分块查找 基本查找 基本查找也叫做顺序查找 ​ 说明&#xff1a;顺序查找适合于存储结构为数组或者链表。 基本思想&#xff1a;顺序查找也称为线形查找&#xff0c;属于无序查找算法。从数据结构线的一端开始&#xff…

IP地址定位查询技术,不管对方在哪,轻轻松松查到他的位置

这是外面在卖588的抓ip技术&#xff0c;真的很简单&#xff0c;卖此技术的人帮人查一次都能赚几十&#xff0c;每天都能出个两三单 玩法&#xff1a;可以生成链接、邮件、图片、pdf的形式&#xff0c;发送给对方的微信或者QQ等地方&#xff0c;只要对方点击后&#xff0c;立马…

知易行难!项目推进的6大常见问题

项目推进是一项企业发展业务中的关键任务。然而&#xff0c;许多项目在实施过程中遇到各种困难和挑战&#xff0c;导致项目无法按计划进行或无法实现预期的成果。以下是项目推进过程中常见的六个问题以及解决方案。1、项目目标不明确 项目推进时&#xff0c;如果项目团队不清楚…

Material —— 材质节点 | Utility

目录 AddNamedRerouteDeclarationNode... AddRerouteNode... AntialiasedTextureMask AtmosphereSunLightIlluminanceOnGround AtmosphereSunLightVector BentNormalCustomOutput BlackBody BoxMask-2D BoxMask-3D BumpOffset&#xff08;B&#xff09; ChannelMask…

Spring Boot 中的 STOMP 是什么,原理,如何使用

Spring Boot 中的 STOMP 是什么&#xff0c;原理&#xff0c;如何使用 介绍 在 Spring Boot 中&#xff0c;STOMP 是一种简单的文本协议&#xff0c;用于在客户端和服务器之间进行实时消息传递。它是 WebSocket 协议的一种扩展&#xff0c;可以在 WebSocket 上运行。在本文中…

Electron + ts + vue3 + vite 项目搭建

新建一个vite ts vue3的项目 在创建选项中选择ts和vue选项。 之后&#xff0c;安装依赖之后试运行一下&#xff0c;出现一下页面意味着vite-vue项目创建成功。 npm create vitelatest electron-vue3-ts-vite-test1 VSCode打开electron-vue3-ts-vite-test1或者cd electron-…

vue项目运行后使用ip地址在手机上打开

文章目录 1、获取ip地址2、保证你的手机和电脑使用的是一个wifi3、修改配置文件 1、获取ip地址 windowr&#xff0c;输入cmd按回车后在输入ipconfig ipv4地址就是你了 2、保证你的手机和电脑使用的是一个wifi 3、修改配置文件 &#xff08;1&#xff09;vue.config.js文件中…

大数据时代,商业智能BI的使用规则

商业智能BI的火热程度让很多不了解的企业也在内部部署了BI系统&#xff0c;怎么利用BI创造价值也就成了新的问题。 商业智能面向管理人员 很多人其实不理解&#xff0c;为什么说企业的管理人员想要完全了解企业的各项业务发展情况实际上是很困难的。 一家企业有这么多部门&a…

【redis】stream消息队列

目录 截图一、代码示例1.1 pom.xml依赖1.2 application.xml配置1.3 启动类1.4 配置类1.5 消息实体1.6 自定义错误1.7 自定义注解1.8 服务类1.9 监听类1.10 controller 截图 一、代码示例 1.1 pom.xml依赖 <?xml version"1.0" encoding"UTF-8"?> …

Unity VR:XR Interaction Toolkit 官方 Demo

Unity XR Interaction Toolkit 提供了一个官方 Demo&#xff0c;包含了丰富的功能演示&#xff0c;可以供大家更好地学习 VR 开发。 项目地址&#xff1a;https://github.com/Unity-Technologies/XR-Interaction-Toolkit-Examples 项目里包括多个演示场景&#xff0c;而 XRI_…

Unity 中 TextMeshPro 字体位置偏上/偏下

问题&#xff1a;在Unity中创建了一个新的TextMeshPro 字体&#xff0c;在使用的时候布局设置的居中对齐&#xff0c;但在场景中实际位置却和预期位置不服&#xff0c;如下图。 当然通过调整布局设置&#xff0c;也可以显示成正常的效果&#xff0c;但不可能所有文本都通过这…

element栅格自定义等分

由于element栅格组件是 24 分栏&#xff0c;所以当我们需要5、7、9等分时&#xff0c;就不好实现 <template><el-row><el-col :span"24">1</el-col></el-row><el-row><el-col :span"12">2</el-col><e…

【Java可执行命令】(三)API文档生成工具javadoc: 深入解析Java API文档生成工具javadoc ~

Java可执行命令详解之javadoc 1️⃣ 概念2️⃣ 优势和缺点3️⃣ 使用3.1 语法格式3.1.1 可选参数&#xff1a;-d < directory>3.1.2 可选参数&#xff1a;-sourcepath < pathlist>3.1.3 可选参数&#xff1a;-classpath < pathlist>3.1.4 可选参数&#xff1…

JTAG 、 SWD 和 J-Link、ST-Link

JTAG和SWD的区别与联系JTAG接口SWD接口JTAG和SWD的区别与联系J-Link和ST-LinkJ-LINK仿真器STLINK仿真器JLINK和STLINK的比较与选择 JTAG和SWD的区别与联系 JTAG和SWD是两种常用的用于调试和编程ARM微控制器的接口&#xff0c;它们都可以通过调试器&#xff08;如ST-LINK或J-Li…

插入排序——希尔排序

希尔排序其实就是一种插入排序&#xff0c;实际上就是通过直接插入排序一步步改进优化而实现的。所以在了解希尔排序之前要明白插入排序的实现原理。 插入排序 其实我觉得插入排序也可以叫做摸牌排序&#xff0c;就是从第二张牌开始处理&#xff0c;将摸到的牌按照合适的顺序插…