Skip to content

Commit

Permalink
Add single linked list and lru cache implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
songzheng45 committed Jan 10, 2019
1 parent 6b0594d commit 1e4b89c
Show file tree
Hide file tree
Showing 6 changed files with 789 additions and 0 deletions.
19 changes: 19 additions & 0 deletions csharp/06_linkedlist/BaseLinkedListTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;

namespace _06_linked_list
{
public class BaseLinkedListTests
{
protected void PrintList<T> (SingleLinkedList<T> list) where T : IComparable<T>
{
if (list == null) return;

var p = list.First;
while (p != null)
{
System.Console.WriteLine (p.Value);
p = p.Next;
}
}
}
}
63 changes: 63 additions & 0 deletions csharp/06_linkedlist/LRULinkedList.Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using Xunit;
using Xunit.Abstractions;

namespace _06_linked_list
{
public class LRULinkedListTests : BaseLinkedListTests
{
[Fact]
public void LRU_Set_Value_When_Not_Existed()
{
var lru = new LRULinkedList();

lru.Set(1);
lru.Set(3);
lru.Set(5);
lru.Set(7);
lru.Set(9);

var list = lru.GetCachedList();

PrintList(list);

Assert.Equal(9, list.First.Value);
}

[Fact]
public void LRU_Set_Value_When_Existed()
{
var lru = new LRULinkedList();

lru.Set(1);
lru.Set(3);
lru.Set(5);
lru.Set(7);
lru.Set(3);

var list = lru.GetCachedList();

PrintList(list);

Assert.Equal(3, list.First.Value);
}

[Fact]
public void LRU_Set_Value_When_Full()
{
var lru = new LRULinkedList(5);

lru.Set(1);
lru.Set(3);
lru.Set(5);
lru.Set(7);
lru.Set(9);
lru.Set(8);

var list = lru.GetCachedList();

PrintList(list);

Assert.Equal(8, list.First.Value);
}
}
}
63 changes: 63 additions & 0 deletions csharp/06_linkedlist/LRULinkedList.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
namespace _06_linked_list
{
/// <summary>
/// 使用单链表实现LRU缓存淘汰算法
/// </summary>
/// <remarks>
/// 思路:
/// 维护一个有序单链表,越是靠近链尾的数据是最早访问的。当有一个新的数据被访问时,
/// 1. 如果数据在缓存中,则将其从原位置删除,然后插入到表头;
/// 2. 如果数据不在缓存中,有两种情况:
/// 1) 链表未满,则将数据插入到表头;
/// 2) 链表已满,则删除尾结点,将新数据插入到表头。
/// </remarks>
public class LRULinkedList
{
private readonly SingleLinkedList<int> _cachedList = new SingleLinkedList<int>();
private readonly int _capacity;

/// <summary>
/// 构造函数
/// </summary>
/// <param name="capacity">缓存容量</param>
public LRULinkedList(int capacity = 10)
{
_capacity = capacity;
}

/// <summary>
/// 存储缓存数据
/// </summary>
/// <param name="val"></param>
public void Set(int val)
{
var deletedNode = _cachedList.Delete(value: val);

// 数据在缓存中存在,从原位置删除,然后插入到表头
if (deletedNode != null)
{
_cachedList.Insert(1, val);
return;
}

// 数据不存在
if (_cachedList.Length != _capacity)
{
// 链表未满
_cachedList.Insert(1, val);
}
else
{
// 链表已满,删除尾结点,将新数据插入到头部
_cachedList.Delete(_cachedList.Length);
_cachedList.Insert(1, val);
}
}

public SingleLinkedList<int> GetCachedList()
{
return _cachedList;
}
}

}
Loading

0 comments on commit 1e4b89c

Please sign in to comment.