重构项目结构,实现链表LRU缓存和链表反转等几个常规操作
This commit is contained in:
parent
1e4b89cfc2
commit
53a4d69bc8
@ -1,223 +0,0 @@
|
||||
using System;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
public class ArrayTests
|
||||
{
|
||||
private readonly Array<int> _sqList;
|
||||
private readonly ITestOutputHelper _output;
|
||||
|
||||
public ArrayTests (ITestOutputHelper output)
|
||||
{
|
||||
_sqList = new Array<int> (10);
|
||||
_output = output;
|
||||
}
|
||||
|
||||
private void PrintList ()
|
||||
{
|
||||
for (int idx = 0; idx < _sqList.Length; idx++)
|
||||
{
|
||||
var elem = _sqList.Find (idx + 1);
|
||||
_output.WriteLine (elem.ToString ());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Length_Equal_0_When_List_Is_Empty ()
|
||||
{
|
||||
Assert.True (_sqList.Length == 0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Length_Equal_1_After_InsertOneElement ()
|
||||
{
|
||||
_sqList.Insert (1, 1);
|
||||
Assert.True (_sqList.Length == 1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Insert_ThrowIndexOutOfRangeException_When_PositionGreaterThanLength ()
|
||||
{
|
||||
_sqList.Insert (1, 1);
|
||||
Exception ex = Assert.Throws<IndexOutOfRangeException> (() => _sqList.Insert (3, 1));
|
||||
Assert.IsType<IndexOutOfRangeException> (ex);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Insert_ThrowIndexOutOfRangeException_When_PositionLessThanOne ()
|
||||
{
|
||||
Exception ex = Assert.Throws<IndexOutOfRangeException> (() => _sqList.Insert (0, 1));
|
||||
Assert.IsType<IndexOutOfRangeException> (ex);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Insert_ThrowIndexOutOfRangeException_When_List_Is_Full ()
|
||||
{
|
||||
_sqList.Insert (1, 10);
|
||||
_sqList.Insert (2, 9);
|
||||
_sqList.Insert (3, 8);
|
||||
_sqList.Insert (4, 7);
|
||||
_sqList.Insert (5, 6);
|
||||
_sqList.Insert (6, 5);
|
||||
_sqList.Insert (7, 4);
|
||||
_sqList.Insert (8, 3);
|
||||
_sqList.Insert (9, 2);
|
||||
_sqList.Insert (10, 1);
|
||||
|
||||
PrintList ();
|
||||
|
||||
Exception ex = Assert.Throws<OutOfMemoryException> (() => _sqList.Insert (11, 101));
|
||||
Assert.IsType<OutOfMemoryException> (ex);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Delete_ThrowIndexOutOfRangeException_When_PositionLessThanOne ()
|
||||
{
|
||||
Exception ex = Assert.Throws<IndexOutOfRangeException> (() => _sqList.Delete (0));
|
||||
Assert.IsType<IndexOutOfRangeException> (ex);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Delete_ThrowIndexOutOfRangeException_When_PositionGreaterThanLength ()
|
||||
{
|
||||
_sqList.Insert (1, 11);
|
||||
_sqList.Insert (2, 22);
|
||||
Exception ex = Assert.Throws<IndexOutOfRangeException> (() => _sqList.Delete (3));
|
||||
Assert.IsType<IndexOutOfRangeException> (ex);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Delete_First_Element ()
|
||||
{
|
||||
_sqList.Insert (1, 11);
|
||||
_sqList.Insert (2, 22);
|
||||
|
||||
var elem = _sqList.Delete (1);
|
||||
Assert.Equal (11, elem);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Delete_Last_Element ()
|
||||
{
|
||||
_sqList.Insert (1, 11);
|
||||
_sqList.Insert (2, 22);
|
||||
_sqList.Insert (3, 33);
|
||||
|
||||
var elem = _sqList.Delete (3);
|
||||
Assert.Equal (33, elem);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Delete_Middle_Element ()
|
||||
{
|
||||
_sqList.Insert (1, 11);
|
||||
_sqList.Insert (2, 22);
|
||||
_sqList.Insert (3, 33);
|
||||
|
||||
var elem = _sqList.Delete (2);
|
||||
Assert.Equal (22, elem);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetElem_ThrowsIndexOutOfRangeException_When_PositionLessThanZero ()
|
||||
{
|
||||
_sqList.Insert (1, 11);
|
||||
_sqList.Insert (2, 22);
|
||||
_sqList.Insert (3, 33);
|
||||
|
||||
Exception ex = Assert.Throws<IndexOutOfRangeException> (() => _sqList.Find (0));
|
||||
Assert.IsType<IndexOutOfRangeException> (ex);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetElem_ThrowsIndexOutOfRangeException_When_PositionGreaterThanLength ()
|
||||
{
|
||||
_sqList.Insert (1, 11);
|
||||
_sqList.Insert (2, 22);
|
||||
_sqList.Insert (3, 33);
|
||||
|
||||
Exception ex = Assert.Throws<IndexOutOfRangeException> (() => _sqList.Find (4));
|
||||
Assert.IsType<IndexOutOfRangeException> (ex);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetElem_Last_Position_Return_33 ()
|
||||
{
|
||||
_sqList.Insert (1, 11);
|
||||
_sqList.Insert (2, 22);
|
||||
_sqList.Insert (3, 33);
|
||||
|
||||
var elem = _sqList.Find (3);
|
||||
|
||||
Assert.Equal (33, elem);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetElem_First_Position_Return_11 ()
|
||||
{
|
||||
_sqList.Insert (1, 11);
|
||||
_sqList.Insert (2, 22);
|
||||
_sqList.Insert (3, 33);
|
||||
|
||||
var elem = _sqList.Find (1);
|
||||
|
||||
Assert.Equal (11, elem);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IndexOf_Return_Netagive1_When_Element_Not_Exist ()
|
||||
{
|
||||
_sqList.Insert (1, 11);
|
||||
_sqList.Insert (2, 22);
|
||||
_sqList.Insert (3, 33);
|
||||
|
||||
var elem = _sqList.IndexOf (55);
|
||||
|
||||
Assert.Equal (-1, elem);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IndexOf_Return_First_Index ()
|
||||
{
|
||||
_sqList.Insert (1, 11);
|
||||
_sqList.Insert (2, 22);
|
||||
_sqList.Insert (3, 33);
|
||||
|
||||
var elem = _sqList.IndexOf (11);
|
||||
|
||||
Assert.Equal (0, elem);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IndexOf_Return_Last_Index ()
|
||||
{
|
||||
_sqList.Insert (1, 11);
|
||||
_sqList.Insert (2, 22);
|
||||
_sqList.Insert (3, 33);
|
||||
|
||||
var elem = _sqList.IndexOf (33);
|
||||
|
||||
Assert.Equal (2, elem);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Clear_Length_Equal_Zero_If_Empty ()
|
||||
{
|
||||
_sqList.Insert (1, 10);
|
||||
_sqList.Insert (2, 9);
|
||||
_sqList.Insert (3, 8);
|
||||
_sqList.Insert (4, 7);
|
||||
_sqList.Insert (5, 6);
|
||||
_sqList.Insert (6, 5);
|
||||
_sqList.Insert (7, 4);
|
||||
_sqList.Insert (8, 3);
|
||||
_sqList.Insert (9, 2);
|
||||
_sqList.Insert (10, 1);
|
||||
|
||||
Assert.Equal (10, _sqList.Length);
|
||||
|
||||
_sqList.Clear ();
|
||||
|
||||
Assert.Equal (0, _sqList.Length);
|
||||
}
|
||||
}
|
@ -1,12 +1,14 @@
|
||||
using System;
|
||||
|
||||
public sealed class Array<T>
|
||||
namespace _05_array
|
||||
{
|
||||
public sealed class Array<T> where T : IComparable<T>
|
||||
{
|
||||
private T[] _data;
|
||||
private int _capacity;
|
||||
private readonly int _capacity;
|
||||
private int _length;
|
||||
|
||||
public Array (int capacity)
|
||||
public Array(int capacity)
|
||||
{
|
||||
_data = new T[capacity];
|
||||
_capacity = capacity;
|
||||
@ -16,84 +18,99 @@ public sealed class Array<T>
|
||||
// length of list
|
||||
public int Length => _length;
|
||||
|
||||
// insert a new element at specified position (position start from 1)
|
||||
public void Insert (int position, T newElem)
|
||||
// insert a new element at specified index (index start from 0)
|
||||
public void Insert(int index, T newElem)
|
||||
{
|
||||
if (_length == _capacity)
|
||||
{
|
||||
throw new OutOfMemoryException ("List has no more space");
|
||||
throw new OutOfMemoryException("List has no more space");
|
||||
}
|
||||
|
||||
if (position < 1 || position > _length + 1)
|
||||
if (index < 0 || index > _length)
|
||||
{
|
||||
throw new IndexOutOfRangeException ("Position was outside the bounds of the list");
|
||||
throw new IndexOutOfRangeException("Index was outside the bounds of the list");
|
||||
}
|
||||
|
||||
// to loop array from last position until finding the target position
|
||||
if (position <= _length)
|
||||
// to loop array from end until finding the target index
|
||||
for (int k = _length; k > index; k--)
|
||||
{
|
||||
for (int k = _length - 1; k >= position - 1; k--)
|
||||
{
|
||||
_data[k + 1] = _data[k];
|
||||
_data[k] = _data[k - 1];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
_data[position - 1] = newElem;
|
||||
_data[index] = newElem;
|
||||
|
||||
_length++;
|
||||
}
|
||||
|
||||
// get an element (position start from 1)
|
||||
public T Find (int position)
|
||||
// get an element base on index
|
||||
public T Find(int index)
|
||||
{
|
||||
if (position < 0 || position > _length)
|
||||
if (index < 0 || index > _length - 1)
|
||||
{
|
||||
throw new IndexOutOfRangeException ("Position was outside the bounds of the list");
|
||||
}
|
||||
return _data[position - 1];
|
||||
throw new IndexOutOfRangeException("Index was outside the bounds of the list");
|
||||
}
|
||||
|
||||
// search the element which matches specified element and return its index (index start from 0)
|
||||
public int IndexOf (T elem)
|
||||
return _data[index];
|
||||
}
|
||||
|
||||
// search the node which matches specified value and return its index (index start from 0)
|
||||
public int IndexOf(T val)
|
||||
{
|
||||
if (_length == 0) return -1;
|
||||
if (_data[0].Equals (elem)) return 0;
|
||||
if (_data[_length - 1].Equals (elem)) return _length - 1;
|
||||
if (_data[0].Equals(val)) return 0;
|
||||
if (_data[_length - 1].CompareTo(val) == 0) return _length - 1;
|
||||
|
||||
int start = 0;
|
||||
int start = 1;
|
||||
while (start < _length - 1)
|
||||
{
|
||||
if (_data[start].Equals (elem)) return start;
|
||||
if (_data[start].CompareTo(val) == 0) return start;
|
||||
start++;
|
||||
continue;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// delete an element which is on the specified position (position start from 1)
|
||||
public T Delete (int position)
|
||||
// delete an node which is on the specified index
|
||||
public bool Delete(int index)
|
||||
{
|
||||
if (position < 1 || position > _length)
|
||||
if (index < 0 || index > _length - 1)
|
||||
{
|
||||
throw new IndexOutOfRangeException ("Position must be in the bound of list");
|
||||
throw new IndexOutOfRangeException("Index must be in the bound of list");
|
||||
}
|
||||
|
||||
var elem = _data[position - 1];
|
||||
for (int k = position; k < _length; k++)
|
||||
T deletedElem = _data[index];
|
||||
if (index < _length - 1)
|
||||
{
|
||||
_data[k - 1] = _data[k];
|
||||
for (int k = index; k < _length; k++)
|
||||
{
|
||||
_data[k] = _data[k + 1];
|
||||
}
|
||||
}
|
||||
|
||||
_length--;
|
||||
|
||||
return elem;
|
||||
return true;
|
||||
}
|
||||
|
||||
// delete an node
|
||||
public bool Delete(T val)
|
||||
{
|
||||
int index;
|
||||
for (index = 0; index < Length; index++)
|
||||
{
|
||||
if (_data[index].CompareTo(val) == 0) break;
|
||||
}
|
||||
|
||||
if (index >= Length) return false;
|
||||
|
||||
return Delete(index);
|
||||
}
|
||||
|
||||
// clear list
|
||||
public void Clear ()
|
||||
public void Clear()
|
||||
{
|
||||
_data = new T[_capacity];
|
||||
_length = 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
@ -6,10 +6,4 @@
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.0" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
45
csharp/06-linkedlist/LRUWithArray.cs
Normal file
45
csharp/06-linkedlist/LRUWithArray.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using _05_array;
|
||||
|
||||
namespace _06_linked_list
|
||||
{
|
||||
/// <summary>
|
||||
/// 使用数组实现LRU缓存淘汰算法
|
||||
/// </summary>
|
||||
public class LRUWithArray
|
||||
{
|
||||
private readonly int _capacity;
|
||||
|
||||
public LRUWithArray(int capacity)
|
||||
{
|
||||
_capacity = capacity;
|
||||
CachedList = new Array<int>(capacity);
|
||||
}
|
||||
|
||||
public Array<int> CachedList { get; }
|
||||
|
||||
public void Set(int val)
|
||||
{
|
||||
// 找出该值在缓存中的索引位置
|
||||
int idx = CachedList.IndexOf(val);
|
||||
|
||||
// 存在该缓存值
|
||||
if (idx != -1)
|
||||
{
|
||||
CachedList.Delete(idx);
|
||||
CachedList.Insert(0, val);
|
||||
return;
|
||||
}
|
||||
|
||||
// 不存在该缓存值
|
||||
if (CachedList.Length == _capacity)
|
||||
{
|
||||
// 缓存已满,删除最后一个元素
|
||||
CachedList.Delete(CachedList.Length - 1);
|
||||
}
|
||||
|
||||
// 将新缓存插入到表头
|
||||
CachedList.Insert(0, val);
|
||||
}
|
||||
}
|
||||
}
|
48
csharp/06-linkedlist/LRUWithLinkedList.cs
Normal file
48
csharp/06-linkedlist/LRUWithLinkedList.cs
Normal file
@ -0,0 +1,48 @@
|
||||
namespace _06_linked_list
|
||||
{
|
||||
/// <summary>
|
||||
/// 使用单链表实现LRU缓存淘汰算法
|
||||
/// </summary>
|
||||
public class LRUWithLinkedList
|
||||
{
|
||||
private readonly int _capacity;
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="capacity">缓存容量</param>
|
||||
public LRUWithLinkedList(int capacity = 10)
|
||||
{
|
||||
_capacity = capacity;
|
||||
}
|
||||
|
||||
public SingleLinkedList<int> CachedList { get; } = new SingleLinkedList<int>();
|
||||
|
||||
/// <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.Delete(CachedList.Length);
|
||||
}
|
||||
|
||||
// 将新缓存值插入到表头
|
||||
CachedList.Insert(1, val);
|
||||
}
|
||||
}
|
||||
}
|
8
csharp/06-linkedlist/LRU缓存实现思路.txt
Normal file
8
csharp/06-linkedlist/LRU缓存实现思路.txt
Normal file
@ -0,0 +1,8 @@
|
||||
实现LRU缓存淘汰算法思路:
|
||||
|
||||
维护一个有序单链表,越靠近链尾的数据是最早访问的。
|
||||
当有一个新的数据被访问时,
|
||||
1. 如果数据在缓存中,则将其从原位置删除,然后插入到表头;
|
||||
2. 如果数据不在缓存中,有两种情况:
|
||||
1) 链表未满,则将数据插入到表头;
|
||||
2) 链表已满,则删除尾结点,将新数据插入到表头。
|
163
csharp/06-linkedlist/SingleLinkedList.cs
Normal file
163
csharp/06-linkedlist/SingleLinkedList.cs
Normal file
@ -0,0 +1,163 @@
|
||||
using System;
|
||||
|
||||
namespace _06_linked_list
|
||||
{
|
||||
/// <summary>
|
||||
/// 单链表的插入、删除、清空、查找
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class SingleLinkedList<T> where T : IComparable<T>
|
||||
{
|
||||
public SingleLinkedList()
|
||||
{
|
||||
Head = new ListNode<T>(default(T));
|
||||
}
|
||||
|
||||
public SingleLinkedList(params T[] list)
|
||||
{
|
||||
Head = new ListNode<T>(default(T));
|
||||
if (list == null) return;
|
||||
|
||||
var p = Head;
|
||||
foreach (var item in list)
|
||||
{
|
||||
var q = new ListNode<T>(item);
|
||||
p.Next = q;
|
||||
p = q;
|
||||
}
|
||||
|
||||
Length = list.Length;
|
||||
}
|
||||
|
||||
// Head node
|
||||
public ListNode<T> First => Head.Next;
|
||||
public ListNode<T> Head { get; }
|
||||
|
||||
public int Length { get; private set; }
|
||||
|
||||
public ListNode<T> Insert(int position, T newElem)
|
||||
{
|
||||
if (position < 1 || position > Length + 1)
|
||||
{
|
||||
throw new IndexOutOfRangeException("Position must be in bound of list");
|
||||
}
|
||||
|
||||
var p = Head;
|
||||
|
||||
int j = 1;
|
||||
while (p != null && j < position)
|
||||
{
|
||||
p = p.Next;
|
||||
++j;
|
||||
}
|
||||
|
||||
var newNode = new ListNode<T>(newElem);
|
||||
newNode.Next = p.Next;
|
||||
p.Next = newNode;
|
||||
|
||||
Length++;
|
||||
|
||||
return newNode;
|
||||
}
|
||||
|
||||
public ListNode<T> Find(int position)
|
||||
{
|
||||
ListNode<T> p = First;
|
||||
int j = 1;
|
||||
|
||||
while (p != null && j < position)
|
||||
{
|
||||
p = p.Next;
|
||||
j++;
|
||||
}
|
||||
|
||||
if (p == null || j > position)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
public ListNode<T> Find(T elem)
|
||||
{
|
||||
ListNode<T> p = Head.Next;
|
||||
|
||||
while (p != null)
|
||||
{
|
||||
if (p.Value.CompareTo(elem) == 0) return p;
|
||||
|
||||
p = p.Next;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public ListNode<T> Delete(T value)
|
||||
{
|
||||
ListNode<T> cur = Head;
|
||||
while (cur.Next != null && cur.Next.Value.CompareTo(value) != 0)
|
||||
{
|
||||
cur = cur.Next;
|
||||
}
|
||||
|
||||
if (cur.Next == null) return null;
|
||||
|
||||
var q = cur.Next;
|
||||
cur.Next = q.Next;
|
||||
|
||||
Length--;
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
public ListNode<T> Delete(int position)
|
||||
{
|
||||
if (position < 1 || position > Length)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var p = First;
|
||||
int j = 1;
|
||||
while (p != null && j < position - 1)
|
||||
{
|
||||
p = p.Next;
|
||||
++j;
|
||||
}
|
||||
|
||||
var q = p.Next;
|
||||
p.Next = q.Next;
|
||||
|
||||
Length--;
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
var cur = Head;
|
||||
while (cur.Next != null)
|
||||
{
|
||||
var q = cur.Next;
|
||||
cur.Next = null;
|
||||
|
||||
cur = q;
|
||||
}
|
||||
|
||||
Length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public class ListNode<T>
|
||||
{
|
||||
public ListNode(T value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public T Value { get; }
|
||||
|
||||
public ListNode<T> Next { get; set; }
|
||||
}
|
||||
}
|
13
csharp/06-linkedlist/_06_linked_list.csproj
Normal file
13
csharp/06-linkedlist/_06_linked_list.csproj
Normal file
@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\05-array\_05_array.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
@ -1,63 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,320 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace _06_linked_list
|
||||
{
|
||||
/// <summary>
|
||||
/// 单链表的插入、删除、清空、查找
|
||||
/// 1. 链表反转
|
||||
/// 2. 环的检测
|
||||
/// 3. 两个有序链表的合并
|
||||
/// 4. 删除链表倒数第n个结点
|
||||
/// 5. 求链表的中间结点
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class SingleLinkedList<T> where T : IComparable<T>
|
||||
{
|
||||
public SingleLinkedList ()
|
||||
{
|
||||
Head = new LinkedListNode<T> (default (T));
|
||||
}
|
||||
|
||||
public SingleLinkedList (params T[] list)
|
||||
{
|
||||
Head = new LinkedListNode<T> (default (T));
|
||||
if (list == null) return;
|
||||
|
||||
var p = Head;
|
||||
foreach (var item in list)
|
||||
{
|
||||
var q = new LinkedListNode<T> (item);
|
||||
p.Next = q;
|
||||
p = q;
|
||||
}
|
||||
|
||||
Length = list.Length;
|
||||
}
|
||||
|
||||
// Head node
|
||||
public LinkedListNode<T> First => Head.Next;
|
||||
public LinkedListNode<T> Head { get; }
|
||||
|
||||
public int Length { get; private set; }
|
||||
|
||||
public LinkedListNode<T> Insert (int position, T newElem)
|
||||
{
|
||||
if (position < 1 || position > Length + 1)
|
||||
{
|
||||
throw new IndexOutOfRangeException ("Position must be in bound of list");
|
||||
}
|
||||
|
||||
var p = Head;
|
||||
|
||||
int j = 1;
|
||||
while (p != null && j < position)
|
||||
{
|
||||
p = p.Next;
|
||||
++j;
|
||||
}
|
||||
|
||||
var newNode = new LinkedListNode<T> (newElem);
|
||||
newNode.Next = p.Next;
|
||||
p.Next = newNode;
|
||||
|
||||
Length++;
|
||||
|
||||
return newNode;
|
||||
}
|
||||
|
||||
public LinkedListNode<T> Find (int position)
|
||||
{
|
||||
LinkedListNode<T> p = First;
|
||||
int j = 1;
|
||||
|
||||
while (p != null && j < position)
|
||||
{
|
||||
p = p.Next;
|
||||
j++;
|
||||
}
|
||||
|
||||
if (p == null || j > position)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
public LinkedListNode<T> Find (T elem)
|
||||
{
|
||||
LinkedListNode<T> p = Head.Next;
|
||||
|
||||
while (p != null)
|
||||
{
|
||||
if (p.Value.CompareTo (elem) == 0) return p;
|
||||
|
||||
p = p.Next;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public LinkedListNode<T> Delete (T value)
|
||||
{
|
||||
LinkedListNode<T> cur = Head;
|
||||
while (cur.Next != null && cur.Next.Value.CompareTo (value) != 0)
|
||||
{
|
||||
cur = cur.Next;
|
||||
}
|
||||
|
||||
if (cur.Next == null) return null;
|
||||
|
||||
var q = cur.Next;
|
||||
cur.Next = q.Next;
|
||||
|
||||
Length--;
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
public LinkedListNode<T> Delete (int position)
|
||||
{
|
||||
if (position < 1 || position > Length)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var p = First;
|
||||
int j = 1;
|
||||
while (p != null && j < position - 1)
|
||||
{
|
||||
p = p.Next;
|
||||
++j;
|
||||
}
|
||||
|
||||
var q = p.Next;
|
||||
p.Next = q.Next;
|
||||
|
||||
Length--;
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
public void Clear ()
|
||||
{
|
||||
var cur = Head;
|
||||
while (cur.Next != null)
|
||||
{
|
||||
var q = cur.Next;
|
||||
cur.Next = null;
|
||||
|
||||
cur = q;
|
||||
}
|
||||
|
||||
Length = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// reverse current list
|
||||
/// </summary>
|
||||
public void Reverse ()
|
||||
{
|
||||
if (Length <= 1) return;
|
||||
|
||||
LinkedListNode<T> p = First;
|
||||
LinkedListNode<T> q = First.Next;
|
||||
|
||||
LinkedListNode<T> r = null;
|
||||
|
||||
p.Next = null;
|
||||
while (q != null)
|
||||
{
|
||||
r = q.Next;
|
||||
|
||||
q.Next = p;
|
||||
p = q;
|
||||
q = r;
|
||||
}
|
||||
|
||||
Head.Next = p;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 环的检测
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 用快慢两个指针,快指针每次移动2个结点,慢指针每次移动1个结点,当两个指针相遇时,说明存在环。
|
||||
/// LeetCode 编号: 141
|
||||
/// </remarks>
|
||||
public bool HasCycle ()
|
||||
{
|
||||
if (Length == 0) return false;
|
||||
|
||||
var slow = Head.Next;
|
||||
var fast = Head.Next.Next;
|
||||
|
||||
while (fast != null && slow != null && fast != slow)
|
||||
{
|
||||
fast = fast.Next?.Next;
|
||||
slow = slow.Next;
|
||||
}
|
||||
|
||||
bool ret = fast == slow;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 合并两个有序链表(从小到大)
|
||||
/// </summary>
|
||||
/// <remarks>LeetCode 编号: 21</remarks>
|
||||
/// <param name="list"></param>
|
||||
/// <returns></returns>
|
||||
public SingleLinkedList<T> Merge (SingleLinkedList<T> list)
|
||||
{
|
||||
if (list == null) return null;
|
||||
|
||||
var root = new SingleLinkedList<T> ();
|
||||
|
||||
LinkedListNode<T> pointer = root.Head; // 总是向新链表的尾结点
|
||||
|
||||
var head1 = list.First;
|
||||
var head2 = this.First;
|
||||
|
||||
while (head1 != null && head2 != null)
|
||||
{
|
||||
if (head1.Value.CompareTo (head2.Value) < 0)
|
||||
{
|
||||
pointer.Next = head1;
|
||||
head1 = head1.Next;
|
||||
}
|
||||
else
|
||||
{
|
||||
pointer.Next = head2;
|
||||
head2 = head2.Next;
|
||||
}
|
||||
|
||||
pointer = pointer.Next; // 指向尾结点
|
||||
}
|
||||
|
||||
if (head1 != null)
|
||||
{
|
||||
pointer.Next = head1;
|
||||
}
|
||||
|
||||
if (head2 != null)
|
||||
{
|
||||
pointer.Next = head2;
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除倒数第n个结点
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 用快慢两个指针,快指针比慢指针早n个结点,然后再同步移动两个指针,当快指针指向尾结点时,慢指针就是将要删除的结点
|
||||
/// LeetCode 编号: 19
|
||||
/// </remarks>
|
||||
/// <param name="n"></param>
|
||||
public void RemoveNthNodeFromEnd (int n)
|
||||
{
|
||||
if (n < 1 || n > Length) return;
|
||||
|
||||
LinkedListNode<T> preNode = Head;
|
||||
LinkedListNode<T> curNode = Head;
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
curNode = curNode.Next;
|
||||
}
|
||||
|
||||
if (curNode == null) return;
|
||||
|
||||
while (curNode.Next != null)
|
||||
{
|
||||
preNode = preNode.Next;
|
||||
curNode = curNode.Next;
|
||||
}
|
||||
|
||||
preNode.Next = preNode.Next.Next;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 链表的中间结点
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 思路: 利用快慢指针,快指针步长2,慢指针步长1,当快指针到达尾结点时,慢指针正好到达中间结点
|
||||
/// LeetCode 编号: 876
|
||||
/// </remarks>
|
||||
/// <returns></returns>
|
||||
public LinkedListNode<T> FindMiddleNode ()
|
||||
{
|
||||
if (First?.Next == null) return null;
|
||||
|
||||
LinkedListNode<T> slowPointer = First;
|
||||
LinkedListNode<T> fastPointer = First.Next;
|
||||
|
||||
while (fastPointer.Next?.Next != null)
|
||||
{
|
||||
fastPointer = fastPointer.Next.Next;
|
||||
slowPointer = slowPointer.Next;
|
||||
}
|
||||
|
||||
slowPointer = slowPointer.Next;
|
||||
return slowPointer;
|
||||
}
|
||||
}
|
||||
|
||||
public class LinkedListNode<T>
|
||||
{
|
||||
private T _value;
|
||||
|
||||
public LinkedListNode (T value)
|
||||
{
|
||||
_value = value;
|
||||
}
|
||||
|
||||
public T Value => _value;
|
||||
public LinkedListNode<T> Next { get; set; }
|
||||
}
|
||||
}
|
172
csharp/07-linkedlist/_07_linkedlist/SingleLinkedListAlgo.cs
Normal file
172
csharp/07-linkedlist/_07_linkedlist/SingleLinkedListAlgo.cs
Normal file
@ -0,0 +1,172 @@
|
||||
using System;
|
||||
using _06_linked_list;
|
||||
|
||||
namespace _07_linkedlist
|
||||
{
|
||||
/// <summary>
|
||||
/// 单链表常用算法操作
|
||||
/// 1. 链表反转
|
||||
/// 2. 环的检测
|
||||
/// 3. 两个有序链表的合并
|
||||
/// 4. 删除链表倒数第n个结点
|
||||
/// 5. 求链表的中间结点
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class SingleLinkedListAlgo<T> : SingleLinkedList<T> where T : IComparable<T>
|
||||
{
|
||||
public SingleLinkedListAlgo(params T[] list) : base(list)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 链表反转
|
||||
/// </summary>
|
||||
public void Reverse()
|
||||
{
|
||||
if (Length <= 1) return;
|
||||
|
||||
ListNode<T> p = First;
|
||||
ListNode<T> q = First.Next;
|
||||
|
||||
ListNode<T> r = null;
|
||||
|
||||
p.Next = null;
|
||||
while (q != null)
|
||||
{
|
||||
r = q.Next;
|
||||
|
||||
q.Next = p;
|
||||
p = q;
|
||||
q = r;
|
||||
}
|
||||
|
||||
Head.Next = p;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 环的检测
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 用快慢两个指针,快指针每次移动2个结点,慢指针每次移动1个结点,当两个指针相遇时,说明存在环。
|
||||
/// LeetCode 编号: 141
|
||||
/// </remarks>
|
||||
public bool HasCycle()
|
||||
{
|
||||
if (Length == 0) return false;
|
||||
|
||||
var slow = Head.Next;
|
||||
var fast = Head.Next.Next;
|
||||
|
||||
while (fast != null && slow != null && fast != slow)
|
||||
{
|
||||
fast = fast.Next?.Next;
|
||||
slow = slow.Next;
|
||||
}
|
||||
|
||||
bool ret = fast == slow;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 合并两个有序链表(从小到大)
|
||||
/// </summary>
|
||||
/// <remarks>LeetCode 编号: 21</remarks>
|
||||
/// <param name="listAlgo"></param>
|
||||
/// <returns></returns>
|
||||
public SingleLinkedListAlgo<T> Merge(SingleLinkedListAlgo<T> listAlgo)
|
||||
{
|
||||
if (listAlgo == null) return null;
|
||||
|
||||
var root = new SingleLinkedListAlgo<T>();
|
||||
|
||||
ListNode<T> pointer = root.Head; // 总是向新链表的尾结点
|
||||
|
||||
var head1 = listAlgo.First;
|
||||
var head2 = this.First;
|
||||
|
||||
while (head1 != null && head2 != null)
|
||||
{
|
||||
if (head1.Value.CompareTo(head2.Value) < 0)
|
||||
{
|
||||
pointer.Next = head1;
|
||||
head1 = head1.Next;
|
||||
}
|
||||
else
|
||||
{
|
||||
pointer.Next = head2;
|
||||
head2 = head2.Next;
|
||||
}
|
||||
|
||||
pointer = pointer.Next; // 指向尾结点
|
||||
}
|
||||
|
||||
if (head1 != null)
|
||||
{
|
||||
pointer.Next = head1;
|
||||
}
|
||||
|
||||
if (head2 != null)
|
||||
{
|
||||
pointer.Next = head2;
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除倒数第n个结点
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 用快慢两个指针,快指针比慢指针早n个结点,然后再同步移动两个指针,当快指针指向尾结点时,慢指针就是将要删除的结点
|
||||
/// LeetCode 编号: 19
|
||||
/// </remarks>
|
||||
/// <param name="n"></param>
|
||||
public void RemoveNthNodeFromEnd(int n)
|
||||
{
|
||||
if (n < 1 || n > Length) return;
|
||||
|
||||
ListNode<T> preNode = Head;
|
||||
ListNode<T> curNode = Head;
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
curNode = curNode.Next;
|
||||
}
|
||||
|
||||
if (curNode == null) return;
|
||||
|
||||
while (curNode.Next != null)
|
||||
{
|
||||
preNode = preNode.Next;
|
||||
curNode = curNode.Next;
|
||||
}
|
||||
|
||||
preNode.Next = preNode.Next.Next;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 链表的中间结点
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 思路: 利用快慢指针,快指针步长2,慢指针步长1,当快指针到达尾结点时,慢指针正好到达中间结点
|
||||
/// LeetCode 编号: 876
|
||||
/// </remarks>
|
||||
/// <returns></returns>
|
||||
public ListNode<T> FindMiddleNode()
|
||||
{
|
||||
if (First?.Next == null) return null;
|
||||
|
||||
ListNode<T> slowPointer = First;
|
||||
ListNode<T> fastPointer = First.Next;
|
||||
|
||||
while (fastPointer.Next?.Next != null)
|
||||
{
|
||||
fastPointer = fastPointer.Next.Next;
|
||||
slowPointer = slowPointer.Next;
|
||||
}
|
||||
|
||||
slowPointer = slowPointer.Next;
|
||||
return slowPointer;
|
||||
}
|
||||
}
|
||||
}
|
11
csharp/07-linkedlist/_07_linkedlist/_07_linkedlist.csproj
Normal file
11
csharp/07-linkedlist/_07_linkedlist/_07_linkedlist.csproj
Normal file
@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\06-linkedlist\_06_linked_list.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
231
csharp/Tests/_05_array_tests/Array.Tests.cs
Normal file
231
csharp/Tests/_05_array_tests/Array.Tests.cs
Normal file
@ -0,0 +1,231 @@
|
||||
using System;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
using _05_array;
|
||||
|
||||
namespace _05_array_tests
|
||||
{
|
||||
public class ArrayTests
|
||||
{
|
||||
private readonly Array<int> _sqList;
|
||||
private readonly ITestOutputHelper _output;
|
||||
|
||||
public ArrayTests(ITestOutputHelper output)
|
||||
{
|
||||
_sqList = new Array<int>(10);
|
||||
_output = output;
|
||||
}
|
||||
|
||||
private void PrintList()
|
||||
{
|
||||
for (int idx = 0; idx < _sqList.Length; idx++)
|
||||
{
|
||||
var elem = _sqList.Find(idx);
|
||||
_output.WriteLine(elem.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Length_Equal_1_After_InsertOneElement()
|
||||
{
|
||||
_sqList.Insert(0, 1);
|
||||
Assert.True(_sqList.Length == 1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Insert_ThrowIndexOutOfRangeException_When_Index_GreaterThan_Length()
|
||||
{
|
||||
_sqList.Insert(0, 1);
|
||||
Exception ex = Assert.Throws<IndexOutOfRangeException>(() => _sqList.Insert(3, 2));
|
||||
Assert.IsType<IndexOutOfRangeException>(ex);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Insert_ThrowIndexOutOfRangeException_When_Index_LessThan_Zero()
|
||||
{
|
||||
Exception ex = Assert.Throws<IndexOutOfRangeException>(() => _sqList.Insert(-1, 1));
|
||||
Assert.IsType<IndexOutOfRangeException>(ex);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Insert_ThrowIndexOutOfRangeException_When_List_Is_Full()
|
||||
{
|
||||
_sqList.Insert(0, 11);
|
||||
_sqList.Insert(1, 10);
|
||||
_sqList.Insert(2, 9);
|
||||
_sqList.Insert(3, 8);
|
||||
_sqList.Insert(4, 7);
|
||||
_sqList.Insert(5, 6);
|
||||
_sqList.Insert(6, 5);
|
||||
_sqList.Insert(7, 4);
|
||||
_sqList.Insert(8, 3);
|
||||
_sqList.Insert(9, 2);
|
||||
|
||||
PrintList();
|
||||
|
||||
Exception ex = Assert.Throws<OutOfMemoryException>(() => _sqList.Insert(10, 101));
|
||||
Assert.IsType<OutOfMemoryException>(ex);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Delete_ThrowIndexOutOfRangeException_When_Index_LessThan_Zero()
|
||||
{
|
||||
Exception ex = Assert.Throws<IndexOutOfRangeException>(() => _sqList.Delete(-1));
|
||||
Assert.IsType<IndexOutOfRangeException>(ex);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Delete_ThrowIndexOutOfRangeException_When_Index_GreaterThan_Length()
|
||||
{
|
||||
_sqList.Insert(0, 11);
|
||||
_sqList.Insert(1, 22);
|
||||
Exception ex = Assert.Throws<IndexOutOfRangeException>(() => _sqList.Delete(3));
|
||||
Assert.IsType<IndexOutOfRangeException>(ex);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Delete_First_Element_Success()
|
||||
{
|
||||
_sqList.Insert(0, 100);
|
||||
_sqList.Insert(1, 11);
|
||||
_sqList.Insert(2, 22);
|
||||
|
||||
bool ret = _sqList.Delete(1);
|
||||
Assert.True(ret);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Delete_Last_Element_Success()
|
||||
{
|
||||
_sqList.Insert(0, 100);
|
||||
_sqList.Insert(1, 11);
|
||||
_sqList.Insert(2, 22);
|
||||
_sqList.Insert(3, 33);
|
||||
|
||||
bool ret = _sqList.Delete(3);
|
||||
Assert.True(ret);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Delete_Middle_Element()
|
||||
{
|
||||
_sqList.Insert(0, 100);
|
||||
_sqList.Insert(1, 11);
|
||||
_sqList.Insert(2, 22);
|
||||
_sqList.Insert(3, 33);
|
||||
|
||||
bool ret = _sqList.Delete(2);
|
||||
Assert.True(ret);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Find_ThrowsIndexOutOfRangeException_When_Index_LessThan_Zero()
|
||||
{
|
||||
_sqList.Insert(0, 100);
|
||||
_sqList.Insert(1, 11);
|
||||
_sqList.Insert(2, 22);
|
||||
_sqList.Insert(3, 33);
|
||||
|
||||
Exception ex = Assert.Throws<IndexOutOfRangeException>(() => _sqList.Find(-1));
|
||||
Assert.IsType<IndexOutOfRangeException>(ex);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Find_ThrowsIndexOutOfRangeException_When_Index_GreaterThan_Length()
|
||||
{
|
||||
_sqList.Insert(0, 100);
|
||||
_sqList.Insert(1, 11);
|
||||
_sqList.Insert(2, 22);
|
||||
_sqList.Insert(3, 33);
|
||||
|
||||
Exception ex = Assert.Throws<IndexOutOfRangeException>(() => _sqList.Find(4));
|
||||
Assert.IsType<IndexOutOfRangeException>(ex);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Find_Last_Position_Return_33()
|
||||
{
|
||||
_sqList.Insert(0, 100);
|
||||
_sqList.Insert(1, 11);
|
||||
_sqList.Insert(2, 22);
|
||||
_sqList.Insert(3, 33);
|
||||
|
||||
var elem = _sqList.Find(3);
|
||||
|
||||
Assert.Equal(33, elem);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Find_First_Element_Return_11()
|
||||
{
|
||||
_sqList.Insert(0, 100);
|
||||
_sqList.Insert(1, 11);
|
||||
_sqList.Insert(2, 22);
|
||||
_sqList.Insert(3, 33);
|
||||
|
||||
var elem = _sqList.Find(1);
|
||||
|
||||
Assert.Equal(11, elem);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IndexOf_Return_Negative_1_When_Element_Not_Exist()
|
||||
{
|
||||
_sqList.Insert(0, 100);
|
||||
_sqList.Insert(1, 11);
|
||||
_sqList.Insert(2, 22);
|
||||
_sqList.Insert(3, 33);
|
||||
|
||||
var elem = _sqList.IndexOf(55);
|
||||
|
||||
Assert.Equal(-1, elem);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IndexOf_Return_First_Index()
|
||||
{
|
||||
_sqList.Insert(0, 100);
|
||||
_sqList.Insert(1, 11);
|
||||
_sqList.Insert(2, 22);
|
||||
_sqList.Insert(3, 33);
|
||||
|
||||
var elem = _sqList.IndexOf(100);
|
||||
|
||||
Assert.Equal(0, elem);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IndexOf_Return_Last_Index()
|
||||
{
|
||||
_sqList.Insert(0, 100);
|
||||
_sqList.Insert(1, 11);
|
||||
_sqList.Insert(2, 22);
|
||||
_sqList.Insert(3, 33);
|
||||
|
||||
var elem = _sqList.IndexOf(33);
|
||||
|
||||
Assert.Equal(3, elem);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Clear_Then_Length_Equal_Zero()
|
||||
{
|
||||
_sqList.Insert(0, 100);
|
||||
_sqList.Insert(1, 10);
|
||||
_sqList.Insert(2, 9);
|
||||
_sqList.Insert(3, 8);
|
||||
_sqList.Insert(4, 7);
|
||||
_sqList.Insert(5, 6);
|
||||
_sqList.Insert(6, 5);
|
||||
_sqList.Insert(7, 4);
|
||||
_sqList.Insert(8, 3);
|
||||
_sqList.Insert(9, 2);
|
||||
|
||||
Assert.Equal(10, _sqList.Length);
|
||||
|
||||
_sqList.Clear();
|
||||
|
||||
Assert.Equal(0, _sqList.Length);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
|
||||
<AssemblyName>05_array_tests</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@ -12,4 +14,8 @@
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\05-array\_05_array.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
@ -1,10 +1,11 @@
|
||||
using System;
|
||||
using _06_linked_list;
|
||||
|
||||
namespace _06_linked_list
|
||||
namespace _06_linkedlist_tests
|
||||
{
|
||||
public class BaseLinkedListTests
|
||||
{
|
||||
protected void PrintList<T> (SingleLinkedList<T> list) where T : IComparable<T>
|
||||
protected void PrintLinkedList<T> (SingleLinkedList<T> list) where T : IComparable<T>
|
||||
{
|
||||
if (list == null) return;
|
||||
|
82
csharp/Tests/_06_linkedlist_tests/LRUWithArray.Tests.cs
Normal file
82
csharp/Tests/_06_linkedlist_tests/LRUWithArray.Tests.cs
Normal file
@ -0,0 +1,82 @@
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
using _05_array;
|
||||
using _06_linked_list;
|
||||
|
||||
namespace _06_linkedlist_tests
|
||||
{
|
||||
public class LRUWithArrayTests
|
||||
{
|
||||
private ITestOutputHelper _output;
|
||||
|
||||
public LRUWithArrayTests(ITestOutputHelper output)
|
||||
{
|
||||
_output = output;
|
||||
}
|
||||
|
||||
private void PrintList(Array<int> list)
|
||||
{
|
||||
if (list == null) return;
|
||||
for (int idx = 0; idx < list.Length; idx++)
|
||||
{
|
||||
_output.WriteLine(list.Find(idx).ToString());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LRU_Set_Value_When_Not_Existed()
|
||||
{
|
||||
var lru = new LRUWithArray(5);
|
||||
|
||||
lru.Set(1);
|
||||
lru.Set(3);
|
||||
lru.Set(5);
|
||||
lru.Set(7);
|
||||
lru.Set(9);
|
||||
|
||||
var list = lru.CachedList;
|
||||
|
||||
PrintList(list);
|
||||
|
||||
Assert.Equal(9, list.Find(0));
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void LRU_Set_Value_When_Existed()
|
||||
{
|
||||
var lru = new LRUWithArray(5);
|
||||
|
||||
lru.Set(1);
|
||||
lru.Set(3);
|
||||
lru.Set(5);
|
||||
lru.Set(7);
|
||||
lru.Set(3);
|
||||
|
||||
var list = lru.CachedList;
|
||||
|
||||
PrintList(list);
|
||||
|
||||
Assert.Equal(3, list.Find(0));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LRU_Set_Value_When_Full()
|
||||
{
|
||||
var lru = new LRUWithArray(5);
|
||||
|
||||
lru.Set(1);
|
||||
lru.Set(3);
|
||||
lru.Set(5);
|
||||
lru.Set(7);
|
||||
lru.Set(9);
|
||||
lru.Set(8);
|
||||
|
||||
var list = lru.CachedList;
|
||||
|
||||
PrintList(list);
|
||||
|
||||
Assert.Equal(8, list.Find(0));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,14 +1,15 @@
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
using _06_linked_list;
|
||||
|
||||
namespace _06_linked_list
|
||||
namespace _06_linkedlist_tests
|
||||
{
|
||||
public class LRULinkedListTests : BaseLinkedListTests
|
||||
public class LRUWithLinkedListTests : BaseLinkedListTests
|
||||
{
|
||||
[Fact]
|
||||
public void LRU_Set_Value_When_Not_Existed()
|
||||
{
|
||||
var lru = new LRULinkedList();
|
||||
var lru = new LRUWithLinkedList();
|
||||
|
||||
lru.Set(1);
|
||||
lru.Set(3);
|
||||
@ -16,9 +17,9 @@ namespace _06_linked_list
|
||||
lru.Set(7);
|
||||
lru.Set(9);
|
||||
|
||||
var list = lru.GetCachedList();
|
||||
var list = lru.CachedList;
|
||||
|
||||
PrintList(list);
|
||||
PrintLinkedList(list);
|
||||
|
||||
Assert.Equal(9, list.First.Value);
|
||||
}
|
||||
@ -26,7 +27,7 @@ namespace _06_linked_list
|
||||
[Fact]
|
||||
public void LRU_Set_Value_When_Existed()
|
||||
{
|
||||
var lru = new LRULinkedList();
|
||||
var lru = new LRUWithLinkedList();
|
||||
|
||||
lru.Set(1);
|
||||
lru.Set(3);
|
||||
@ -34,9 +35,9 @@ namespace _06_linked_list
|
||||
lru.Set(7);
|
||||
lru.Set(3);
|
||||
|
||||
var list = lru.GetCachedList();
|
||||
var list = lru.CachedList;
|
||||
|
||||
PrintList(list);
|
||||
PrintLinkedList(list);
|
||||
|
||||
Assert.Equal(3, list.First.Value);
|
||||
}
|
||||
@ -44,7 +45,7 @@ namespace _06_linked_list
|
||||
[Fact]
|
||||
public void LRU_Set_Value_When_Full()
|
||||
{
|
||||
var lru = new LRULinkedList(5);
|
||||
var lru = new LRUWithLinkedList(5);
|
||||
|
||||
lru.Set(1);
|
||||
lru.Set(3);
|
||||
@ -53,9 +54,9 @@ namespace _06_linked_list
|
||||
lru.Set(9);
|
||||
lru.Set(8);
|
||||
|
||||
var list = lru.GetCachedList();
|
||||
var list = lru.CachedList;
|
||||
|
||||
PrintList(list);
|
||||
PrintLinkedList(list);
|
||||
|
||||
Assert.Equal(8, list.First.Value);
|
||||
}
|
@ -1,8 +1,9 @@
|
||||
using System;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
using _06_linked_list;
|
||||
|
||||
namespace _06_linked_list
|
||||
namespace _06_linkedlist_tests
|
||||
{
|
||||
public class SingleLinkedListTests : BaseLinkedListTests
|
||||
{
|
||||
@ -11,7 +12,7 @@ namespace _06_linked_list
|
||||
{
|
||||
var list = new SingleLinkedList<string>("The", "Quick", "Brown");
|
||||
|
||||
PrintList(list);
|
||||
PrintLinkedList(list);
|
||||
|
||||
Assert.Equal(3, list.Length);
|
||||
}
|
||||
@ -33,7 +34,7 @@ namespace _06_linked_list
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Find_Return_Null_When_Postion_LessThan_1()
|
||||
public void Find_Return_Null_When_Position_LessThan_1()
|
||||
{
|
||||
var list = new SingleLinkedList<string>("The", "Quick", "Brown");
|
||||
|
||||
@ -42,7 +43,7 @@ namespace _06_linked_list
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Find_Return_Null_When_Postion_GreaterThan_Length()
|
||||
public void Find_Return_Null_When_Position_GreaterThan_Length()
|
||||
{
|
||||
var list = new SingleLinkedList<string>("The", "Quick", "Brown");
|
||||
|
||||
@ -51,7 +52,7 @@ namespace _06_linked_list
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Find_Return_Correct_When_Postion_Valid()
|
||||
public void Find_Return_Correct_When_Position_Valid()
|
||||
{
|
||||
var list = new SingleLinkedList<string>("The", "Quick", "Brown");
|
||||
|
||||
@ -60,7 +61,7 @@ namespace _06_linked_list
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Delete_Return_Null_When_Postion_LessThan_1()
|
||||
public void Delete_Return_Null_When_Position_LessThan_1()
|
||||
{
|
||||
var list = new SingleLinkedList<string>("The", "Quick", "Brown");
|
||||
|
||||
@ -69,7 +70,7 @@ namespace _06_linked_list
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Delete_Return_Null_When_Postion_GreaterThan_Length()
|
||||
public void Delete_Return_Null_When_Position_GreaterThan_Length()
|
||||
{
|
||||
var list = new SingleLinkedList<string>("The", "Quick", "Brown");
|
||||
|
||||
@ -85,7 +86,7 @@ namespace _06_linked_list
|
||||
|
||||
var deletedNode = list.Delete("over");
|
||||
|
||||
PrintList(list);
|
||||
PrintLinkedList(list);
|
||||
|
||||
Assert.Equal("over", deletedNode.Value);
|
||||
Assert.Equal(8, list.Length);
|
||||
@ -99,7 +100,7 @@ namespace _06_linked_list
|
||||
|
||||
var deletedNode = list.Delete("hello");
|
||||
|
||||
PrintList(list);
|
||||
PrintLinkedList(list);
|
||||
|
||||
Assert.Null(deletedNode);
|
||||
Assert.Equal(9, list.Length);
|
||||
@ -113,7 +114,7 @@ namespace _06_linked_list
|
||||
|
||||
var deletedNode = list.Delete("The");
|
||||
|
||||
PrintList(list);
|
||||
PrintLinkedList(list);
|
||||
|
||||
Assert.Equal("The", deletedNode.Value);
|
||||
Assert.Equal(8, list.Length);
|
||||
@ -127,7 +128,7 @@ namespace _06_linked_list
|
||||
|
||||
var deletedNode = list.Delete("dog");
|
||||
|
||||
PrintList(list);
|
||||
PrintLinkedList(list);
|
||||
|
||||
Assert.Equal("dog", deletedNode.Value);
|
||||
Assert.Equal(8, list.Length);
|
||||
@ -141,7 +142,7 @@ namespace _06_linked_list
|
||||
|
||||
var node = list.Delete(3);
|
||||
|
||||
PrintList(list);
|
||||
PrintLinkedList(list);
|
||||
|
||||
Assert.Equal("Brown", node.Value);
|
||||
Assert.Equal(8, list.Length);
|
||||
@ -167,143 +168,5 @@ namespace _06_linked_list
|
||||
Assert.Null(list.First);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Reverse_When_List_Is_Empty()
|
||||
{
|
||||
var list = new SingleLinkedList<string>();
|
||||
|
||||
list.Reverse();
|
||||
|
||||
PrintList(list);
|
||||
|
||||
Assert.Null(list.First);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Reverse_When_List_Has_Many_Elements()
|
||||
{
|
||||
var list = new SingleLinkedList<string>("The", "Quick", "Brown", "Fox", "jumps", "over", "the", "lazy",
|
||||
"dog");
|
||||
|
||||
list.Reverse();
|
||||
|
||||
PrintList(list);
|
||||
|
||||
Assert.True(list.First.Value == "dog");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HasCycle_List_Empty()
|
||||
{
|
||||
var list = new SingleLinkedList<string>("The", "Quick", "Brown", "Fox", "jumps", "over", "the", "lazy",
|
||||
"dog");
|
||||
|
||||
bool hasCycle = list.HasCycle();
|
||||
|
||||
Assert.False(hasCycle);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HasCycle_False_When_List_Length_1()
|
||||
{
|
||||
var list = new SingleLinkedList<string>("The");
|
||||
|
||||
bool hasCycle = list.HasCycle();
|
||||
|
||||
Assert.False(hasCycle);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HasCycle_False_When_List_Length_2()
|
||||
{
|
||||
var list = new SingleLinkedList<string>("The", "Quick");
|
||||
|
||||
bool hasCycle = list.HasCycle();
|
||||
|
||||
Assert.False(hasCycle);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HasCycle_True_When_List_Length_2()
|
||||
{
|
||||
var list = new SingleLinkedList<string>();
|
||||
|
||||
var firstNode = list.Insert(1, "The");
|
||||
var secondNode = list.Insert(2, "Quick");
|
||||
|
||||
secondNode.Next = firstNode;
|
||||
|
||||
bool hasCycle = list.HasCycle();
|
||||
|
||||
Assert.True(hasCycle);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HasCycle_False()
|
||||
{
|
||||
var linkList =
|
||||
new SingleLinkedList<string>("The", "Quick", "Brown", "fox", "jumps", "over", "the", "lazy", "dog");
|
||||
|
||||
bool hasCycle = linkList.HasCycle();
|
||||
|
||||
Assert.False(hasCycle);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HasCycle_True()
|
||||
{
|
||||
var list = new SingleLinkedList<string>();
|
||||
|
||||
// 初始化一个具有环的链表
|
||||
list.Insert(1, "The");
|
||||
list.Insert(2, "Quick");
|
||||
list.Insert(3, "Brown");
|
||||
var fourthNode = list.Insert(4, "fox");
|
||||
list.Insert(5, "jumps");
|
||||
list.Insert(6, "over");
|
||||
list.Insert(7, "the");
|
||||
list.Insert(8, "lazy");
|
||||
var last = list.Insert(9, "dog");
|
||||
|
||||
last.Next = fourthNode;
|
||||
|
||||
bool hasCycle = list.HasCycle();
|
||||
|
||||
Assert.True(hasCycle);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Merge()
|
||||
{
|
||||
var list1 = new SingleLinkedList<int>(1, 2, 4);
|
||||
var list2 = new SingleLinkedList<int>(1, 3, 4);
|
||||
|
||||
var list3 = list1.Merge(list2);
|
||||
|
||||
PrintList(list3);
|
||||
|
||||
Assert.True(list1.First.Next.Next.Value == 2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Remove_2th_Node_From_End()
|
||||
{
|
||||
var list = new SingleLinkedList<int>(1, 2, 3, 4, 5);
|
||||
list.RemoveNthNodeFromEnd(2);
|
||||
|
||||
PrintList(list);
|
||||
|
||||
Assert.True(list.First.Next.Next.Next.Value == 5);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FindMiddleNode()
|
||||
{
|
||||
var list = new SingleLinkedList<int>(1, 2, 3, 4, 5);
|
||||
|
||||
LinkedListNode<int> middleNode = list.FindMiddleNode();
|
||||
|
||||
Assert.True(middleNode.Value == 3);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
<RootNamespace>_06_linkedlist_tests</RootNamespace>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.0" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\05-array\_05_array.csproj" />
|
||||
<ProjectReference Include="..\..\06-linkedlist\_06_linked_list.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
150
csharp/Tests/_07_linkedlist_tests/SingleLinkedListAlgo.Tests.cs
Normal file
150
csharp/Tests/_07_linkedlist_tests/SingleLinkedListAlgo.Tests.cs
Normal file
@ -0,0 +1,150 @@
|
||||
using System;
|
||||
using Xunit;
|
||||
using _06_linkedlist_tests;
|
||||
using _06_linked_list;
|
||||
using _07_linkedlist;
|
||||
|
||||
namespace _07_linkedlist_tests
|
||||
{
|
||||
public class SingleLinkedListAlgoTests : BaseLinkedListTests
|
||||
{
|
||||
[Fact]
|
||||
public void Reverse_When_List_Is_Empty()
|
||||
{
|
||||
var list = new SingleLinkedListAlgo<string>();
|
||||
|
||||
list.Reverse();
|
||||
|
||||
PrintLinkedList(list);
|
||||
|
||||
Assert.Null(list.First);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Reverse_When_List_Has_Many_Elements()
|
||||
{
|
||||
var list = new SingleLinkedListAlgo<string>("The", "Quick", "Brown", "Fox", "jumps", "over", "the", "lazy",
|
||||
"dog");
|
||||
|
||||
list.Reverse();
|
||||
|
||||
PrintLinkedList(list);
|
||||
|
||||
Assert.True(list.First.Value == "dog");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HasCycle_List_Empty()
|
||||
{
|
||||
var list = new SingleLinkedListAlgo<string>("The", "Quick", "Brown", "Fox", "jumps", "over", "the", "lazy",
|
||||
"dog");
|
||||
|
||||
bool hasCycle = list.HasCycle();
|
||||
|
||||
Assert.False(hasCycle);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HasCycle_False_When_List_Length_1()
|
||||
{
|
||||
var list = new SingleLinkedListAlgo<string>("The");
|
||||
|
||||
bool hasCycle = list.HasCycle();
|
||||
|
||||
Assert.False(hasCycle);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HasCycle_False_When_List_Length_2()
|
||||
{
|
||||
var list = new SingleLinkedListAlgo<string>("The", "Quick");
|
||||
|
||||
bool hasCycle = list.HasCycle();
|
||||
|
||||
Assert.False(hasCycle);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HasCycle_True_When_List_Length_2()
|
||||
{
|
||||
var list = new SingleLinkedListAlgo<string>();
|
||||
|
||||
var firstNode = list.Insert(1, "The");
|
||||
var secondNode = list.Insert(2, "Quick");
|
||||
|
||||
secondNode.Next = firstNode;
|
||||
|
||||
bool hasCycle = list.HasCycle();
|
||||
|
||||
Assert.True(hasCycle);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HasCycle_False()
|
||||
{
|
||||
var linkList =
|
||||
new SingleLinkedListAlgo<string>("The", "Quick", "Brown", "fox", "jumps", "over", "the", "lazy", "dog");
|
||||
|
||||
bool hasCycle = linkList.HasCycle();
|
||||
|
||||
Assert.False(hasCycle);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HasCycle_True()
|
||||
{
|
||||
var list = new SingleLinkedListAlgo<string>();
|
||||
|
||||
// 初始化一个具有环的链表
|
||||
list.Insert(1, "The");
|
||||
list.Insert(2, "Quick");
|
||||
list.Insert(3, "Brown");
|
||||
var fourthNode = list.Insert(4, "fox");
|
||||
list.Insert(5, "jumps");
|
||||
list.Insert(6, "over");
|
||||
list.Insert(7, "the");
|
||||
list.Insert(8, "lazy");
|
||||
var last = list.Insert(9, "dog");
|
||||
|
||||
last.Next = fourthNode;
|
||||
|
||||
bool hasCycle = list.HasCycle();
|
||||
|
||||
Assert.True(hasCycle);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Merge()
|
||||
{
|
||||
var list1 = new SingleLinkedListAlgo<int>(1, 2, 4);
|
||||
var list2 = new SingleLinkedListAlgo<int>(1, 3, 4);
|
||||
|
||||
var list3 = list1.Merge(list2);
|
||||
|
||||
PrintLinkedList(list3);
|
||||
|
||||
Assert.True(list1.First.Next.Next.Value == 2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Remove_2th_Node_From_End()
|
||||
{
|
||||
var list = new SingleLinkedListAlgo<int>(1, 2, 3, 4, 5);
|
||||
list.RemoveNthNodeFromEnd(2);
|
||||
|
||||
PrintLinkedList(list);
|
||||
|
||||
Assert.True(list.First.Next.Next.Next.Value == 5);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FindMiddleNode()
|
||||
{
|
||||
var list = new SingleLinkedListAlgo<int>(1, 2, 3, 4, 5);
|
||||
|
||||
ListNode<int> middleNode = list.FindMiddleNode();
|
||||
|
||||
Assert.True(middleNode.Value == 3);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.0" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\06-linkedlist\_06_linked_list.csproj" />
|
||||
<ProjectReference Include="..\..\07-linkedlist\_07_linkedlist\_07_linkedlist.csproj" />
|
||||
<ProjectReference Include="..\_06_linkedlist_tests\_06_linkedlist_tests.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
111
csharp/csharp.sln
Normal file
111
csharp/csharp.sln
Normal file
@ -0,0 +1,111 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26124.0
|
||||
MinimumVisualStudioVersion = 15.0.26124.0
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "_05_array", "05-array\_05_array.csproj", "{B88033F6-FF08-434A-AED7-91F5CDB73402}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "_06_linked_list", "06-linkedlist\_06_linked_list.csproj", "{29CABAFB-2581-42D1-ABD9-F0D9E0BB8DC2}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{B0248987-EEDF-4D93-8E12-C00B1EB5B6CB}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "_05_array_tests", "Tests\_05_array_tests\_05_array_tests.csproj", "{14982212-49E4-4409-8BFD-2D8A2945BD83}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "_06_linkedlist_tests", "Tests\_06_linkedlist_tests\_06_linkedlist_tests.csproj", "{1B93D9C6-D6C1-4619-BFB9-D84C29099223}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "_07_linkedlist", "07-linkedlist\_07_linkedlist\_07_linkedlist.csproj", "{5A4CCBB9-F683-4436-AAEE-4B3ABA76936B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "_07_linkedlist_tests", "Tests\_07_linkedlist_tests\_07_linkedlist_tests.csproj", "{66C3BC00-C135-4279-A666-A330A86F20D5}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{B88033F6-FF08-434A-AED7-91F5CDB73402}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B88033F6-FF08-434A-AED7-91F5CDB73402}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B88033F6-FF08-434A-AED7-91F5CDB73402}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B88033F6-FF08-434A-AED7-91F5CDB73402}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{B88033F6-FF08-434A-AED7-91F5CDB73402}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{B88033F6-FF08-434A-AED7-91F5CDB73402}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{B88033F6-FF08-434A-AED7-91F5CDB73402}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B88033F6-FF08-434A-AED7-91F5CDB73402}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B88033F6-FF08-434A-AED7-91F5CDB73402}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{B88033F6-FF08-434A-AED7-91F5CDB73402}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B88033F6-FF08-434A-AED7-91F5CDB73402}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B88033F6-FF08-434A-AED7-91F5CDB73402}.Release|x86.Build.0 = Release|Any CPU
|
||||
{29CABAFB-2581-42D1-ABD9-F0D9E0BB8DC2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{29CABAFB-2581-42D1-ABD9-F0D9E0BB8DC2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{29CABAFB-2581-42D1-ABD9-F0D9E0BB8DC2}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{29CABAFB-2581-42D1-ABD9-F0D9E0BB8DC2}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{29CABAFB-2581-42D1-ABD9-F0D9E0BB8DC2}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{29CABAFB-2581-42D1-ABD9-F0D9E0BB8DC2}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{29CABAFB-2581-42D1-ABD9-F0D9E0BB8DC2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{29CABAFB-2581-42D1-ABD9-F0D9E0BB8DC2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{29CABAFB-2581-42D1-ABD9-F0D9E0BB8DC2}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{29CABAFB-2581-42D1-ABD9-F0D9E0BB8DC2}.Release|x64.Build.0 = Release|Any CPU
|
||||
{29CABAFB-2581-42D1-ABD9-F0D9E0BB8DC2}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{29CABAFB-2581-42D1-ABD9-F0D9E0BB8DC2}.Release|x86.Build.0 = Release|Any CPU
|
||||
{14982212-49E4-4409-8BFD-2D8A2945BD83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{14982212-49E4-4409-8BFD-2D8A2945BD83}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{14982212-49E4-4409-8BFD-2D8A2945BD83}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{14982212-49E4-4409-8BFD-2D8A2945BD83}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{14982212-49E4-4409-8BFD-2D8A2945BD83}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{14982212-49E4-4409-8BFD-2D8A2945BD83}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{14982212-49E4-4409-8BFD-2D8A2945BD83}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{14982212-49E4-4409-8BFD-2D8A2945BD83}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{14982212-49E4-4409-8BFD-2D8A2945BD83}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{14982212-49E4-4409-8BFD-2D8A2945BD83}.Release|x64.Build.0 = Release|Any CPU
|
||||
{14982212-49E4-4409-8BFD-2D8A2945BD83}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{14982212-49E4-4409-8BFD-2D8A2945BD83}.Release|x86.Build.0 = Release|Any CPU
|
||||
{1B93D9C6-D6C1-4619-BFB9-D84C29099223}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1B93D9C6-D6C1-4619-BFB9-D84C29099223}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1B93D9C6-D6C1-4619-BFB9-D84C29099223}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{1B93D9C6-D6C1-4619-BFB9-D84C29099223}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{1B93D9C6-D6C1-4619-BFB9-D84C29099223}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{1B93D9C6-D6C1-4619-BFB9-D84C29099223}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{1B93D9C6-D6C1-4619-BFB9-D84C29099223}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1B93D9C6-D6C1-4619-BFB9-D84C29099223}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1B93D9C6-D6C1-4619-BFB9-D84C29099223}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{1B93D9C6-D6C1-4619-BFB9-D84C29099223}.Release|x64.Build.0 = Release|Any CPU
|
||||
{1B93D9C6-D6C1-4619-BFB9-D84C29099223}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{1B93D9C6-D6C1-4619-BFB9-D84C29099223}.Release|x86.Build.0 = Release|Any CPU
|
||||
{5A4CCBB9-F683-4436-AAEE-4B3ABA76936B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5A4CCBB9-F683-4436-AAEE-4B3ABA76936B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5A4CCBB9-F683-4436-AAEE-4B3ABA76936B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{5A4CCBB9-F683-4436-AAEE-4B3ABA76936B}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{5A4CCBB9-F683-4436-AAEE-4B3ABA76936B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{5A4CCBB9-F683-4436-AAEE-4B3ABA76936B}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{5A4CCBB9-F683-4436-AAEE-4B3ABA76936B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5A4CCBB9-F683-4436-AAEE-4B3ABA76936B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5A4CCBB9-F683-4436-AAEE-4B3ABA76936B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{5A4CCBB9-F683-4436-AAEE-4B3ABA76936B}.Release|x64.Build.0 = Release|Any CPU
|
||||
{5A4CCBB9-F683-4436-AAEE-4B3ABA76936B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{5A4CCBB9-F683-4436-AAEE-4B3ABA76936B}.Release|x86.Build.0 = Release|Any CPU
|
||||
{66C3BC00-C135-4279-A666-A330A86F20D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{66C3BC00-C135-4279-A666-A330A86F20D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{66C3BC00-C135-4279-A666-A330A86F20D5}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{66C3BC00-C135-4279-A666-A330A86F20D5}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{66C3BC00-C135-4279-A666-A330A86F20D5}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{66C3BC00-C135-4279-A666-A330A86F20D5}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{66C3BC00-C135-4279-A666-A330A86F20D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{66C3BC00-C135-4279-A666-A330A86F20D5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{66C3BC00-C135-4279-A666-A330A86F20D5}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{66C3BC00-C135-4279-A666-A330A86F20D5}.Release|x64.Build.0 = Release|Any CPU
|
||||
{66C3BC00-C135-4279-A666-A330A86F20D5}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{66C3BC00-C135-4279-A666-A330A86F20D5}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{14982212-49E4-4409-8BFD-2D8A2945BD83} = {B0248987-EEDF-4D93-8E12-C00B1EB5B6CB}
|
||||
{1B93D9C6-D6C1-4619-BFB9-D84C29099223} = {B0248987-EEDF-4D93-8E12-C00B1EB5B6CB}
|
||||
{66C3BC00-C135-4279-A666-A330A86F20D5} = {B0248987-EEDF-4D93-8E12-C00B1EB5B6CB}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
10
csharp/csharp.sln.DotSettings.user
Normal file
10
csharp/csharp.sln.DotSettings.user
Normal file
@ -0,0 +1,10 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/CodeStyle/Naming/CSharpAutoNaming/IsNotificationDisabled/@EntryValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/AutoDetectedNamingRules/=Method/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="" Style="AaBb_AaBb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/AutoDetectedNamingRules/=Parameters/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/AutoDetectedNamingRules/=TypesAndNamespaces/@EntryIndexedValue"><Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/AutoDetectedNamingRules/=Locals/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/AutoDetectedNamingRules/=PrivateInstanceFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/AutoDetectedNamingRules/=Property/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/Naming/CSharpNaming/ApplyAutoDetectedRules/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/Naming/CSharpAutoNaming/IsNamingAutoDetectionCompleted/@EntryValue">True</s:Boolean></wpf:ResourceDictionary>
|
Loading…
Reference in New Issue
Block a user