中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

PHP MYSQL網(wǎng)站開發(fā)全程實(shí)百度搜索排行

PHP MYSQL網(wǎng)站開發(fā)全程實(shí),百度搜索排行,網(wǎng)站上線確認(rèn)書,做網(wǎng)站的怎么認(rèn)證微博文章目錄 1. 什么是LRU Cache2. LRU Cache的實(shí)現(xiàn)3. LRU Cache的OJ題目分析AC代碼 1. 什么是LRU Cache LRU是Least Recently Used的縮寫,意思是最近最少使用,它是一種Cache替換算法。 什么是Cache? 狹義的Cache指的是位于CPU和主存間的快速RAM…

文章目錄

  • 1. 什么是LRU Cache
  • 2. LRU Cache的實(shí)現(xiàn)
  • 3. LRU Cache的OJ
    • 題目分析
    • AC代碼

1. 什么是LRU Cache

LRU是Least Recently Used的縮寫,意思是最近最少使用,它是一種Cache替換算法。
什么是Cache?
狹義的Cache指的是位于CPU和主存間的快速RAM, 通常它不像系統(tǒng)主存那樣使用DRAM技術(shù),而使用昂貴但較快速的SRAM技術(shù)。 廣義上的Cache指的是位于速度相差較大的兩種硬件之間, 用于協(xié)調(diào)兩者數(shù)據(jù)傳輸速度差異的結(jié)構(gòu)。除了CPU與主存之間有Cache, 內(nèi)存與硬盤之間也有Cache,乃至在硬盤與網(wǎng)絡(luò)之間也有某種意義上的Cache── 稱為Internet臨時(shí)文件夾或網(wǎng)絡(luò)內(nèi)容緩存等。
在這里插入圖片描述
而Cache的容量有限,那如果cache滿了怎么辦?
當(dāng)Cache的容量用完后,而又有新的內(nèi)容需要添加進(jìn)來時(shí), 就需要挑選并舍棄原有的部分內(nèi)容,從而騰出空間來放新內(nèi)容。
那應(yīng)該選取那一部分的內(nèi)容和新內(nèi)容進(jìn)行替換呢?這就涉及到cache的替換算法,而LRU Cache就是cache替換算法中的一種!
LRU Cache 的替換原則就是將最近最少使用的內(nèi)容替換掉。其實(shí),LRU譯成最久未使用會(huì)更形象, 因?yàn)樵撍惴看翁鎿Q掉的就是一段時(shí)間內(nèi)最久沒有使用過的內(nèi)容。

2. LRU Cache的實(shí)現(xiàn)

那要實(shí)現(xiàn)一個(gè)LRU Cache其實(shí)并不難,方法和思路有很多;但是想要實(shí)現(xiàn)一個(gè)高效(所有操作都是O(1) )的LRU Cache是有難度的

實(shí)現(xiàn)LRU Cache的方法和思路很多,但是要保持高效實(shí)現(xiàn)O(1)的put和get,那么使用雙向鏈表和哈希表的搭配是最高效和經(jīng)典的。
使用雙向鏈表是因?yàn)殡p向鏈表可以實(shí)現(xiàn)任意位置O(1)的插入和刪除,使用哈希表是因?yàn)楣1淼脑鰟h查改也是O(1)。
在這里插入圖片描述

那具體到底應(yīng)該應(yīng)該怎么做呢?

下面我們借助LeetCode上的一道OJ來給大家進(jìn)行一個(gè)詳細(xì)的講解。

3. LRU Cache的OJ

題目鏈接: link

我們來看一下題目:
在這里插入圖片描述
在這里插入圖片描述
大家可以自己先看一下題目,我們看到題目中要求函數(shù) get 和 put 必須以 O(1) 的平均時(shí)間復(fù)雜度運(yùn)行。

那我們來分析一下要如何實(shí)現(xiàn)

題目分析

題目要求我們實(shí)現(xiàn)一個(gè)滿足 LRU (最近最少使用) 緩存 約束的數(shù)據(jù)結(jié)構(gòu)。
這個(gè) LRUCache 類的要求是這樣的:

在這里插入圖片描述

那我們要如何實(shí)現(xiàn)呢?

其實(shí)分析完題目我們很容易能想到用哈希表,那當(dāng)然C++里面我們就用unordered_map去搞,那這樣的話get函數(shù)(其實(shí)就是查找嘛)就能達(dá)到O(1);然后put呢,put也是要查找嘛,找到就更新,找不到就插入。那這樣就也是O(1)。
但是呢我們真正還要考慮還有——如果插入操作導(dǎo)致關(guān)鍵字?jǐn)?shù)量超過 capacity ,我們此時(shí)就要進(jìn)行LRU替換,則應(yīng)該 逐出 最久未使用的關(guān)鍵字。
那我們要如何實(shí)現(xiàn)LRU的替換呢?滿的話應(yīng)該逐出誰啊?如何找到最久未被使用的那個(gè)呢?

🆗,那上面也提到了,使用雙向鏈表和哈希表的搭配是最高效和經(jīng)典的:

在這里插入圖片描述
我們?cè)俑阋粋€(gè)list(list底層就是帶頭雙向循環(huán)鏈表),讓它里面也存儲(chǔ)數(shù)據(jù)(相當(dāng)于數(shù)據(jù)存儲(chǔ)兩份),然后我們可以默認(rèn)認(rèn)為尾部的那個(gè)元素就是最近最少用(最久未被使用)的(按頭部實(shí)現(xiàn)也可)。
然后如果有新插入的元素或者被訪問(get一個(gè)已有的值)的元素我就把它移到鏈表頭部。
這樣我們需要替換的時(shí)候,那么鏈表尾部的那個(gè)就是最久未被使用的那個(gè)。

但是呢?

在這里插入圖片描述
如果我們就這樣設(shè)計(jì)的話,還存在一個(gè)問題。
就是更新的時(shí)候其實(shí)復(fù)雜度是O(N)。
為什么呢?
更新的情況就是調(diào)用put先在哈希表里面查找到key是已存在的,那然后我們要修改,哈希表里面我找到這個(gè)就可以直接修改。
但是,在list里面我們是不是也要修改啊,因?yàn)槲覀兲鎿Q的時(shí)候找最久未被使用的那個(gè)值就是要從list里面找呢。
但是要修改list的話我們知不知道當(dāng)前要修改的這個(gè)元素是list里面的哪一個(gè)元素?
是不知道的,所以還得遍歷list去找。找到之后更新一下,然后把它移到頭部去,更新順序。
那這里遍歷查找的話不就是O(N)了嘛。

那這個(gè)問題我們?nèi)绾谓鉀Q一下呢?

如何做到在哈希表里面找到這個(gè)key之后,就直接能獲取到他在list中的位置,而不需要去遍歷查找呢?

那這里有一個(gè)非常巧的設(shè)計(jì)是這樣來解決的:

還是list和unordered_map搭配。
list里面呢還是存key-value的鍵值對(duì)pair。然后哈希表里面key還是要存的,但是不再像上面寫的那樣直接存key對(duì)應(yīng)的數(shù)據(jù)value,而是存這個(gè)key對(duì)應(yīng)的元素在list里面的對(duì)應(yīng)的迭代器。(那這樣真正的數(shù)據(jù)就只存在list里面)
在這里插入圖片描述
那這樣的話如果更新的話,首先我們?cè)诠1砝锩嬲业絢ey,然后通過它里面存的該元素在list中的迭代器,就可以直接修改list里面存放的數(shù)據(jù)。
然后再把它放到鏈表頭部(兩種方法,后面會(huì)提到)。
當(dāng)然list<pair<int,int>>::iterator這個(gè)類型比較長,我們也可以typedef一下
在這里插入圖片描述

那下面我們來嘗試寫一下代碼:

AC代碼

那首先我們應(yīng)該還要再增加一個(gè)成員變量:

即cache的容量capactity,因?yàn)橛袝r(shí)候我們還需要判斷cache滿不滿。
在這里插入圖片描述

然后我們來逐一實(shí)現(xiàn)一下它的3個(gè)成員函數(shù):

在這里插入圖片描述

首先是它的構(gòu)造函數(shù)LRUCache:

那這個(gè)很簡單,就是初始化一下capacity就行了。
剩下兩個(gè)成員變量是自定義類型,有默認(rèn)構(gòu)造。
在這里插入圖片描述

那然后是get函數(shù):

get呢也很簡單,就是通過key判斷在不在嘛。
如果在的話,就返回key對(duì)應(yīng)的值;如果不在,返回-1。
那我們就可以直接調(diào)用unordered_map的find函數(shù),根據(jù)find的返回結(jié)果判斷,如果找到了,我們要返回什么呢?
在這里插入圖片描述
🆗,首先這里的ret是啥啊,這里find返回的是迭代器,找到的話返回的就是key對(duì)應(yīng)的這個(gè)元素的迭代器。
那我們要返回這個(gè)key對(duì)應(yīng)的那個(gè)有效的值,那真正的數(shù)據(jù)是存在list里面的。
我們通過誰可以找到list里面存儲(chǔ)的這個(gè)key對(duì)應(yīng)的元素呢?
🆗,現(xiàn)在unordered_map里面的value存的是list里面這個(gè)key對(duì)應(yīng)元素的迭代器(有點(diǎn)繞了這里😂)。
在這里插入圖片描述
所以ret->second就是list里面這個(gè)元素的迭代器,但是我們想要拿到的是這個(gè)元素的key對(duì)應(yīng)的值,即ret->second->second,這里要取兩次second。
在這里插入圖片描述

🆗,那這樣就完了嘛?

還沒有。
如果get的時(shí)候成功找到了這個(gè)數(shù)據(jù),那相當(dāng)于訪問了它,那cache里面存儲(chǔ)數(shù)據(jù)的順序是不是就要調(diào)整了。是不是要把這個(gè)剛被訪問的元素放到鏈表頭部啊。

那如何在list里面調(diào)整這個(gè)順序呢?我們上面提到有兩種方式:

首先第一種方法我們可以先把這個(gè)元素刪除掉,然后在頭插到頭部。
但是這樣的話記得還要更新一下unordered_map里面存的對(duì)應(yīng)的那個(gè)迭代器,因?yàn)閯h完之后這個(gè)迭代器就失效了。之前的文章我們模擬實(shí)現(xiàn)過list,我們知道list的迭代器其實(shí)就是對(duì)結(jié)點(diǎn)指針的封裝嘛,這個(gè)結(jié)點(diǎn)刪除的話它這個(gè)結(jié)點(diǎn)指針指向的空間就釋放了。
所以這種方法好像有點(diǎn)麻煩。
那我就可以考慮用另外一種——直接調(diào)用list的splice 接口轉(zhuǎn)移結(jié)點(diǎn)。
那splice 這個(gè)函數(shù)其實(shí)我們之前也有提到過
在這里插入圖片描述
它可以把一個(gè)鏈表的一部分轉(zhuǎn)移到另一個(gè)鏈表(當(dāng)然也可以是同一個(gè)鏈表直接進(jìn)行轉(zhuǎn)移)
所以我們就可以直接調(diào)用splice將這個(gè)結(jié)點(diǎn)轉(zhuǎn)移到list的頭部。
在這里插入圖片描述

那最后就剩下put:

那put的話呢?zé)o非就兩種操作
如果關(guān)鍵字 key 已經(jīng)存在,則變更其數(shù)據(jù)值 value ;如果不存在,則向緩存中插入該組 key-value 。
當(dāng)然插入的時(shí)候需要判斷:
如果插入操作導(dǎo)致關(guān)鍵字?jǐn)?shù)量超過 capacity ,則應(yīng)該 逐出 最久未使用的關(guān)鍵字,然后插入新值。
另外不論是插入還是更新,都應(yīng)該把插入或更新的值放到鏈表頭部。

那我們來寫一下代碼:

在這里插入圖片描述
🆗,那到這里就完事了。

我們來提交一下:

在這里插入圖片描述
沒有問題!

完整代碼:

class LRUCache {
public:LRUCache(int capacity):_capacity(capacity){}int get(int key) {auto ret=_hashmap.find(key);if(ret!=_hashmap.end()){LtIter it=ret->second;//將it對(duì)應(yīng)的結(jié)點(diǎn)轉(zhuǎn)移到鏈表頭部_LRUList.splice(_LRUList.begin(),_LRUList,it);return it->second;}return -1;}void put(int key, int value) {auto ret=_hashmap.find(key);//如果找到,更新值if(ret!=_hashmap.end()){LtIter it=ret->second;it->second=value;//將it對(duì)應(yīng)的結(jié)點(diǎn)轉(zhuǎn)移到鏈表頭部_LRUList.splice(_LRUList.begin(),_LRUList,it);}else//找不到,插入{//如果滿了需要先刪除最久未使用的值if(_capacity==_hashmap.size()){pair<int,int> back=_LRUList.back();_hashmap.erase(back.first);_LRUList.pop_back();}//插入_LRUList.push_front(make_pair(key,value));_hashmap[key]=_LRUList.begin();}}
private:typedef list<pair<int,int>>::iterator LtIter;//hash做到查找更新/插入是O(1)unordered_map<int, LtIter> _hashmap;//LRU 默認(rèn)鏈表尾部的是最久未被使用的list<pair<int, int>> _LRUList;size_t _capacity;
};

那我們這篇文章就到這里…

http://m.risenshineclean.com/news/58325.html

相關(guān)文章:

  • 網(wǎng)站改版的步驟軟件開發(fā)公司網(wǎng)站
  • 優(yōu)秀創(chuàng)意網(wǎng)站湖北短視頻搜索seo
  • 國內(nèi)專業(yè)網(wǎng)站建設(shè)公司希愛力雙效片用后感受
  • 手機(jī)網(wǎng)站制作移動(dòng)高端網(wǎng)站建設(shè)廈門seo推廣公司
  • 手機(jī)h5網(wǎng)站小廣告網(wǎng)站
  • 上海免費(fèi)網(wǎng)站建設(shè)百度關(guān)鍵詞seo推廣
  • dede網(wǎng)站日志北京優(yōu)化網(wǎng)站推廣
  • 唐山營銷型網(wǎng)站制作東莞seo報(bào)價(jià)
  • 建設(shè)網(wǎng)站的運(yùn)行費(fèi)包括什么搜狗搜索引擎優(yōu)化指南
  • 杭州網(wǎng)站推廣找哪家鄭州百度推廣seo
  • 客服外包在哪個(gè)平臺(tái)接業(yè)務(wù)談?wù)勀銓?duì)seo概念的理解
  • 南京網(wǎng)站開發(fā)南京樂識(shí)好臺(tái)灣永久免費(fèi)加密一
  • 沈陽男科醫(yī)院排名最好的是哪家seo 優(yōu)化案例
  • 唐山疫情最新消息今天滿足seo需求的網(wǎng)站
  • 怎么做視頻在線播放網(wǎng)站手機(jī)百度極速版
  • 優(yōu)購物官方網(wǎng)站訂單查詢電商怎么推廣自己的產(chǎn)品
  • 采購網(wǎng)站大全寧波正規(guī)seo快速排名公司
  • 長沙哪些公司做網(wǎng)站地推放單平臺(tái)
  • 官方:杜絕網(wǎng)絡(luò)平臺(tái)發(fā)疫情財(cái)優(yōu)化二十條
  • 個(gè)體戶營業(yè)執(zhí)照科研做企業(yè)網(wǎng)站嗎域名注冊(cè)服務(wù)機(jī)構(gòu)
  • 廊坊做網(wǎng)站優(yōu)化百度賬號(hào)注冊(cè)
  • c 做交易網(wǎng)站谷歌外貿(mào)
  • 誰會(huì)在掏寶網(wǎng)上做網(wǎng)站seo查詢 站長之家
  • 網(wǎng)站怎么吸引人淄博網(wǎng)站推廣
  • 陜西省咸陽市建設(shè)銀行網(wǎng)站競價(jià)推廣托管服務(wù)
  • 為什么建設(shè)營銷型網(wǎng)站自媒體平臺(tái)app下載
  • 房管局網(wǎng)站建設(shè)方案泉州seo按天計(jì)費(fèi)
  • 阿里云的wordpress如何設(shè)置密碼百度搜索引擎優(yōu)化方案
  • 怎么做單頁網(wǎng)站導(dǎo)航怎么進(jìn)行推廣
  • wordpress清空緩存廣州seo推廣公司