Kas yra LRU talpykla?
Talpyklos keitimo algoritmai yra efektyviai sukurti taip, kad pakeistų talpyklą, kai vieta pilna. The Neseniai naudotas (LRU) yra vienas iš tų algoritmų. Kaip rodo pavadinimas, kai talpyklos atmintis yra pilna, LRU parenka duomenis, kurie buvo neseniai naudojami, ir pašalina juos, kad būtų vietos naujiems duomenims. Duomenų prioritetas talpykloje keičiasi atsižvelgiant į tų duomenų poreikį, t. y. jei kai kurie duomenys būtų paimti arba atnaujinti neseniai, tų duomenų prioritetas būtų pakeistas ir priskiriamas aukščiausiam prioritetui, o duomenų prioritetas mažėja, jei lieka nepanaudotos operacijos po operacijų.
Turinys
- Kas yra LRU talpykla?
- Operacijos LRU talpykloje:
- LRU talpyklos veikimas:
- LRU talpyklos diegimo būdai:
- LRU talpyklos diegimas naudojant eilę ir maišą:
- LRU talpyklos diegimas naudojant dvigubai susietą sąrašą ir maišą:
- LRU talpyklos diegimas naudojant Deque & Hashmap:
- LRU talpyklos diegimas naudojant Stack & Hashmap:
- LRU talpykla naudojant Counter Implementation:
- LRU talpyklos diegimas naudojant „Lazy Updates“:
- LRU talpyklos sudėtingumo analizė:
- LRU talpyklos privalumai:
- LRU talpyklos trūkumai:
- Realus LRU talpyklos taikymas:
LRU algoritmas yra standartinė problema ir jis gali keistis pagal poreikį, pavyzdžiui, operacinėse sistemose LRU vaidina lemiamą vaidmenį, nes gali būti naudojamas kaip puslapio pakeitimo algoritmas, siekiant sumažinti puslapio gedimus.
Operacijos LRU talpykloje:
- LRUCache (c talpa): Inicijuoti LRU talpyklą su teigiamo dydžio talpa c.
- gauti (raktą) : grąžina rakto reikšmę k' jei jis yra talpykloje, kitu atveju jis grąžina -1. Taip pat atnaujinamas LRU talpykloje esančių duomenų prioritetas.
- įdėti (raktas, vertė): Atnaujinkite rakto reikšmę, jei toks raktas yra, Kitu atveju pridėkite rakto ir vertės porą prie talpyklos. Jei raktų skaičius viršijo LRU talpyklos talpą, atmeskite neseniai naudotą raktą.
LRU talpyklos veikimas:
Tarkime, kad turime 3 talpos LRU talpyklą ir norėtume atlikti šias operacijas:
- Įdėkite (key=1, value=A) į talpyklą
- Įdėkite (raktas = 2, vertė = B) į talpyklą
- Įdėkite (key=3, value=C) į talpyklą
- Gaukite (key=2) iš talpyklos
- Gaukite (key=4) iš talpyklos
- Įdėkite (key=4, value=D) į talpyklą
- Įdėkite (key=3, value=E) į talpyklą
- Gaukite (key=4) iš talpyklos
- Įdėkite (key=1, value=A) į talpyklą
Aukščiau nurodytos operacijos atliekamos viena po kitos, kaip parodyta paveikslėlyje žemiau:

Išsamus kiekvienos operacijos paaiškinimas:
- Įdėti (1 raktas, vertė A) : Kadangi LRU talpyklos talpa yra tuščia = 3, nereikia keisti ir mes įdedame {1 : A} viršuje, t. y. {1 : A} turi aukščiausią prioritetą.
- Įdėkite (2 raktas, B vertė) : Kadangi LRU talpyklos talpa tuščia = 2, vėl nereikia keisti, bet dabar {2 : B} turi aukščiausią prioritetą, o prioritetas {1 : A} sumažėja.
- Įdėti (3 raktas, vertė C) : Vis dar yra 1 laisva vieta talpykloje, todėl įdėkite {3 : C} be jokių pakeitimų, pastebėkite, kad dabar talpykla pilna ir dabartinė prioritetų tvarka nuo aukščiausio iki mažiausio yra {3:C}, {2:B }, {1:A}.
- Gaukite (2 raktas) : Dabar šios operacijos metu grąžinkite rakto = 2 reikšmę, taip pat kadangi naudojamas raktas = 2, dabar nauja prioritetų tvarka yra {2:B}, {3:C}, {1:A}
- Gaukite (4 raktas): Stebėkite, kad 4 klavišo talpykloje nėra, šiai operacijai grąžiname „-1“.
- Įdėti (4 raktas, reikšmė D) : Stebėkite, ar talpykla pilna, dabar naudokite LRU algoritmą, kad nustatytumėte, kuris raktas buvo naudojamas mažiausiai neseniai. Kadangi {1:A} turėjo mažiausią prioritetą, pašalinkite {1:A} iš talpyklos ir įdėkite {4:D} į talpyklą. Atkreipkite dėmesį, kad nauja prioriteto tvarka yra {4:D}, {2:B}, {3:C}
- Įdėti (3 raktas, vertė E) : Kadangi key=3 jau buvo talpykloje su value=C, todėl ši operacija nepašalins jokio rakto, o atnaujins key=3 reikšmę į „ IR' . Dabar nauja prioriteto tvarka taps {3:E}, {4:D}, {2:B}
- Gaukite (4 klavišas) : grąžina rakto reikšmę = 4. Dabar naujas prioritetas taps {4:D}, {3:E}, {2:B}
- Įdėti (1 raktas, vertė A) : Kadangi mūsų talpykla PILNA, todėl naudokite mūsų LRU algoritmą, kad nustatytumėte, kuris raktas buvo naudojamas mažiausiai neseniai, o kadangi {2:B} turėjo mažiausią prioritetą, pašalinkite {2:B} iš talpyklos ir įdėkite {1:A} į talpykla. Dabar nauja prioriteto tvarka yra {1:A}, {4:D}, {3:E}
LRU talpyklos diegimo būdai:
LRU talpykla gali būti įdiegta įvairiais būdais, ir kiekvienas programuotojas gali pasirinkti skirtingą metodą. Tačiau toliau pateikiami dažniausiai naudojami metodai:
- LRU naudojant eilę ir maišą
- LRU naudojant Dvigubai susietas sąrašas + maiša
- LRU naudojant Deque
- LRU naudojant Stack
- LRU naudojant Skaitiklio įgyvendinimas
- LRU naudojant Lazy Updates
LRU talpyklos diegimas naudojant eilę ir maišą:
Mes naudojame dvi duomenų struktūras, kad įdiegtume LRU talpyklą.
- Eilė yra įgyvendinamas naudojant dvigubai susietą sąrašą. Didžiausias eilės dydis bus lygus bendram galimų kadrų skaičiui (talpyklos dydžiui). Paskutiniai naudoti puslapiai bus šalia priekinės dalies, o rečiausiai naudoti puslapiai bus netoli galinės dalies.
- A Hašas su puslapio numeriu kaip raktu ir atitinkamo eilės mazgo adresu kaip reikšmė.
Kai pateikiama nuoroda į puslapį, reikiamas puslapis gali būti atmintyje. Jei jis yra atmintyje, turime atskirti sąrašo mazgą ir perkelti jį į eilės priekį.
Jei reikiamo puslapio atmintyje nėra, įnešame jį į atmintį. Paprastais žodžiais tariant, eilės priekyje pridedame naują mazgą ir atnaujiname atitinkamo mazgo adresą maišoje. Jei eilė pilna, t.y. visi kadrai pilni, pašaliname mazgą iš eilės galo, o naują mazgą įtraukiame į eilės priekį.
Iliustracija:
Apsvarstykime operacijas, Nurodo Raktas x su LRU talpykloje: { 1, 2, 3, 4, 1, 2, 5, 1, 2, 3 }
Pastaba: Iš pradžių atmintyje nėra puslapio.Toliau pateiktuose vaizduose žingsnis po žingsnio parodytas aukščiau nurodytų operacijų vykdymas LRU talpykloje.
Algoritmas:
- Sukurkite klasę LRUCache su deklaruodami int tipo sąrašą, netvarkingą tipo žemėlapį
, ir kintamasis, skirtas saugoti maksimalų talpyklos dydį - LRUCache nuoroda funkcijoje
- Jei šios reikšmės eilėje nėra, stumkite šią reikšmę prieš eilę ir pašalinkite paskutinę reikšmę, jei eilė pilna
- Jei reikšmė jau yra, pašalinkite ją iš eilės ir įstumkite į eilės priekį
- Ekrano funkcijoje spausdinama LRUCache naudojant eilę pradedant nuo priekio
Toliau pateikiamas pirmiau minėto metodo įgyvendinimas:
C++
Linux paleisti cmd
// We can use stl container list as a double> // ended queue to store the cache keys, with> // the descending time of reference from front> // to back and a set container to check presence> // of a key. But to fetch the address of the key> // in the list using find(), it takes O(N) time.> // This can be optimized by storing a reference> // (iterator) to each key in a hash map.> #include> using> namespace> std;> > class> LRUCache {> >// store keys of cache> >list<>int>>dq;>> // store references of key in cache> >unordered_map<>int>, list<>int>>::iteratorius> ma;>> csize;>// maximum capacity of cache> > public>:> >LRUCache(>int>);> >void> refer(>int>);> >void> display();> };> > // Declare the size> LRUCache::LRUCache(>int> n) { csize = n; }> > // Refers key x with in the LRU cache> void> LRUCache::refer(>int> x)> {> >// not present in cache> >if> (ma.find(x) == ma.end()) {> >// cache is full> >if> (dq.size() == csize) {> >// delete least recently used element> >int> last = dq.back();> > >// Pops the last element> >dq.pop_back();> > >// Erase the last> >ma.erase(last);> >}> >}> > >// present in cache> >else> >dq.erase(ma[x]);> > >// update reference> >dq.push_front(x);> >ma[x] = dq.begin();> }> > // Function to display contents of cache> void> LRUCache::display()> {> > >// Iterate in the deque and print> >// all the elements in it> >for> (>auto> it = dq.begin(); it != dq.end(); it++)> >cout << (*it) <<>' '>;> > >cout << endl;> }> > // Driver Code> int> main()> {> >LRUCache ca(4);> > >ca.refer(1);> >ca.refer(2);> >ca.refer(3);> >ca.refer(1);> >ca.refer(4);> >ca.refer(5);> >ca.display();> > >return> 0;> }> // This code is contributed by Satish Srinivas> |
>
>
C
// A C program to show implementation of LRU cache> #include> #include> > // A Queue Node (Queue is implemented using Doubly Linked> // List)> typedef> struct> QNode {> >struct> QNode *prev, *next;> >unsigned> >pageNumber;>// the page number stored in this QNode> } QNode;> > // A Queue (A FIFO collection of Queue Nodes)> typedef> struct> Queue {> >unsigned count;>// Number of filled frames> >unsigned numberOfFrames;>// total number of frames> >QNode *front, *rear;> } Queue;> > // A hash (Collection of pointers to Queue Nodes)> typedef> struct> Hash {> >int> capacity;>// how many pages can be there> >QNode** array;>// an array of queue nodes> } Hash;> > // A utility function to create a new Queue Node. The queue> // Node will store the given 'pageNumber'> QNode* newQNode(unsigned pageNumber)> {> >// Allocate memory and assign 'pageNumber'> >QNode* temp = (QNode*)>malloc>(>sizeof>(QNode));> >temp->pageNumber = puslapioNumber;>> // Initialize prev and next as NULL> >temp->ankstesnis = temp->kitas = NULL;>> return> temp;> }> > // A utility function to create an empty Queue.> // The queue can have at most 'numberOfFrames' nodes> Queue* createQueue(>int> numberOfFrames)> {> >Queue* queue = (Queue*)>malloc>(>sizeof>(Queue));> > >// The queue is empty> >queue->skaičius = 0;>> // Number of frames that can be stored in memory> >queue->skaičiusOframes = skaičiusOframes;>> return> queue;> }> > // A utility function to create an empty Hash of given> // capacity> Hash* createHash(>int> capacity)> {> >// Allocate memory for hash> >Hash* hash = (Hash*)>malloc>(>sizeof>(Hash));> >hash->talpa = talpa;>> // Create an array of pointers for referring queue nodes> >hash->masyvas>> malloc>(hash->talpa *>>> > >// Initialize all hash entries as empty> >int> i;> >for> (i = 0; i capacity; ++i)> >hash->masyvas[i] = NULL;>> return> hash;> }> > // A function to check if there is slot available in memory> int> AreAllFramesFull(Queue* queue)> {> >return> queue->count == eilė->Frames skaičius;>> // A utility function to check if queue is empty> int> isQueueEmpty(Queue* queue)> {> >return> queue->galinis == NULL;>> // A utility function to delete a frame from queue> void> deQueue(Queue* queue)> {> >if> (isQueueEmpty(queue))> >return>;> > >// If this is the only node in list, then change front> >if> (queue->priekis == eilė-> galas)>> // Change rear and remove the previous rear> >QNode* temp = queue->galinis;>> if> (queue->gale)>> free>(temp);> > >// decrement the number of full frames by 1> >queue->skaičiuoti--;>> // A function to add a page with given 'pageNumber' to both> // queue and hash> void> Enqueue(Queue* queue, Hash* hash, unsigned pageNumber)> {> >// If all frames are full, remove the page at the rear> >if> (AreAllFramesFull(queue)) {> >// remove page from hash> >hash->masyvas[eilė->gale->puslapio numeris] = NULL;>> >}> > >// Create a new node with given page number,> >// And add the new node to the front of queue> >QNode* temp = newQNode(pageNumber);> >temp->kitas = eilė->priekis;>> // If queue is empty, change both front and rear> >// pointers> >if> (isQueueEmpty(queue))> >queue->galinis = eilė->priekis = temp;>> // Else change the front> >{> >queue->front->prev = temp;>> > >// Add page entry to hash also> >hash->masyvas[puslapio numeris] = temp;>> // increment number of full frames> >queue->skaičiuoti++;>> // This function is called when a page with given> // 'pageNumber' is referenced from cache (or memory). There> // are two cases:> // 1. Frame is not there in memory, we bring it in memory> // and add to the front of queue> // 2. Frame is there in memory, we move the frame to front> // of queue> void> ReferencePage(Queue* queue, Hash* hash,> >unsigned pageNumber)> {> >QNode* reqPage = hash->masyvas[puslapio numeris];>> // the page is not in cache, bring it> >if> (reqPage == NULL)> >Enqueue(queue, hash, pageNumber);> > >// page is there and not at front, change pointer> >else> if> (reqPage != queue->priekyje) {> >// Unlink rquested page from its current location> >// in queue.> >reqPage->ankstesnis->kitas = reqPage->ext;>> (reqPage->kitas)>>> // If the requested page is rear, then change rear> >// as this node will be moved to front> >if> (reqPage == queue->gale) {> >queue->galinis = reqPage->prev;>> > >// Put the requested page before current front> >reqPage->kitas = eilė->priekis;>> // Change prev of current front> >reqPage->kitas->ankstesnis = reqPage;>> // Change front to the requested page> >queue->front = reqPage;>> }> > // Driver code> int> main()> {> >// Let cache can hold 4 pages> >Queue* q = createQueue(4);> > >// Let 10 different pages can be requested (pages to be> >// referenced are numbered from 0 to 9> >Hash* hash = createHash(10);> > >// Let us refer pages 1, 2, 3, 1, 4, 5> >ReferencePage(q, hash, 1);> >ReferencePage(q, hash, 2);> >ReferencePage(q, hash, 3);> >ReferencePage(q, hash, 1);> >ReferencePage(q, hash, 4);> >ReferencePage(q, hash, 5);> > >// Let us print cache frames after the above referenced> >// pages> >printf>(>'%d '>, q->front->pageNumber);>> (>'%d '>, q->priekis->kitas->puslapio numeris);>> (>'%d '>, q->front->ext->ext->pageNumber);>> (>'%d '>, q->priekis->kitas->kitas->kitas->puslapio numeris);>> return> 0;> }> |
>
>
Java
/* We can use Java inbuilt Deque as a double> >ended queue to store the cache keys, with> >the descending time of reference from front> >to back and a set container to check presence> >of a key. But remove a key from the Deque using> >remove(), it takes O(N) time. This can be> >optimized by storing a reference (iterator) to> >each key in a hash map. */> import> java.util.Deque;> import> java.util.HashSet;> import> java.util.Iterator;> import> java.util.LinkedList;> > public> class> LRUCache {> > >// store keys of cache> >private> Deque doublyQueue;> > >// store references of key in cache> >private> HashSet hashSet;> > >// maximum capacity of cache> >private> final> int> CACHE_SIZE;> > >LRUCache(>int> capacity)> >{> >doublyQueue =>new> LinkedList();> >hashSet =>new> HashSet();> >CACHE_SIZE = capacity;> >}> > >/* Refer the page within the LRU cache */> >public> void> refer(>int> page)> >{> >if> (!hashSet.contains(page)) {> >if> (doublyQueue.size() == CACHE_SIZE) {> >int> last = doublyQueue.removeLast();> >hashSet.remove(last);> >}> >}> >else> {>/* The found page may not be always the last> >element, even if it's an intermediate> >element that needs to be removed and added> >to the start of the Queue */> >doublyQueue.remove(page);> >}> >doublyQueue.push(page);> >hashSet.add(page);> >}> > >// display contents of cache> >public> void> display()> >{> >Iterator itr = doublyQueue.iterator();> >while> (itr.hasNext()) {> >System.out.print(itr.next() +>' '>);> >}> >}> > >// Driver code> >public> static> void> main(String[] args)> >{> >LRUCache cache =>new> LRUCache(>4>);> >cache.refer(>1>);> >cache.refer(>2>);> >cache.refer(>3>);> >cache.refer(>1>);> >cache.refer(>4>);> >cache.refer(>5>);> >cache.display();> >}> }> // This code is contributed by Niraj Kumar> |
>
>
Python3
# We can use stl container list as a double> # ended queue to store the cache keys, with> # the descending time of reference from front> # to back and a set container to check presence> # of a key. But to fetch the address of the key> # in the list using find(), it takes O(N) time.> # This can be optimized by storing a reference> # (iterator) to each key in a hash map.> class> LRUCache:> ># store keys of cache> >def> __init__(>self>, n):> >self>.csize>=> n> >self>.dq>=> []> >self>.ma>=> {}> > > ># Refers key x with in the LRU cache> >def> refer(>self>, x):> > ># not present in cache> >if> x>not> in> self>.ma.keys():> ># cache is full> >if> len>(>self>.dq)>=>=> self>.csize:> ># delete least recently used element> >last>=> self>.dq[>->1>]> > ># Pops the last element> >ele>=> self>.dq.pop();> > ># Erase the last> >del> self>.ma[last]> > ># present in cache> >else>:> >del> self>.dq[>self>.ma[x]]> > ># update reference> >self>.dq.insert(>0>, x)> >self>.ma[x]>=> 0>;> > ># Function to display contents of cache> >def> display(>self>):> > ># Iterate in the deque and print> ># all the elements in it> >print>(>self>.dq)> > # Driver Code> ca>=> LRUCache(>4>)> > ca.refer(>1>)> ca.refer(>2>)> ca.refer(>3>)> ca.refer(>1>)> ca.refer(>4>)> ca.refer(>5>)> ca.display()> # This code is contributed by Satish Srinivas> |
>
>
C#
// C# program to implement the approach> > using> System;> using> System.Collections.Generic;> > class> LRUCache {> >// store keys of cache> >private> List<>int>>doubleQueue;>> // store references of key in cache> >private> HashSet<>int>>hashSet;>> // maximum capacity of cache> >private> int> CACHE_SIZE;> > >public> LRUCache(>int> capacity)> >{> >doublyQueue =>new> List<>int>>();>> new> HashSet<>int>>();>> >}> > >/* Refer the page within the LRU cache */> >public> void> Refer(>int> page)> >{> >if> (!hashSet.Contains(page)) {> >if> (doublyQueue.Count == CACHE_SIZE) {> >int> last> >= doublyQueue[doublyQueue.Count - 1];> >doublyQueue.RemoveAt(doublyQueue.Count - 1);> >hashSet.Remove(last);> >}> >}> >else> {> >/* The found page may not be always the last> >element, even if it's an intermediate> >element that needs to be removed and added> >to the start of the Queue */> >doublyQueue.Remove(page);> >}> >doublyQueue.Insert(0, page);> >hashSet.Add(page);> >}> > >// display contents of cache> >public> void> Display()> >{> >foreach>(>int> page>in> doublyQueue)> >{> >Console.Write(page +>' '>);> >}> >}> > >// Driver code> >static> void> Main(>string>[] args)> >{> >LRUCache cache =>new> LRUCache(4);> >cache.Refer(1);> >cache.Refer(2);> >cache.Refer(3);> >cache.Refer(1);> >cache.Refer(4);> >cache.Refer(5);> >cache.Display();> >}> }> > // This code is contributed by phasing17> |
>
>
Javascript
// JS code to implement the approach> class LRUCache {> >constructor(n) {> >this>.csize = n;> >this>.dq = [];> >this>.ma =>new> Map();> >}> > >refer(x) {> >if> (!>this>.ma.has(x)) {> >if> (>this>.dq.length ===>this>.csize) {> >const last =>this>.dq[>this>.dq.length - 1];> >this>.dq.pop();> >this>.ma.>delete>(last);> >}> >}>else> {> >this>.dq.splice(>this>.dq.indexOf(x), 1);> >}> > >this>.dq.unshift(x);> >this>.ma.set(x, 0);> >}> > >display() {> >console.log(>this>.dq);> >}> }> > const cache =>new> LRUCache(4);> > cache.refer(1);> cache.refer(2);> cache.refer(3);> cache.refer(1);> cache.refer(4);> cache.refer(5);> cache.display();> > // This code is contributed by phasing17> |
>
>
LRU talpyklos diegimas naudojant dvigubai susietą sąrašą ir maišą :
Idėja yra labai paprasta, t. y. toliau įterpkite elementus prie galvos.
- jei elemento sąraše nėra, pridėkite jį prie sąrašo pradžios
- jei elementas yra sąraše, perkelkite elementą į antraštę ir perkelkite likusį sąrašo elementą
Atkreipkite dėmesį, kad mazgo prioritetas priklausys nuo to mazgo atstumo nuo galvos, kuo mazgas arčiausiai galvos, tuo aukštesnis jo prioritetas. Taigi, kai talpyklos dydis yra pilnas ir mums reikia pašalinti kurį nors elementą, pašaliname elementą, esantį šalia dvigubai susieto sąrašo uodegos.
LRU talpyklos diegimas naudojant Deque & Hashmap:
Deque duomenų struktūra leidžia įterpti ir ištrinti iš priekio ir galo, ši savybė leidžia įgyvendinti LRU, nes priekinis elementas gali būti aukšto prioriteto elementas, o galutinis elementas gali būti žemo prioriteto elementas, t. y. Neseniai naudotas.
Dirba:
- Gaukite operaciją : patikrina, ar raktas yra talpyklos maišos žemėlapyje, ir laikykitės toliau pateiktų atvejai:
- Jei raktas rastas:
- Daiktas laikomas neseniai naudotu, todėl jis perkeliamas į deko priekį.
- Su raktu susijusi reikšmė grąžinama kaip rezultatas
get>operacija.- Jei raktas nerastas:
- grąžinkite -1, nurodydami, kad tokio rakto nėra.
- Įdėjimo operacija: Pirmiausia patikrinkite, ar raktas jau yra talpyklos maišos žemėlapyje, ir vadovaukitės toliau pateiktais atvejais
- Jei raktas yra:
- Su raktu susijusi vertė atnaujinama.
- Elementas perkeltas į deko priekinę dalį, nes dabar jis naudotas vėliausiai.
- Jei rakto nėra:
- Jei talpykla pilna, tai reiškia, kad reikia įdėti naują elementą, o rečiausiai naudotą prekę – iškeldinti. Tai atliekama pašalinant elementą iš dektos pabaigos ir atitinkamą įrašą iš maišos žemėlapio.
- Tada naujoji rakto-reikšmių pora įterpiama ir į maišos žemėlapį, ir į deque priekinę dalį, kad būtų pažymėta, kad tai vėliausiai naudotas elementas
LRU talpyklos diegimas naudojant Stack & Hashmap:
LRU (mažiausiai naudotos) talpyklos įdiegimas naudojant dėklo duomenų struktūrą ir maišą gali būti šiek tiek sudėtingas, nes paprastas dėklas nesuteikia veiksmingos prieigos prie mažiausiai neseniai naudoto elemento. Tačiau galite derinti krūvą su maišos žemėlapiu, kad tai pasiektumėte efektyviai. Štai aukšto lygio metodas, kaip jį įgyvendinti:
- Naudokite maišos žemėlapį : maišos žemėlapyje bus saugomos talpyklos raktų ir reikšmių poros. Raktai bus susieti su atitinkamais krūvos mazgais.
- Naudokite krūvą : dėklas išlaikys raktų tvarką pagal jų naudojimą. Neseniai naudotas daiktas bus krūvos apačioje, o paskutinis naudotas – viršuje
Šis metodas nėra toks efektyvus, todėl nenaudojamas dažnai.
konvertuoti eilutę į sveikąjį skaičių Java
LRU talpykla naudojant Counter Implementation:
Kiekvienas talpyklos blokas turės savo LRU skaitiklį, kuriam priklauso skaitiklio reikšmė nuo 0 iki n-1} , čia n “ reiškia talpyklos dydį. Blokas, kuris keičiamas bloko keitimo metu, tampa MRU bloku, todėl jo skaitiklio reikšmė pakeičiama į n – 1. Skaitiklio reikšmės, didesnės už gauto bloko skaitiklio reikšmę, sumažinamos vienu. Likę blokai nepakeisti.
| Conter vertė | Pirmenybė | Naudota būsena |
|---|---|---|
| 0 | Žemas | Neseniai naudotas |
| n-1 | Aukštas | Dažniausiai naudotas |
LRU talpyklos diegimas naudojant „Lazy Updates“:
LRU (mažiausiai naudotos) talpyklos įdiegimas naudojant tingius naujinimus yra įprastas būdas pagerinti talpyklos operacijų efektyvumą. Tingi atnaujinimai apima sekimo tvarką, kuria pasiekiami elementai, nedelsiant neatnaujinant visos duomenų struktūros. Kai įvyksta talpyklos praleidimas, pagal tam tikrus kriterijus galite nuspręsti, ar atlikti visą atnaujinimą, ar ne.
LRU talpyklos sudėtingumo analizė:
- Laiko sudėtingumas:
- „Put()“ operacija: O(1), ty laikas, reikalingas naujai rakto-reikšmių porai įterpti arba atnaujinti, yra pastovus
- Get() operacija: O(1), ty laikas, reikalingas rakto vertei gauti, yra pastovus
- Pagalbinė erdvė: O(N) kur N yra talpyklos talpa.
LRU talpyklos privalumai:
- Greita prieiga : Norint pasiekti duomenis iš LRU talpyklos, reikia O(1) laiko.
- Greitas atnaujinimas : Atnaujinti rakto-reikšmių porą LRU talpykloje užtrunka O(1) laiko.
- Greitas mažiausiai naudotų duomenų pašalinimas : Reikia O(1) ištrinti tai, kas neseniai nebuvo naudojama.
- Jokio daužymo: LRU yra mažiau jautrus daužymui, palyginti su FIFO, nes atsižvelgia į puslapių naudojimo istoriją. Jis gali aptikti, kurie puslapiai yra dažnai naudojami, ir suteikti jiems pirmenybę atminties paskirstymui, taip sumažinant puslapių klaidų skaičių ir disko įvesties/išvesties operacijas.
LRU talpyklos trūkumai:
- Norint padidinti efektyvumą, reikia didelio talpyklos dydžio.
- Tam reikia įdiegti papildomą duomenų struktūrą.
- Aparatinės įrangos pagalba yra didelė.
- LRU klaidų aptikimas yra sudėtingas, palyginti su kitais algoritmais.
- Jis turi ribotą priimtinumą.
Realus LRU talpyklos taikymas:
- Duomenų bazių sistemose, kad gautumėte greitus užklausų rezultatus.
- Operacinėse sistemose, kad sumažintumėte puslapio klaidas.
- Teksto redaktoriai ir IDE, skirti saugoti dažnai naudojamus failus ar kodo fragmentus
- Tinklo maršrutizatoriai ir komutatoriai naudoja LRU, kad padidintų kompiuterių tinklo efektyvumą
- Kompiliatoriaus optimizavime
- Teksto numatymo ir automatinio užbaigimo įrankiai