title: 鏈表2
date: 2019-02-19 22:17:11
tags: 鏈表
copyright: true
categories: 算法
---java
通過上一章的學習,咱們基本瞭解了鏈表的特性,如今咱們就兩個練習增強對鏈表這種數據結構的理解和應用,發揮你的才智吧!node
有哪些緩存淘汰策略? 常見的3種包括先進先出策略FIFO(First In,First Out)、最少使用策略LFU(Least Frequently Used)、最近最少使用策略LRU(Least Recently Used)。算法
當訪問的數據沒有存儲在緩存的鏈表中時,直接將數據插入鏈表表頭,時間複雜度爲O(1);當訪問的數據存在於存儲的鏈表中時,將該數據對應的節點,插入到鏈表表頭,時間複雜度爲O(n)。若是緩存被佔滿,則從鏈表尾部的數據開始清理,時間複雜度爲O(1)。
代碼實現:數據庫
public class LRUBaseLinkedList<T> { /** * 默認鏈表容量 */ private final static Integer DEFAULT_CAPACITY = 10; /** * 頭結點 */ private SNode<T> headNode; /** * 鏈表長度 */ private Integer length; /** * 鏈表容量 */ private Integer capacity; public LRUBaseLinkedList() { this.headNode = new SNode<>(); this.capacity = DEFAULT_CAPACITY; this.length = 0; } public LRUBaseLinkedList(Integer capacity) { this.headNode = new SNode<>(); this.capacity = capacity; this.length = 0; } public void add(T data) { SNode preNode = findPreNode(data); // 鏈表中存在,刪除原數據,再插入到鏈表的頭部 if (preNode != null) { deleteElemOptim(preNode); intsertElemAtBegin(data); } else { if (length >= this.capacity) { //刪除尾結點 deleteElemAtEnd(); } intsertElemAtBegin(data); } } /** * 刪除preNode結點下一個元素 * * @param preNode */ private void deleteElemOptim(SNode preNode) { SNode temp = preNode.getNext(); preNode.setNext(temp.getNext()); temp = null; length--; } /** * 鏈表頭部插入節點 * * @param data */ private void intsertElemAtBegin(T data) { SNode next = headNode.getNext(); headNode.setNext(new SNode(data, next)); length++; } /** * 獲取查找到元素的前一個結點 * * @param data * @return */ private SNode findPreNode(T data) { SNode node = headNode; while (node.getNext() != null) { if (data.equals(node.getNext().getElement())) { return node; } node = node.getNext(); } return null; } /** * 刪除尾結點 */ private void deleteElemAtEnd() { SNode ptr = headNode; // 空鏈表直接返回 if (ptr.getNext() == null) { return; } // 倒數第二個結點 while (ptr.getNext().getNext() != null) { ptr = ptr.getNext(); } SNode tmp = ptr.getNext(); ptr.setNext(null); tmp = null; length--; } private void printAll() { SNode node = headNode.getNext(); while (node != null) { System.out.print(node.getElement() + ","); node = node.getNext(); } System.out.println(); } public class SNode<T> { private T element; private SNode next; public SNode(T element) { this.element = element; } public SNode(T element, SNode next) { this.element = element; this.next = next; } public SNode() { this.next = null; } public T getElement() { return element; } public void setElement(T element) { this.element = element; } public SNode getNext() { return next; } public void setNext(SNode next) { this.next = next; } } public static void main(String[] args) { LRUBaseLinkedList list = new LRUBaseLinkedList(); Scanner sc = new Scanner(System.in); while (true) { list.add(sc.nextInt()); list.printAll(); } } }
方式一:首位置保存最新訪問數據,末尾位置優先清理 當訪問的數據未存在於緩存的數組中時,直接將數據插入數組第一個元素位置,此時數組全部元素須要向後移動1個位置,時間複雜度爲O(n);當訪問的數據存在於緩存的數組中時,查找到數據並將其插入數組的第一個位置,此時亦需移動數組元素,時間複雜度爲O(n)。緩存用滿時,則清理掉末尾的數據,時間複雜度爲O(1)。數組
方式二:首位置優先清理,末尾位置保存最新訪問數據 當訪問的數據未存在於緩存的數組中時,直接將數據添加進數組做爲當前最有一個元素時間複雜度爲O(1);當訪問的數據存在於緩存的數組中時,查找到數據並將其插入當前數組最後一個元素的位置,此時亦需移動數組元素,時間複雜度爲O(n)。緩存用滿時,則清理掉數組首位置的元素,且剩餘數組元素需總體前移一位,時間複雜度爲O(n)。(優化:清理的時候能夠考慮一次性清理必定數量,從而下降清理次數,提升性能。)瀏覽器
ps 若是有小夥伴對緩存算法感興趣,能夠更深刻地瞭解一下==> 友情連接緩存
前提:字符串以單個字符的形式存儲在單鏈表中。數據結構
遍歷鏈表,判斷字符個數是否爲奇數,若爲偶數,則不是。性能
將鏈表中的字符倒序存儲一份在另外一個鏈表中。學習
同步遍歷2個鏈表,比較對應的字符是否相等,若相等,則是水仙花字串,不然,不是。