数据结构与算法之LRU: 实现 LRU 缓存算法功能 (Ts, Py, Go版)

RK3588平台开发系列讲解(硬件篇-功能外设2) RK3588 芯片内置两个USB3.0 OTG控制器(内嵌2个USB2.0 OTG,下图绿色处),1个USB3.0 HOST 控制器,2个USB2.0 HOST控制器。这些控制器与PHY的内部复用图如下:USB3.0 OTG0 控制器支持SS/HS/FS/LS, 内嵌的USB2.0(HS/FS/LS)信号采用USB2.0 OTG PHY, 信号名见下图的红色方框内;RK3588目前仅此接口支持做Fireware的Download,应用中请务必要预留出。 阅读详情

关于LRU缓存

  • LRU - Lease Recently Used 最近使用
  • 如果内存优先,只缓存最近使用的,删除 ‘沉睡’ 数据
  • 核心 api: get set

Typescript 版算法实现


1 )方案1

  • 分析
    • 使用哈希表来实现, O(1)
    • 必须是有序的,常用放在前面,沉睡放在后面, 即:有序,可排序
    • 这样 {} 不符合要求;Map是可以排序的,按照设置顺序
class LRUCache {
    private length: number
    private data: Map<any, any> = new  Map()
  
    constructor(length: number) {
      if (length < 1) throw new Error('invalid length')
      this.length = length
    }
  
    set(key: any, value: any) {
      const data = this.data
      if (data.has(key)) {
        data.delete(key)
      }
      data.set(key, value)
      if (data.size > this.length) {
        // 如果超出了容量,则删除 Map 最老的元素
        const delKey = data.keys().next().value
        data.delete(delKey)
      }
    }
  
    get(key: any): any {
      const data = this.data
      if(!data.has(key)) return null
      const value = data.get(key)
      data.delete(key)
      data.set(key, value) // 保持最新的
      return value
    }
}

const lruCache = new LRUCache(2)

lruCache.set(1, 1) // { 1=1 }
lruCache.set(2, 2) // { 1=1,  2=2 }
console.log(lruCache.get(1))  // 1 {2=2, 1=1}

lruCache.set(3,3) // {1=1, 3=3}
console.log(lruCache.get(2))  // null

lruCache.set(4,4) // {3=3, 4=4}
console.log(lruCache.get(1))  // null

console.log(lruCache.get(3)) // 3 {4=4, 3=3}
console.log(lruCache.get(4)) // 4 {3=3, 4=4}

2 ) 方案2

  • 不用 Map 如何实现 LRU 缓存
  • 注意:有序
  • 结合 Object + Array
  • 将Array改造成双向链表
const obj1 = {value: 1, key: 'a'}
const obj2 = {value: 2, key: 'b'}
const obj3 = {value: 3, key: 'c'}

const data = [obj1, obj2, obj3]
const map =  {'a': obj1, 'b': obj2, 'c': obj3}

上述数据结构很精妙,如此,给出了下面的新方案

interface IListNode {
    value: any
    key: string
    prev?: IListNode
    next?: IListNode
  }
  
class LRUCache2 {
    private length: number
    private data: { [key: string]: IListNode } = {}
    private dataLength: number = 0
    private listHead: IListNode | null = null
    private listTail: IListNode | null = null
  
    constructor(length: number) {
      if (length < 1) throw new Error('invalid length')
        this.length = length
    }
  
    private moveToTail(curNode: IListNode) {
      const tail = this.listTail
      if (tail === curNode) return
      // 1. 让 pre next 断绝与 curNode的关系
      const preNode = curNode.prev
      const nextNode = curNode.next
      if (preNode) {
        if (nextNode) {
          preNode.next = nextNode
        } else {
          delete preNode.next
        }
      }
      if (nextNode) {
        if (preNode) {
          nextNode.prev = preNode
        } else {
          delete nextNode.prev
        }
        if (this.listHead === curNode) this.listHead = nextNode
      }
  
      // 2. 让 curNode 断绝与 prev, next的关系
      delete curNode.prev
      delete curNode.next
      // 3. 在list 末尾重新建立 curNode 的新关系
      if (tail) {
        tail.next = curNode
        curNode.prev = tail
      }
      this.listTail = curNode
    }
  
    private tryClean() {
      while(this.dataLength > this.length) {
        const head = this.listHead
        if (!head) throw new Error('head is null')
        const headNext = head.next
        if (!headNext) throw new Error('headNext is null')
        // 1. 断绝head和next的关系
        delete headNext.prev
        delete head.next
        // 2. 重新赋值 listHead
        this.listHead = headNext
        // 3. 清理 data, 重新计数
        delete this.data[head.key]
        this.dataLength -= 1
      }
    }
  
    get(key: string):any {
      const data = this.data
      const curNode  = data[key]
      if (!curNode) return null
      if (this.listTail === curNode) {
        return curNode.value
      }
      // curNode 移动到末尾
      this.moveToTail(curNode)
      return curNode.value
    }
    set(key: string, value: any) {
      const data = this.data
      const curNode  = data[key]
      if (!curNode) {
        // 新增数据
        const newNode: IListNode = {key, value}
        // 移动到末尾
        this.moveToTail(newNode)
        data[key] = newNode
        this.dataLength ++
        if (this.dataLength === 1) this.listHead = newNode
      } else {
        // 修改现有数据
        curNode.value = value
        // 移动到末尾
        this.moveToTail(curNode)
      }
      // 长度超过了,则需要清理
      this.tryClean()
    }
}

const lc = new LRUCache2(2)
lc.set('1', 1) // { 1=1 }
lc.set('2', 2) // { 1=1,  2=2 }
console.log(lc.get('1'))  // 1 {2=2, 1=1} 真实结构比这个复杂,下同

lc.set('3',3) // {1=1, 3=3}
console.log(lc.get('2'))  // null

lc.set('4',4) // {3=3, 4=4}
console.log(lc.get('1'))  // null
console.log(lc.get('3'))  // 3 {4=4, 3=3}

console.log(lc.get('4'))  // 4 {3=3, 4=4}
  • 数据结构设计:data 和 list 分别存储什么
  • 双向链表的操作非常繁琐,代码很容易写错, 不易调试
  • 链表 node 要存储 node.key, 否则需要遍历 data 删除

Python3 版算法实现


1 )方案1

class LRUCache:
    def __init__(self, length):
        if length < 1:
            raise ValueError('Invalid length')
        self.length = length
        self.data = {}
        self.order = []

    def set(self, key, value):
        if key in self.data:
            self.order.remove(key)
        elif len(self.data) >= self.length:
            # 如果超出了容量,则删除最老的元素
            oldest_key = self.order.pop(0)
            del self.data[oldest_key]
        self.data[key] = value
        self.order.append(key)

    def get(self, key):
        if key not in self.data:
            return None
        # 保持最新的
        self.order.remove(key)
        self.order.append(key)
        return self.data[key]

# 测试用例
lru_cache = LRUCache(2)

lru_cache.set(1, 1)  # { 1=1 }
lru_cache.set(2, 2)  # { 1=1,  2=2 }
print(lru_cache.get(1))  # 1 {2=2, 1=1}

lru_cache.set(3, 3)  # {1=1, 3=3}
print(lru_cache.get(2))  # None

lru_cache.set(4, 4)  # {3=3, 4=4}
print(lru_cache.get(1))  # None

print(lru_cache.get(3))  # 3 {4=4, 3=3}
print(lru_cache.get(4))  # 4 {3=3, 4=4}

2 )方案2


class ListNode:
    def __init__(self, key, value):
        self.key = key
        self.value = value
        self.prev = None
        self.next = None

class LRUCache2:
    def __init__(self, length):
        if length < 1:
            raise ValueError('Invalid length')
        self.length = length
        self.data = {}
        self.data_length = 0
        self.list_head = None
        self.list_tail = None

    def move_to_tail(self, cur_node):
        tail = self.list_tail
        if tail == cur_node:
            return
        # 1. 让 pre next 断绝与 curNode的关系
        pre_node = cur_node.prev
        next_node = cur_node.next
        if pre_node:
            if next_node:
                pre_node.next = next_node
            else:
                pre_node.next = None
        if next_node:
            if pre_node:
                next_node.prev = pre_node
            else:
                next_node.prev = None
            if self.list_head == cur_node:
                self.list_head = next_node

        # 2. 让 curNode 断绝与 prev, next的关系
        cur_node.prev = None
        cur_node.next = None
        # 3. 在list 末尾重新建立 curNode 的新关系
        if tail:
            tail.next = cur_node
            cur_node.prev = tail
        self.list_tail = cur_node

    def try_clean(self):
        while self.data_length > self.length:
            head = self.list_head
            if not head:
                raise ValueError('Head is null')
            head_next = head.next
            if not head_next:
                raise ValueError('HeadNext is null')
            # 1. 断绝head和next的关系
            head_next.prev = None
            head.next = None
            # 2. 重新赋值 listHead
            self.list_head = head_next
            # 3. 清理 data, 重新计数
            del self.data[head.key]
            self.data_length -= 1

    def get(self, key):
        cur_node = self.data.get(key)
        if not cur_node:
            return None
        if self.list_tail == cur_node:
            return cur_node.value
        # curNode 移动到末尾
        self.move_to_tail(cur_node)
        return cur_node.value

    def set(self, key, value):
        cur_node = self.data.get(key)
        if not cur_node:
            # 新增数据
            new_node = ListNode(key, value)
            # 移动到末尾
            self.move_to_tail(new_node)
            self.data[key] = new_node
            self.data_length += 1
            if self.data_length == 1:
                self.list_head = new_node
        else:
            # 修改现有数据
            cur_node.value = value
            # 移动到末尾
            self.move_to_tail(cur_node)
        # 长度超过了,则需要清理
        self.try_clean()

# 测试用例
lc = LRUCache2(2)
lc.set('1', 1)  # { 1=1 }
lc.set('2', 2)  # { 1=1,  2=2 }
print(lc.get('1'))  # 1 {2=2, 1=1}

lc.set('3', 3)  # {1=1, 3=3}
print(lc.get('2'))  # null

lc.set('4', 4)  # {3=3, 4=4}
print(lc.get('1'))  # null
print(lc.get('3'))  # 3 {4=4, 3=3}

print(lc.get('4'))  # 4 {3=3, 4=4}

Golang 版算法实现


1 )方案1

package main

import (
	"errors"
	"fmt"
)

type LRUCache struct {
	length int
	data   map[interface{}]interface{}
	order  []interface{}
}

func NewLRUCache(length int) (*LRUCache, error) {
	if length < 1 {
		return nil, errors.New("invalid length")
	}
	return &LRUCache{
		length: length,
		data:   make(map[interface{}]interface{}),
		order:  make([]interface{}, 0),
	}, nil
}

func (cache *LRUCache) Set(key interface{}, value interface{}) {
	if _, exists := cache.data[key]; exists {
		// 如果键已存在,先从 order 中移除该键
		for i, k := range cache.order {
			if k == key {
				cache.order = append(cache.order[:i], cache.order[i+1:]...)
				break
			}
		}
	} else if len(cache.data) >= cache.length {
		// 如果超出了容量,则删除最老的元素
		oldestKey := cache.order[0]
		delete(cache.data, oldestKey)
		cache.order = cache.order[1:]
	}
	cache.data[key] = value
	cache.order = append(cache.order, key)
}

func (cache *LRUCache) Get(key interface{}) interface{} {
	value, exists := cache.data[key]
	if !exists {
		return nil
	}
	// 保持最新的
	for i, k := range cache.order {
		if k == key {
			cache.order = append(cache.order[:i], cache.order[i+1:]...)
			break
		}
	}
	cache.order = append(cache.order, key)
	return value
}

func main() {
	lruCache, _ := NewLRUCache(2)

	lruCache.Set(1, 1)           // { 1=1 }
	lruCache.Set(2, 2)           // { 1=1,  2=2 }
	fmt.Println(lruCache.Get(1)) // 1 {2=2, 1=1}

	lruCache.Set(3, 3)           // {1=1, 3=3}
	fmt.Println(lruCache.Get(2)) // null

	lruCache.Set(4, 4)           // {3=3, 4=4}
	fmt.Println(lruCache.Get(1)) // null

	fmt.Println(lruCache.Get(3)) // 3 {4=4, 3=3}
	fmt.Println(lruCache.Get(4)) // 4 {3=3, 4=4}
}

2 )方案2

package main

import (
	"errors"
	"fmt"
)

type ListNode struct {
	key, value interface{}
	prev, next *ListNode
}

type LRUCache2 struct {
	length             int
	data               map[string]*ListNode
	dataLength         int
	listHead, listTail *ListNode
}

func NewLRUCache2(length int) (*LRUCache2, error) {
	if length < 1 {
		return nil, errors.New("invalid length")
	}
	return &LRUCache2{
		length: length,
		data:   make(map[string]*ListNode),
	}, nil
}

func (cache *LRUCache2) moveToTail(curNode *ListNode) {
	tail := cache.listTail
	if tail == curNode {
		return
	}
	// 1. 让 pre next 断绝与 curNode的关系
	preNode := curNode.prev
	nextNode := curNode.next
	if preNode != nil {
		if nextNode != nil {
			preNode.next = nextNode
		} else {
			preNode.next = nil
		}
	}
	if nextNode != nil {
		if preNode != nil {
			nextNode.prev = preNode
		} else {
			nextNode.prev = nil
		}
		if cache.listHead == curNode {
			cache.listHead = nextNode
		}
	}

	// 2. 让 curNode 断绝与 prev, next的关系
	curNode.prev = nil
	curNode.next = nil
	// 3. 在list 末尾重新建立 curNode 的新关系
	if tail != nil {
		tail.next = curNode
		curNode.prev = tail
	}
	cache.listTail = curNode
}

func (cache *LRUCache2) tryClean() {
	for cache.dataLength > cache.length {
		head := cache.listHead
		if head == nil {
			panic("head is null")
		}
		headNext := head.next
		if headNext == nil {
			panic("headNext is null")
		}
		// 1. 断绝head和next的关系
		headNext.prev = nil
		head.next = nil
		// 2. 重新赋值 listHead
		cache.listHead = headNext
		// 3. 清理 data, 重新计数
		delete(cache.data, head.key.(string))
		cache.dataLength--
	}
}

func (cache *LRUCache2) Get(key string) interface{} {
	curNode, exists := cache.data[key]
	if !exists {
		return nil
	}
	if cache.listTail == curNode {
		return curNode.value
	}
	// curNode 移动到末尾
	cache.moveToTail(curNode)
	return curNode.value
}

func (cache *LRUCache2) Set(key string, value interface{}) {
	curNode, exists := cache.data[key]
	if !exists {
		// 新增数据
		newNode := &ListNode{key: key, value: value}
		// 移动到末尾
		cache.moveToTail(newNode)
		cache.data[key] = newNode
		cache.dataLength++
		if cache.dataLength == 1 {
			cache.listHead = newNode
		}
	} else {
		// 修改现有数据
		curNode.value = value
		// 移动到末尾
		cache.moveToTail(curNode)
	}
	// 长度超过了,则需要清理
	cache.tryClean()
}

func main() {
	lc, _ := NewLRUCache2(2)
	lc.Set("1", 1)           // { 1=1 }
	lc.Set("2", 2)           // { 1=1,  2=2 }
	fmt.Println(lc.Get("1")) // 1 {2=2, 1=1}

	lc.Set("3", 3)           // {1=1, 3=3}
	fmt.Println(lc.Get("2")) // null

	lc.Set("4", 4)           // {3=3, 4=4}
	fmt.Println(lc.Get("1")) // null
	fmt.Println(lc.Get("3")) // 3 {4=4, 3=3}

	fmt.Println(lc.Get("4")) // 4 {3=3, 4=4}
}
1.为什么要学习MATLAB 学习MATLAB 阅读详情

相关推荐

Python自动化:3分钟搞定微信收藏链接批量导出到TXT(附完整代码)

本文介绍如何使用Python自动化工具在3分钟内将微信收藏链接批量导出到TXT文件。通过模拟人类操作和OCR技术,脚本高效处理大量链接,显著提升工作效率,并附有完整代码和实战避坑指南。

weixin_29062671的博客 631

前端也来点算法(TS版) | 1 - LRU Cache

这是 前端也来点算法 系列的第一篇文章,项目中的代码打算全部用 TS 编写。这篇文章会涉及到的技术有:双向链表哈希表(JS 中叫对象)What:缓存是一种提高数据读取性能...

止水聊技术 540

Python实战:用MOOTDX库轻松抓取股票分时数据并绘制专业图表(附完整代码)

本文详细介绍了如何使用Python的MOOTDX库获取股票分时数据,并通过Pandas进行数据清洗与VWAP计算,最后利用Matplotlib绘制包含价格线、均线和成交量的专业分时图。文章提供了从环境搭建、数据获取到可视化呈现的完整代码,帮助读者快速构建本地化的股票分时数据分析工具。

weixin_29041195的博客 477

[TypeScript]手撸LRU

[TypeScript]手撸LRU

SCUhzs 720

STM32 BootLoader 入门教程:从原理到 APP 跳转实现

在 STM32 项目开发中,BootLoader 通常用于实现固件升级、程序引导和应用程序校验。本文从最基础的 BootLoader 原理开始,讲解 STM32 内部 Flash 分区设计、APP 地址偏移、向量表重定位、BootLoader 跳转 APP 的核心代码,以及实际开发中常见的问题。本文适合刚开始接触 STM32 BootLoader、IAP 在线升级、串口升级、OTA 升级的开发者阅读。

lidecong133的博客 1678

【学习笔记】《基于φ-OTDR的分布式扰动传感系统定位算法研究-北交-通信与信息系统-吴》重点笔记

一、绪论 1.1 引言 光纤传感器的优点:跟电子传感器相比较,光纤传感器有诸多独特的优势:对电磁干扰免疫;具有很好的绝缘性和耐腐蚀性;灵敏度高,可测量微弱信息;可实现大范围监测和分布式传感,仅需一根传感光纤,更为经济便捷;传感光纤体积小、重量轻、可形变,适用于一些特殊应用场所;还有无需供电、耐高温、便于组网等等优点 光纤传感器的感知信号的方法:当探测光入射到光纤中时会发生散射并产生各种散射光...

qq_36045093的博客 2万+

ts版LRU

interface Node { k: number; v: number ; prev: Node | undefined; next: Node | undefined; } class DoubleLink { head: Node tail: Node constructor() { this.head = this.buildNode(-1, -1); this.tail = this.buildNode(-

JUNSON009的博客 280

基于单片机控制的开关电源设计

采用开关电源技术和MCU模块,凭借可靠性高、易于调适的特点,可以更高效地发挥出二者的优势,从而实现更好的组合。stm32的起动模式是通过Boot0和Boot1两个管脚的高低电平来决定的,当stm32被供电之后,这两个管脚的电平。在 VCC上,键盘的一头(列线)被连接到 VCC上,而在“0”的编程输出中,则用来进。,在开关管打开的情况下,由输入电力供给电流,感应装置存储   Buck变换器是一种非隔离式的电压转换器[10]整流电路对输入电压进行整流,再经过滤波电路,即Dc电压是直流/直流变换器的直流输入。

QQ1694456187的博客 2313

react TS实现缓存类(复用)

【代码】react TS实现缓存类(复用)

m0_46365130的博客 221

计算机视觉(角点检测)- 1 - Harris角点检测

计算机视觉(角点检测)-1.1 Harris角点检测学习前言 学习前言   今天更新一下计算机视觉的东西吧,哈哈哈o( ̄︶ ̄)o   关于角点检测呢,就是检测图像中角点的算法,常见的有四种常见的算法:Moravec角点检测算法、 Harris角点检测算法、Shi-Tomasi 算法、FAST角点检测算法,不过常用的就两种吧——Harris角点检测算法、Shi-Tomasi 算法(反正我基本上就只用到这两种,先着重介绍前面两种,后面再花世界介绍吧)(~ ̄▽ ̄)~ ...

qq_40374812的博客 1万+

【异常】Claude Code 在 Windows CMD 中出现重影现象的排查与解决

Windows CMD运行Claude Code时出现文字重影、乱码等问题,原因是传统CMD对现代ANSI终端控制序列支持不足。解决方案包括:1)推荐安装Windows Terminal(完全支持ANSI标准);2)使用PowerShell 7;3)优化CMD设置(启用虚拟终端、UTF-8编码);4)关闭Claude Code视觉特效。建议优先使用Windows Terminal以获得最佳体验,这是最彻底的解决方案。其他方案仅能部分改善或缓解问题。

奶爸的编程之路,也就一周冷个三天 1964

LRU(末位淘汰)算法

/** * @Author: subd * @Date: 2019/8/28 8:22 * LRU * 末尾淘汰算法 线程不安全 * 手写linkedHashMap 进行书写 */ public class LRU { private Node head; private Node end; //缓存上限设置 private int limit; ...

csdn_subaodong的博客 747

对halcon形状匹配算法的一点分析

基于Intel VTune Profiler对halcon形状匹配算法的一点分析

manuoo的专栏 568

黑群晖 RR引导 完整教程:5步完成安装引导盘并学会自救

RR引导(Redpill Recovery)就是一张能装系统也能救场的引导盘:写进 U 盘,任意 x86/x64 机器即可安装黑群晖 DSM,装砸了同一张盘还能进恢复环境找回数据。本文适合准备自建 NAS 的新手,当前版本 26.7.4,按下面 5 个步骤走即可。 ## 🧩 ① 下载镜像前,先做 4 项硬件自查 大部分安装失败源于硬件不达标,对照下表逐项打勾再动手: | 检查项 | 要求

gitblog_00052的博客 1086

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

猫抓 Cat-Catch 资源嗅探扩展拆解:一条 M3U8 从被拦截到落盘要闯几道关

猫抓 Cat-Catch(cat-catch)是一个浏览器资源嗅探扩展,当前版本 2.7.4:它在后台监听页面全部网络请求,把视频、音频等媒体资源列进侧边栏,再用注入脚本捞回 blob、WebRTC 这类"隐身"流,并把 M3U8/MPD 的解析、切片下载、合并转码做完。本文不按功能清单讲,而是按它实际要解决的四个问题拆:抓不到的资源怎么补、被拦下的请求怎么落库、后台进程被杀怎么续命、并发下载怎么

gitblog_01039的博客 342

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

AiSOC 故障排查实战:从 doctor 健康检查到 Kafka 滞后与 Agent 静默的分层诊断手册

本篇基于 AiSOC 官方运维文档 [troubleshooting.md](https://link.gitcode.com/i/9514b55b2240a80fc3c70febb75df921) 展开,覆盖这套开源 AI 安全运营中心最常见的故障类别:服务连不上依赖、凭据错误、Kafka 队列卡死、LLM 提供商不可达。读完本文,你将掌握一套按"症状 → 子系统 → 日志位置 → 恢复动作"组

gitblog_00284的博客 157

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Hello 算法:链表数据结构深度解析 —— 节点结构、基本操作与多语言实现

本篇技术指南以《Hello 算法》(hello-algo)俄语版教程中的"链表"章节为主体,系统讲解链表为何能突破数组"连续内存"的局限、链表节点(`ListNode`)在十余种语言中的定义方式,以及初始化、插入、删除、访问、查找这五项基本操作的实现逻辑与时间复杂度。结合仓库中 [Python](https://link.gitcode.com/i/acd77a7fe46f4360e15d0730

gitblog_00483的博客 496

happy-app 移动端 Diff 语法高亮架构:Worklets 专用运行时、首屏门控与 LRU 缓存的工程实践

本文详解 happy-app(Codex 与 Claude Code 的移动/Web 客户端)中 diff 视图语法高亮的完整架构:**同步 diff 构建器始终保持语法关闭**,由挂载后的组件按可见完整 hunk 异步请求着色,在"语法就绪或 1 秒超时"之前用精确预留的布局隐藏代码本体,从而兼顾首屏速度、滚动流畅度与辅助功能安全。读完本文,你将掌握其首屏揭示门控(first-reveal ga

gitblog_00863的博客 666

大模型AI测评:GPT-4与Claude 3.5代码生成实测横评

文章摘要: 通过对GPT-4与Claude 3.5的代码生成能力横评发现,Claude 3.5在工程细节(如边界检查、错误处理)和代码直接可用性上更优,适合快速产出生产级代码;GPT-4则擅长算法讲解和跨语言转换,提供更多原理分析与优化建议。测试基于国内可直连的聚合平台KULAAI完成,该平台免费集成多款顶级模型,支持文件上传与联网搜索,响应稳定(Claude 3.5平均生成耗时8秒,略快于GPT-4的9.2秒)。开发者可根据需求选择:“执行型”任务用Claude 3.5,“学习型”需求选GPT-4,或通过

小龙报的博客 2540

如何快速理解数据结构基础:Hello 算法中数组、链表与哈希表的源码逐行图解

还在为枯燥的公式和干巴巴的定义头疼吗?开源教程《Hello 算法》用**动画图解 + 一键运行的多语言源码**(支持 Python、Java、C++、Go、Rust 等 14 种语言),把数据结构与算法讲成了"看图学做菜"。本文带你逐行读懂它最核心的三件数据结构基础——**数组、链表、哈希表**,30 分钟建立清晰的心智模型。 [![Hello 算法中数组与链表的动画图解](https://ra

gitblog_00254的博客 490

Redis六大实战特性全解析:消息订阅、Pipeline、布隆过滤器与LRU

在互联网高并发架构中,Redis早已不是简单的缓存读写工具,而是承载系统稳定性的关键中间件。很多团队在使用Redis时只停留在SET/GET层面,一旦遇到缓存穿透、批量写入性能低下、内存溢出等问题便手足无措。其实,消息订阅、Pipeline、事务与Lua脚本、模块机制、布隆过滤器、LRU淘汰策略这六大特性,正是应对工程难题的利器。理解它们各自解决的原理问题,掌握生产环境中的落地方案与隐藏坑点,才能让Redis发挥真正价值。本文从缓存系统的核心痛点切入,结合具体命令与代码示例,逐一拆解这些被低估的Redis能

weixin_34116110的博客 226

50个必知必会算法实战指南:多语言实现深度解析

Algo项目是一个专注于数据结构和算法实践的开源库,提供了50个核心算法的多语言实现方案。这个项目由前Google工程师创建,旨在帮助开发者通过实际代码掌握算法精髓,提升编程面试和工程实践能力。项目覆盖从基础数据结构到高级算法的完整知识体系,支持C/C++、Java、Python、Go、JavaScript、TypeScript、Rust、Scala、Swift、Kotlin、PHP、Object

gitblog_00311的博客 498

OpCore-Simplify:1 份硬件报告自动构建 OpenCore EFI

装黑苹果最耗时的环节是手写 config.plist:对照硬件逐个挑 Kext、补 ACPI 表、核对 macOS 版本支持。OpCore-Simplify 是黑苹果 OpenCore EFI 自动构建工具,把"导入 Report.json → 选版本 → 构建"压成三个动作。它内置 78 个 Intel CPU 代号与 31 个 AMD 代号数据表,覆盖 High Sierra 10.13 到

gitblog_01167的博客 411

Feather:iOS 免越狱设备端本地签名安装完整指南

Feather 是一款免费、完全在设备端工作的 iOS/iPadOS 应用管理器:它用 Zsign 在你自己的 iPhone 上完成本地签名,再通过本地服务器 + itms-services 或设备配对通道把第三方应用装进系统,全程不需要电脑,也没有任何跟踪代码。它适合手里有 Apple Developer 证书(.p12 + .mobileprovision)、要侧载内部测试包或非 App St

gitblog_00451的博客 167

对象存储Byte-Range缓存设计:原理、实现与生产实践

在对象存储访问中,HTTP Range请求允许客户端只读取大对象的指定字节区间,是流媒体播放、模型权重加载和数据备份等场景的基础能力。然而,每次Range请求都直接回源对象存储,会带来跨地域延迟、请求计费和出流量成本。Byte-range缓存按固定chunk粒度缓存对象的部分字节,将重复读取的请求拦截在本地,显著降低回源次数和访问延迟。本文从Range语义出发,解析206 Partial Content的边界处理难点,讲解缓存的分块设计、元数据组织、并发控制与原子写,并给出一套最小可运行的Python实现与

weixin_34194359的博客 426

Subtitle Edit 5:从零同步到批量转换的开源字幕编辑完整方案

Subtitle Edit 5 是一款免费开源的视频字幕编辑器,支持读写 380+ 种字幕格式,运行在 Windows、Linux 和 macOS 三大平台。内置可视化同步、语音识别、OCR 与批量转换,覆盖"没有字幕"到"多语言交付"的完整流程;命令行工具 seconv 与界面共用同一套核心库,所有操作都能脚本化。 ## 项目速览 核心能力集中在 8 个方面: 1. 格式转换:读写 Sub

gitblog_00326的博客 166
上一篇: 数据结构与算法之排序: 堆排序 (Ts, Py, Go版)
下一篇: 前端小技巧: TS实现数组转树,树转数组
Wang's Blog
博客等级 码龄12年 7438粉丝 2422原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值