鏈表:如何實現(xiàn)LRU緩存淘汰算法

緩存策略

1,F(xiàn)IFO(first in first out)先進先出
2夫壁,LFU(least frequently used)最少使用策略
3江滨,LRU(least recently used)最近最少使用策略

數(shù)組鏈表區(qū)別

數(shù)組
內(nèi)存連續(xù)

鏈表
內(nèi)存不連續(xù)

鏈表分類

單鏈表
雙向鏈表
循環(huán)鏈表
雙向循環(huán)鏈表

執(zhí)行較慢的程序

可以通過空間換時間來進行優(yōu)化
消耗過多內(nèi)存的程序油坝,可以通過時間換空間來降低內(nèi)存的消耗

鏈表數(shù)據(jù)使用

數(shù)據(jù)缺點大小固定,一經(jīng)聲明就要占用整塊的連續(xù)內(nèi)存空間
java中ArrayList使用動態(tài)擴容镇匀,但擴容時把原數(shù)組拷貝到擴充后的數(shù)組中是非常耗時的
如果對于代碼對內(nèi)存使用非痴赵澹苛刻就需要使用數(shù)組,因為鏈表每個結點指針都會占用內(nèi)存
對鏈表進行頻繁插入汗侵、刪除會導致頻繁內(nèi)存申請和釋放幸缕,容易造成內(nèi)存碎屏,java中也可能導致頻繁GC

LRU緩存淘汰算法

基于有序單鏈表事項LRU算法
維護一個有序單鏈表晰韵,越靠近鏈表尾部的結點是越早訪問的发乔。當有一個新的數(shù)據(jù)被訪問是,我們從鏈表頭開始順序遍歷鏈表
1雪猪,如果此數(shù)據(jù)之前已經(jīng)被緩存在鏈表中栏尚,我們遍歷得到這個數(shù)據(jù)對應的結點,并將其從原來的位置刪除只恨,然后在插入到鏈表的頭部
2译仗,如果此數(shù)據(jù)沒有在緩存鏈表中,分為兩種情況

  • 如果此時緩存未滿官觅,則將此結點直接插入到鏈表頭部
  • 如果此時緩存滿了纵菌,則鏈表尾結點刪除,將新數(shù)據(jù)結點插入到鏈表的頭部

寫鏈表

寫鏈表技巧

1休涤,理解指針或引用的含義

將某個變量賦值給指針咱圆,實際上就是將這個變量的地址賦值給指針,或者返過來說功氨,指針中存儲了這個變量的內(nèi)存地址序苏,指向了這個變量,通過指針就能找到這個變量

2捷凄,警惕指針丟失和內(nèi)存泄露

3忱详,利用哨兵簡化實現(xiàn)難度

帶頭結點鏈表

//在數(shù)組a中,查找key,返回key所在的位置
int find(char* a,int n,char key){
    if (a == NULL || n <= 0){
        return -1;
    }
    int i =0;
    while (i < n){
        if (a[i] == key){
            return i;
        }
        ++i;
    }
    return -1;
}

//在數(shù)組a中,查找key,返回key所在的位置
int find2(char* a,int n,char key){
    if (a == NULL || n <= 0){
        return -1;
    }
    if (a[n -1] == key){
        return n -1;
    }
    char tmp = a[n-1];
    a[n-1] = key;
  
    int i =0;
    while (a[i] != key){
        ++i;
    }
    a[n-1] = tmp;
    if (i == n-1){
        return -1;
    } else {
        return i;
    }
}

對比兩段代碼,在字符a很長時跺涤,第二段代碼更快匈睁,我們通過一個哨兵a[n-1]=key管钳,成功省略掉了一個比較語句

4,重點留意邊界條件處理

  • 如果鏈表為空時软舌,代碼是否能正常工作
  • 如果鏈表只包含一個結點,代碼是否能正常工作
  • 如果鏈表只包含兩個結點牛曹,代碼是否能正常工作
  • 代碼邏輯在處理頭結點和尾結點時佛点,是否能正常工作

5,舉例畫圖黎比,輔助思考

6超营,多練多寫沒有捷徑

創(chuàng)建鏈表頭插法,尾插法

LinkedList createListByHead(){
    int arr[] = {4,5,6,7,8,89,9,2,2,34};
    LinkedList head = malloc(sizeof(Node));
    head->next =NULL;
    for(int i = 0;i < 10;i++){
        Node *p = malloc(sizeof(Node));
        p->value=arr[i];
        p->next = head->next;
        head->next = p;

    }
    return head;
}


LinkedList createListByTail(){
    int arr[] = {4,5,6,7,8,89,9,2,2,34};
    LinkedList head = malloc(sizeof(Node));
    head->next =NULL;
    LinkedList p = head;
    for(int i = 0;i < 10;i++){
        Node *q = malloc(sizeof(Node));
        q->value=arr[i];
        q->next=NULL;
        p->next = q;
        p=p->next;
    }
    return head;
}

單鏈表反轉

//不帶頭結點單鏈表反轉
LinkedList reverseList(Node* head){
    if (head == NULL){
        return NULL;
    }
    if (head->next == NULL){
        return head;
    }
    Node *root = head;
    Node *pre = NULL;
    Node *next = NULL;
    while (root->next!= NULL){
        next=root->next;
        root->next=pre;
        pre=root;
        root=next;
    }
    root->next=pre;
    return next;
}

鏈表中環(huán)檢測

int isCircle(Node* head){
    Node* fast=head;
    Node* slow=head;
    while (fast != NULL && slow != NULL){
        fast = fast->next;
        slow = slow->next;
        if (fast != NULL){
            fast = fast->next;
        }
        if (slow != NULL && slow == fast){
            return 1;
        }
    }
    return 0;
}

兩個有序鏈表合并

LinkedList mergeList(Node* first,Node* second){
    if (first ==NULL && second ==NULL){
        return NULL;
    } else if (first ==NULL){
        return second;
    } else if (second ==NULL){
        return first;
    }
    Node* p = NULL;
    Node* head = NULL;
    while (first!=NULL && second!=NULL){
        if (first->value <= second->value){
            if (head == NULL){
                head = first;
                p = first;
            } else {
                p->next = first;
                p = p->next;
            }
            first = first->next;
        } else {
            if (head == NULL){
                head = second;
                p = second;
            } else {
                p->next = second;
                p = p->next;
            }
            second = second->next;
        }
    }

    if (first!=NULL){
        p->next = first;
    }
    if (second!=NULL){
        p->next = second;
    }
    return head;
}

刪除鏈表倒數(shù)第n個結點

LinkedList deleteElementFromTail(Node* head,int i){
    if (head==NULL || i < 0){
        return NULL;
    }
    Node* fast = head;
    Node* low = head;
    Node* pre = NULL;
    while (i -1 >0){
        if (fast->next != NULL){
            fast = fast->next;
        } else {
            return head;
        }
        i--;
    }
    while (fast->next != NULL){
        fast = fast->next;
        pre = low;
        low = low->next;
    }
    if (low == head){
        head = head->next;
        free(pre);
    } else {
        pre->next = pre->next->next;
        free(low);
    }
    return head;
}

求鏈表的中間結點

LinkedList findMiddleOfList(Node* head){
    if (head == NULL || head->next == NULL || head->next->next ==NULL){
        return head;
    }
    Node* fast = head;
    Node* low = head;
    while (fast->next !=NULL){
        fast = fast->next->next;
        low = low->next;
    }
    return low;
}
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末阅虫,一起剝皮案震驚了整個濱河市演闭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌颓帝,老刑警劉巖米碰,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異购城,居然都是意外死亡吕座,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進店門瘪板,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吴趴,“玉大人,你說我怎么就攤上這事侮攀÷嘀Γ” “怎么了?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵兰英,是天一觀的道長撇叁。 經(jīng)常有香客問我,道長箭昵,這世上最難降的妖魔是什么税朴? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮家制,結果婚禮上正林,老公的妹妹穿的比我還像新娘。我一直安慰自己颤殴,他們只是感情好觅廓,可當我...
    茶點故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著涵但,像睡著了一般杈绸。 火紅的嫁衣襯著肌膚如雪帖蔓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天瞳脓,我揣著相機與錄音塑娇,去河邊找鬼。 笑死劫侧,一個胖子當著我的面吹牛埋酬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播烧栋,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼写妥,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了审姓?” 一聲冷哼從身側響起珍特,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎魔吐,沒想到半個月后扎筒,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡画畅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年砸琅,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片轴踱。...
    茶點故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡症脂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出淫僻,到底是詐尸還是另有隱情诱篷,我是刑警寧澤,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布雳灵,位于F島的核電站棕所,受9級特大地震影響,放射性物質發(fā)生泄漏悯辙。R本人自食惡果不足惜琳省,卻給世界環(huán)境...
    茶點故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望躲撰。 院中可真熱鬧针贬,春花似錦、人聲如沸拢蛋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽谆棱。三九已至快压,卻和暖如春圆仔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蔫劣。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工坪郭, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人脉幢。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓截粗,卻偏偏與公主長得像,于是被迫代替她去往敵國和親鸵隧。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,658評論 2 350

推薦閱讀更多精彩內(nèi)容