From 53a4d69bc8c7f69a703fdba86c8db2ce4a7ac65f Mon Sep 17 00:00:00 2001 From: robin Date: Fri, 11 Jan 2019 16:48:26 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E9=A1=B9=E7=9B=AE=E7=BB=93?= =?UTF-8?q?=E6=9E=84=EF=BC=8C=E5=AE=9E=E7=8E=B0=E9=93=BE=E8=A1=A8LRU?= =?UTF-8?q?=E7=BC=93=E5=AD=98=E5=92=8C=E9=93=BE=E8=A1=A8=E5=8F=8D=E8=BD=AC?= =?UTF-8?q?=E7=AD=89=E5=87=A0=E4=B8=AA=E5=B8=B8=E8=A7=84=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- csharp/05-array/Array.Tests.cs | 223 ------------ csharp/05-array/Array.cs | 155 +++++---- csharp/05-array/_05_array.csproj | 8 +- csharp/06-linkedlist/LRUWithArray.cs | 45 +++ csharp/06-linkedlist/LRUWithLinkedList.cs | 48 +++ ...6\347\216\260\346\200\235\350\267\257.txt" | 8 + csharp/06-linkedlist/SingleLinkedList.cs | 163 +++++++++ csharp/06-linkedlist/_06_linked_list.csproj | 13 + csharp/06_linkedlist/LRULinkedList.cs | 63 ---- csharp/06_linkedlist/SingleLinkedList.cs | 320 ------------------ .../_07_linkedlist/SingleLinkedListAlgo.cs | 172 ++++++++++ .../_07_linkedlist/_07_linkedlist.csproj | 11 + csharp/Tests/_05_array_tests/Array.Tests.cs | 231 +++++++++++++ .../_05_array_tests/_05_array_tests.csproj} | 8 +- .../BaseLinkedListTests.cs | 5 +- .../LRUWithArray.Tests.cs | 82 +++++ .../LRUWithLinkedList.Tests.cs} | 23 +- .../SingleLinkedList.Tests.cs | 163 +-------- .../_06_linkedlist_tests.csproj | 21 ++ .../SingleLinkedListAlgo.Tests.cs | 150 ++++++++ .../_07_linkedlist_tests.csproj | 21 ++ csharp/csharp.sln | 111 ++++++ csharp/csharp.sln.DotSettings.user | 10 + 23 files changed, 1208 insertions(+), 846 deletions(-) delete mode 100644 csharp/05-array/Array.Tests.cs create mode 100644 csharp/06-linkedlist/LRUWithArray.cs create mode 100644 csharp/06-linkedlist/LRUWithLinkedList.cs create mode 100644 "csharp/06-linkedlist/LRU\347\274\223\345\255\230\345\256\236\347\216\260\346\200\235\350\267\257.txt" create mode 100644 csharp/06-linkedlist/SingleLinkedList.cs create mode 100644 csharp/06-linkedlist/_06_linked_list.csproj delete mode 100644 csharp/06_linkedlist/LRULinkedList.cs delete mode 100644 csharp/06_linkedlist/SingleLinkedList.cs create mode 100644 csharp/07-linkedlist/_07_linkedlist/SingleLinkedListAlgo.cs create mode 100644 csharp/07-linkedlist/_07_linkedlist/_07_linkedlist.csproj create mode 100644 csharp/Tests/_05_array_tests/Array.Tests.cs rename csharp/{06_linkedlist/_06_linked_list.csproj => Tests/_05_array_tests/_05_array_tests.csproj} (67%) rename csharp/{06_linkedlist => Tests/_06_linkedlist_tests}/BaseLinkedListTests.cs (66%) create mode 100644 csharp/Tests/_06_linkedlist_tests/LRUWithArray.Tests.cs rename csharp/{06_linkedlist/LRULinkedList.Tests.cs => Tests/_06_linkedlist_tests/LRUWithLinkedList.Tests.cs} (63%) rename csharp/{06_linkedlist => Tests/_06_linkedlist_tests}/SingleLinkedList.Tests.cs (50%) create mode 100644 csharp/Tests/_06_linkedlist_tests/_06_linkedlist_tests.csproj create mode 100644 csharp/Tests/_07_linkedlist_tests/SingleLinkedListAlgo.Tests.cs create mode 100644 csharp/Tests/_07_linkedlist_tests/_07_linkedlist_tests.csproj create mode 100644 csharp/csharp.sln create mode 100644 csharp/csharp.sln.DotSettings.user diff --git a/csharp/05-array/Array.Tests.cs b/csharp/05-array/Array.Tests.cs deleted file mode 100644 index 6bfdab13..00000000 --- a/csharp/05-array/Array.Tests.cs +++ /dev/null @@ -1,223 +0,0 @@ -using System; -using Xunit; -using Xunit.Abstractions; - -public class ArrayTests -{ - private readonly Array _sqList; - private readonly ITestOutputHelper _output; - - public ArrayTests (ITestOutputHelper output) - { - _sqList = new Array (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 (() => _sqList.Insert (3, 1)); - Assert.IsType (ex); - } - - [Fact] - public void Insert_ThrowIndexOutOfRangeException_When_PositionLessThanOne () - { - Exception ex = Assert.Throws (() => _sqList.Insert (0, 1)); - Assert.IsType (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 (() => _sqList.Insert (11, 101)); - Assert.IsType (ex); - } - - [Fact] - public void Delete_ThrowIndexOutOfRangeException_When_PositionLessThanOne () - { - Exception ex = Assert.Throws (() => _sqList.Delete (0)); - Assert.IsType (ex); - } - - [Fact] - public void Delete_ThrowIndexOutOfRangeException_When_PositionGreaterThanLength () - { - _sqList.Insert (1, 11); - _sqList.Insert (2, 22); - Exception ex = Assert.Throws (() => _sqList.Delete (3)); - Assert.IsType (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 (() => _sqList.Find (0)); - Assert.IsType (ex); - } - - [Fact] - public void GetElem_ThrowsIndexOutOfRangeException_When_PositionGreaterThanLength () - { - _sqList.Insert (1, 11); - _sqList.Insert (2, 22); - _sqList.Insert (3, 33); - - Exception ex = Assert.Throws (() => _sqList.Find (4)); - Assert.IsType (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); - } -} \ No newline at end of file diff --git a/csharp/05-array/Array.cs b/csharp/05-array/Array.cs index d214f014..ecdc35f5 100644 --- a/csharp/05-array/Array.cs +++ b/csharp/05-array/Array.cs @@ -1,99 +1,116 @@ using System; -public sealed class Array +namespace _05_array { - private T[] _data; - private int _capacity; - private int _length; - - public Array (int capacity) + public sealed class Array where T : IComparable { - _data = new T[capacity]; - _capacity = capacity; - _length = 0; - } - - // length of list - public int Length => _length; + private T[] _data; + private readonly int _capacity; + private int _length; - // insert a new element at specified position (position start from 1) - public void Insert (int position, T newElem) - { - if (_length == _capacity) + public Array(int capacity) { - throw new OutOfMemoryException ("List has no more space"); + _data = new T[capacity]; + _capacity = capacity; + _length = 0; } - if (position < 1 || position > _length + 1) - { - throw new IndexOutOfRangeException ("Position was outside the bounds of the list"); - } + // length of list + public int Length => _length; - // to loop array from last position until finding the target position - if (position <= _length) + // insert a new element at specified index (index start from 0) + public void Insert(int index, T newElem) { - for (int k = _length - 1; k >= position - 1; k--) + if (_length == _capacity) { - _data[k + 1] = _data[k]; + throw new OutOfMemoryException("List has no more space"); + } + if (index < 0 || index > _length) + { + throw new IndexOutOfRangeException("Index was outside the bounds of the list"); } - } - _data[position - 1] = newElem; - _length++; - } + // to loop array from end until finding the target index + for (int k = _length; k > index; k--) + { + _data[k] = _data[k - 1]; + } - // get an element (position start from 1) - public T Find (int position) - { - if (position < 0 || position > _length) - { - throw new IndexOutOfRangeException ("Position was outside the bounds of the list"); - } - return _data[position - 1]; - } + _data[index] = newElem; - // search the element which matches specified element and return its index (index start from 0) - public int IndexOf (T elem) - { - if (_length == 0) return -1; - if (_data[0].Equals (elem)) return 0; - if (_data[_length - 1].Equals (elem)) return _length - 1; + _length++; + } - int start = 0; - while (start < _length - 1) + // get an element base on index + public T Find(int index) { - if (_data[start].Equals (elem)) return start; - start++; - continue; - } + if (index < 0 || index > _length - 1) + { + throw new IndexOutOfRangeException("Index was outside the bounds of the list"); + } - return -1; - } + return _data[index]; + } - // delete an element which is on the specified position (position start from 1) - public T Delete (int position) - { - if (position < 1 || position > _length) + // search the node which matches specified value and return its index (index start from 0) + public int IndexOf(T val) { - throw new IndexOutOfRangeException ("Position must be in the bound of list"); + if (_length == 0) return -1; + if (_data[0].Equals(val)) return 0; + if (_data[_length - 1].CompareTo(val) == 0) return _length - 1; + + int start = 1; + while (start < _length - 1) + { + if (_data[start].CompareTo(val) == 0) return start; + start++; + } + + return -1; } - var elem = _data[position - 1]; - for (int k = position; k < _length; k++) + // delete an node which is on the specified index + public bool Delete(int index) { - _data[k - 1] = _data[k]; + if (index < 0 || index > _length - 1) + { + throw new IndexOutOfRangeException("Index must be in the bound of list"); + } + + T deletedElem = _data[index]; + if (index < _length - 1) + { + for (int k = index; k < _length; k++) + { + _data[k] = _data[k + 1]; + } + } + + _length--; + + return true; } - _length--; + // delete an node + public bool Delete(T val) + { + int index; + for (index = 0; index < Length; index++) + { + if (_data[index].CompareTo(val) == 0) break; + } - return elem; - } + if (index >= Length) return false; - // clear list - public void Clear () - { - _data = new T[_capacity]; - _length = 0; + return Delete(index); + } + + // clear list + public void Clear() + { + _data = new T[_capacity]; + _length = 0; + } } } \ No newline at end of file diff --git a/csharp/05-array/_05_array.csproj b/csharp/05-array/_05_array.csproj index 3e025101..68495a72 100644 --- a/csharp/05-array/_05_array.csproj +++ b/csharp/05-array/_05_array.csproj @@ -1,4 +1,4 @@ - + netcoreapp2.2 @@ -6,10 +6,4 @@ false - - - - - - diff --git a/csharp/06-linkedlist/LRUWithArray.cs b/csharp/06-linkedlist/LRUWithArray.cs new file mode 100644 index 00000000..69603ed0 --- /dev/null +++ b/csharp/06-linkedlist/LRUWithArray.cs @@ -0,0 +1,45 @@ +using System.Text.RegularExpressions; +using _05_array; + +namespace _06_linked_list +{ + /// + /// 使用数组实现LRU缓存淘汰算法 + /// + public class LRUWithArray + { + private readonly int _capacity; + + public LRUWithArray(int capacity) + { + _capacity = capacity; + CachedList = new Array(capacity); + } + + public Array 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); + } + } +} \ No newline at end of file diff --git a/csharp/06-linkedlist/LRUWithLinkedList.cs b/csharp/06-linkedlist/LRUWithLinkedList.cs new file mode 100644 index 00000000..a96d427b --- /dev/null +++ b/csharp/06-linkedlist/LRUWithLinkedList.cs @@ -0,0 +1,48 @@ +namespace _06_linked_list +{ + /// + /// 使用单链表实现LRU缓存淘汰算法 + /// + public class LRUWithLinkedList + { + private readonly int _capacity; + + /// + /// 构造函数 + /// + /// 缓存容量 + public LRUWithLinkedList(int capacity = 10) + { + _capacity = capacity; + } + + public SingleLinkedList CachedList { get; } = new SingleLinkedList(); + + /// + /// 存储缓存数据 + /// + /// + 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); + } + } +} \ No newline at end of file diff --git "a/csharp/06-linkedlist/LRU\347\274\223\345\255\230\345\256\236\347\216\260\346\200\235\350\267\257.txt" "b/csharp/06-linkedlist/LRU\347\274\223\345\255\230\345\256\236\347\216\260\346\200\235\350\267\257.txt" new file mode 100644 index 00000000..896706c0 --- /dev/null +++ "b/csharp/06-linkedlist/LRU\347\274\223\345\255\230\345\256\236\347\216\260\346\200\235\350\267\257.txt" @@ -0,0 +1,8 @@ +实现LRU缓存淘汰算法思路: + +维护一个有序单链表,越靠近链尾的数据是最早访问的。 +当有一个新的数据被访问时, +1. 如果数据在缓存中,则将其从原位置删除,然后插入到表头; +2. 如果数据不在缓存中,有两种情况: + 1) 链表未满,则将数据插入到表头; + 2) 链表已满,则删除尾结点,将新数据插入到表头。 diff --git a/csharp/06-linkedlist/SingleLinkedList.cs b/csharp/06-linkedlist/SingleLinkedList.cs new file mode 100644 index 00000000..6b7bd83c --- /dev/null +++ b/csharp/06-linkedlist/SingleLinkedList.cs @@ -0,0 +1,163 @@ +using System; + +namespace _06_linked_list +{ + /// + /// 单链表的插入、删除、清空、查找 + /// + /// + public class SingleLinkedList where T : IComparable + { + public SingleLinkedList() + { + Head = new ListNode(default(T)); + } + + public SingleLinkedList(params T[] list) + { + Head = new ListNode(default(T)); + if (list == null) return; + + var p = Head; + foreach (var item in list) + { + var q = new ListNode(item); + p.Next = q; + p = q; + } + + Length = list.Length; + } + + // Head node + public ListNode First => Head.Next; + public ListNode Head { get; } + + public int Length { get; private set; } + + public ListNode 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(newElem); + newNode.Next = p.Next; + p.Next = newNode; + + Length++; + + return newNode; + } + + public ListNode Find(int position) + { + ListNode 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 Find(T elem) + { + ListNode p = Head.Next; + + while (p != null) + { + if (p.Value.CompareTo(elem) == 0) return p; + + p = p.Next; + } + + return null; + } + + public ListNode Delete(T value) + { + ListNode 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 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 + { + public ListNode(T value) + { + Value = value; + } + + public T Value { get; } + + public ListNode Next { get; set; } + } +} \ No newline at end of file diff --git a/csharp/06-linkedlist/_06_linked_list.csproj b/csharp/06-linkedlist/_06_linked_list.csproj new file mode 100644 index 00000000..66e10c44 --- /dev/null +++ b/csharp/06-linkedlist/_06_linked_list.csproj @@ -0,0 +1,13 @@ + + + + netcoreapp2.2 + + false + + + + + + + diff --git a/csharp/06_linkedlist/LRULinkedList.cs b/csharp/06_linkedlist/LRULinkedList.cs deleted file mode 100644 index 3bbff324..00000000 --- a/csharp/06_linkedlist/LRULinkedList.cs +++ /dev/null @@ -1,63 +0,0 @@ -namespace _06_linked_list -{ - /// - /// 使用单链表实现LRU缓存淘汰算法 - /// - /// - /// 思路: - /// 维护一个有序单链表,越是靠近链尾的数据是最早访问的。当有一个新的数据被访问时, - /// 1. 如果数据在缓存中,则将其从原位置删除,然后插入到表头; - /// 2. 如果数据不在缓存中,有两种情况: - /// 1) 链表未满,则将数据插入到表头; - /// 2) 链表已满,则删除尾结点,将新数据插入到表头。 - /// - public class LRULinkedList - { - private readonly SingleLinkedList _cachedList = new SingleLinkedList(); - private readonly int _capacity; - - /// - /// 构造函数 - /// - /// 缓存容量 - public LRULinkedList(int capacity = 10) - { - _capacity = capacity; - } - - /// - /// 存储缓存数据 - /// - /// - 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 GetCachedList() - { - return _cachedList; - } - } - -} \ No newline at end of file diff --git a/csharp/06_linkedlist/SingleLinkedList.cs b/csharp/06_linkedlist/SingleLinkedList.cs deleted file mode 100644 index 59ad6ba5..00000000 --- a/csharp/06_linkedlist/SingleLinkedList.cs +++ /dev/null @@ -1,320 +0,0 @@ -using System; - -namespace _06_linked_list -{ - /// - /// 单链表的插入、删除、清空、查找 - /// 1. 链表反转 - /// 2. 环的检测 - /// 3. 两个有序链表的合并 - /// 4. 删除链表倒数第n个结点 - /// 5. 求链表的中间结点 - /// - /// - public class SingleLinkedList where T : IComparable - { - public SingleLinkedList () - { - Head = new LinkedListNode (default (T)); - } - - public SingleLinkedList (params T[] list) - { - Head = new LinkedListNode (default (T)); - if (list == null) return; - - var p = Head; - foreach (var item in list) - { - var q = new LinkedListNode (item); - p.Next = q; - p = q; - } - - Length = list.Length; - } - - // Head node - public LinkedListNode First => Head.Next; - public LinkedListNode Head { get; } - - public int Length { get; private set; } - - public LinkedListNode 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 (newElem); - newNode.Next = p.Next; - p.Next = newNode; - - Length++; - - return newNode; - } - - public LinkedListNode Find (int position) - { - LinkedListNode 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 Find (T elem) - { - LinkedListNode p = Head.Next; - - while (p != null) - { - if (p.Value.CompareTo (elem) == 0) return p; - - p = p.Next; - } - - return null; - } - - public LinkedListNode Delete (T value) - { - LinkedListNode 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 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; - } - - /// - /// reverse current list - /// - public void Reverse () - { - if (Length <= 1) return; - - LinkedListNode p = First; - LinkedListNode q = First.Next; - - LinkedListNode r = null; - - p.Next = null; - while (q != null) - { - r = q.Next; - - q.Next = p; - p = q; - q = r; - } - - Head.Next = p; - } - - /// - /// 环的检测 - /// - /// - /// 用快慢两个指针,快指针每次移动2个结点,慢指针每次移动1个结点,当两个指针相遇时,说明存在环。 - /// LeetCode 编号: 141 - /// - 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; - } - - /// - /// 合并两个有序链表(从小到大) - /// - /// LeetCode 编号: 21 - /// - /// - public SingleLinkedList Merge (SingleLinkedList list) - { - if (list == null) return null; - - var root = new SingleLinkedList (); - - LinkedListNode 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; - } - - /// - /// 删除倒数第n个结点 - /// - /// - /// 用快慢两个指针,快指针比慢指针早n个结点,然后再同步移动两个指针,当快指针指向尾结点时,慢指针就是将要删除的结点 - /// LeetCode 编号: 19 - /// - /// - public void RemoveNthNodeFromEnd (int n) - { - if (n < 1 || n > Length) return; - - LinkedListNode preNode = Head; - LinkedListNode 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; - } - - /// - /// 链表的中间结点 - /// - /// - /// 思路: 利用快慢指针,快指针步长2,慢指针步长1,当快指针到达尾结点时,慢指针正好到达中间结点 - /// LeetCode 编号: 876 - /// - /// - public LinkedListNode FindMiddleNode () - { - if (First?.Next == null) return null; - - LinkedListNode slowPointer = First; - LinkedListNode fastPointer = First.Next; - - while (fastPointer.Next?.Next != null) - { - fastPointer = fastPointer.Next.Next; - slowPointer = slowPointer.Next; - } - - slowPointer = slowPointer.Next; - return slowPointer; - } - } - - public class LinkedListNode - { - private T _value; - - public LinkedListNode (T value) - { - _value = value; - } - - public T Value => _value; - public LinkedListNode Next { get; set; } - } -} \ No newline at end of file diff --git a/csharp/07-linkedlist/_07_linkedlist/SingleLinkedListAlgo.cs b/csharp/07-linkedlist/_07_linkedlist/SingleLinkedListAlgo.cs new file mode 100644 index 00000000..061a9a15 --- /dev/null +++ b/csharp/07-linkedlist/_07_linkedlist/SingleLinkedListAlgo.cs @@ -0,0 +1,172 @@ +using System; +using _06_linked_list; + +namespace _07_linkedlist +{ + /// + /// 单链表常用算法操作 + /// 1. 链表反转 + /// 2. 环的检测 + /// 3. 两个有序链表的合并 + /// 4. 删除链表倒数第n个结点 + /// 5. 求链表的中间结点 + /// + /// + public class SingleLinkedListAlgo : SingleLinkedList where T : IComparable + { + public SingleLinkedListAlgo(params T[] list) : base(list) + { + } + + /// + /// 链表反转 + /// + public void Reverse() + { + if (Length <= 1) return; + + ListNode p = First; + ListNode q = First.Next; + + ListNode r = null; + + p.Next = null; + while (q != null) + { + r = q.Next; + + q.Next = p; + p = q; + q = r; + } + + Head.Next = p; + } + + /// + /// 环的检测 + /// + /// + /// 用快慢两个指针,快指针每次移动2个结点,慢指针每次移动1个结点,当两个指针相遇时,说明存在环。 + /// LeetCode 编号: 141 + /// + 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; + } + + /// + /// 合并两个有序链表(从小到大) + /// + /// LeetCode 编号: 21 + /// + /// + public SingleLinkedListAlgo Merge(SingleLinkedListAlgo listAlgo) + { + if (listAlgo == null) return null; + + var root = new SingleLinkedListAlgo(); + + ListNode 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; + } + + /// + /// 删除倒数第n个结点 + /// + /// + /// 用快慢两个指针,快指针比慢指针早n个结点,然后再同步移动两个指针,当快指针指向尾结点时,慢指针就是将要删除的结点 + /// LeetCode 编号: 19 + /// + /// + public void RemoveNthNodeFromEnd(int n) + { + if (n < 1 || n > Length) return; + + ListNode preNode = Head; + ListNode 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; + } + + /// + /// 链表的中间结点 + /// + /// + /// 思路: 利用快慢指针,快指针步长2,慢指针步长1,当快指针到达尾结点时,慢指针正好到达中间结点 + /// LeetCode 编号: 876 + /// + /// + public ListNode FindMiddleNode() + { + if (First?.Next == null) return null; + + ListNode slowPointer = First; + ListNode fastPointer = First.Next; + + while (fastPointer.Next?.Next != null) + { + fastPointer = fastPointer.Next.Next; + slowPointer = slowPointer.Next; + } + + slowPointer = slowPointer.Next; + return slowPointer; + } + } +} \ No newline at end of file diff --git a/csharp/07-linkedlist/_07_linkedlist/_07_linkedlist.csproj b/csharp/07-linkedlist/_07_linkedlist/_07_linkedlist.csproj new file mode 100644 index 00000000..0080a55e --- /dev/null +++ b/csharp/07-linkedlist/_07_linkedlist/_07_linkedlist.csproj @@ -0,0 +1,11 @@ + + + + netcoreapp2.2 + + + + + + + diff --git a/csharp/Tests/_05_array_tests/Array.Tests.cs b/csharp/Tests/_05_array_tests/Array.Tests.cs new file mode 100644 index 00000000..f5cae7c4 --- /dev/null +++ b/csharp/Tests/_05_array_tests/Array.Tests.cs @@ -0,0 +1,231 @@ +using System; +using Xunit; +using Xunit.Abstractions; +using _05_array; + +namespace _05_array_tests +{ + public class ArrayTests + { + private readonly Array _sqList; + private readonly ITestOutputHelper _output; + + public ArrayTests(ITestOutputHelper output) + { + _sqList = new Array(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(() => _sqList.Insert(3, 2)); + Assert.IsType(ex); + } + + [Fact] + public void Insert_ThrowIndexOutOfRangeException_When_Index_LessThan_Zero() + { + Exception ex = Assert.Throws(() => _sqList.Insert(-1, 1)); + Assert.IsType(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(() => _sqList.Insert(10, 101)); + Assert.IsType(ex); + } + + [Fact] + public void Delete_ThrowIndexOutOfRangeException_When_Index_LessThan_Zero() + { + Exception ex = Assert.Throws(() => _sqList.Delete(-1)); + Assert.IsType(ex); + } + + [Fact] + public void Delete_ThrowIndexOutOfRangeException_When_Index_GreaterThan_Length() + { + _sqList.Insert(0, 11); + _sqList.Insert(1, 22); + Exception ex = Assert.Throws(() => _sqList.Delete(3)); + Assert.IsType(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(() => _sqList.Find(-1)); + Assert.IsType(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(() => _sqList.Find(4)); + Assert.IsType(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); + } + } +} \ No newline at end of file diff --git a/csharp/06_linkedlist/_06_linked_list.csproj b/csharp/Tests/_05_array_tests/_05_array_tests.csproj similarity index 67% rename from csharp/06_linkedlist/_06_linked_list.csproj rename to csharp/Tests/_05_array_tests/_05_array_tests.csproj index 3e025101..d0fa21aa 100644 --- a/csharp/06_linkedlist/_06_linked_list.csproj +++ b/csharp/Tests/_05_array_tests/_05_array_tests.csproj @@ -1,9 +1,11 @@ - + netcoreapp2.2 false + + 05_array_tests @@ -12,4 +14,8 @@ + + + + diff --git a/csharp/06_linkedlist/BaseLinkedListTests.cs b/csharp/Tests/_06_linkedlist_tests/BaseLinkedListTests.cs similarity index 66% rename from csharp/06_linkedlist/BaseLinkedListTests.cs rename to csharp/Tests/_06_linkedlist_tests/BaseLinkedListTests.cs index b09568f1..e36298c4 100644 --- a/csharp/06_linkedlist/BaseLinkedListTests.cs +++ b/csharp/Tests/_06_linkedlist_tests/BaseLinkedListTests.cs @@ -1,10 +1,11 @@ using System; +using _06_linked_list; -namespace _06_linked_list +namespace _06_linkedlist_tests { public class BaseLinkedListTests { - protected void PrintList (SingleLinkedList list) where T : IComparable + protected void PrintLinkedList (SingleLinkedList list) where T : IComparable { if (list == null) return; diff --git a/csharp/Tests/_06_linkedlist_tests/LRUWithArray.Tests.cs b/csharp/Tests/_06_linkedlist_tests/LRUWithArray.Tests.cs new file mode 100644 index 00000000..449e8d76 --- /dev/null +++ b/csharp/Tests/_06_linkedlist_tests/LRUWithArray.Tests.cs @@ -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 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)); + } + } +} \ No newline at end of file diff --git a/csharp/06_linkedlist/LRULinkedList.Tests.cs b/csharp/Tests/_06_linkedlist_tests/LRUWithLinkedList.Tests.cs similarity index 63% rename from csharp/06_linkedlist/LRULinkedList.Tests.cs rename to csharp/Tests/_06_linkedlist_tests/LRUWithLinkedList.Tests.cs index 7df7dbb6..11a343d2 100644 --- a/csharp/06_linkedlist/LRULinkedList.Tests.cs +++ b/csharp/Tests/_06_linkedlist_tests/LRUWithLinkedList.Tests.cs @@ -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 @@ public void LRU_Set_Value_When_Not_Existed() 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 @@ public void LRU_Set_Value_When_Not_Existed() [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 @@ public void LRU_Set_Value_When_Existed() 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 @@ public void LRU_Set_Value_When_Existed() [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 @@ public void LRU_Set_Value_When_Full() lru.Set(9); lru.Set(8); - var list = lru.GetCachedList(); + var list = lru.CachedList; - PrintList(list); + PrintLinkedList(list); Assert.Equal(8, list.First.Value); } diff --git a/csharp/06_linkedlist/SingleLinkedList.Tests.cs b/csharp/Tests/_06_linkedlist_tests/SingleLinkedList.Tests.cs similarity index 50% rename from csharp/06_linkedlist/SingleLinkedList.Tests.cs rename to csharp/Tests/_06_linkedlist_tests/SingleLinkedList.Tests.cs index e7c670af..525665eb 100644 --- a/csharp/06_linkedlist/SingleLinkedList.Tests.cs +++ b/csharp/Tests/_06_linkedlist_tests/SingleLinkedList.Tests.cs @@ -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 @@ public void Insert_3_Elements_Return_Length_3() { var list = new SingleLinkedList("The", "Quick", "Brown"); - PrintList(list); + PrintLinkedList(list); Assert.Equal(3, list.Length); } @@ -33,7 +34,7 @@ public void Insert_Some_Elements_Then_Verify_Last() } [Fact] - public void Find_Return_Null_When_Postion_LessThan_1() + public void Find_Return_Null_When_Position_LessThan_1() { var list = new SingleLinkedList("The", "Quick", "Brown"); @@ -42,7 +43,7 @@ public void Find_Return_Null_When_Postion_LessThan_1() } [Fact] - public void Find_Return_Null_When_Postion_GreaterThan_Length() + public void Find_Return_Null_When_Position_GreaterThan_Length() { var list = new SingleLinkedList("The", "Quick", "Brown"); @@ -51,7 +52,7 @@ public void Find_Return_Null_When_Postion_GreaterThan_Length() } [Fact] - public void Find_Return_Correct_When_Postion_Valid() + public void Find_Return_Correct_When_Position_Valid() { var list = new SingleLinkedList("The", "Quick", "Brown"); @@ -60,7 +61,7 @@ public void Find_Return_Correct_When_Postion_Valid() } [Fact] - public void Delete_Return_Null_When_Postion_LessThan_1() + public void Delete_Return_Null_When_Position_LessThan_1() { var list = new SingleLinkedList("The", "Quick", "Brown"); @@ -69,7 +70,7 @@ public void Delete_Return_Null_When_Postion_LessThan_1() } [Fact] - public void Delete_Return_Null_When_Postion_GreaterThan_Length() + public void Delete_Return_Null_When_Position_GreaterThan_Length() { var list = new SingleLinkedList("The", "Quick", "Brown"); @@ -85,7 +86,7 @@ public void Delete_By_Value_Success_When_Element_Exist() var deletedNode = list.Delete("over"); - PrintList(list); + PrintLinkedList(list); Assert.Equal("over", deletedNode.Value); Assert.Equal(8, list.Length); @@ -99,7 +100,7 @@ public void Delete_By_Value_Success_When_Element_Not_Exist() var deletedNode = list.Delete("hello"); - PrintList(list); + PrintLinkedList(list); Assert.Null(deletedNode); Assert.Equal(9, list.Length); @@ -113,7 +114,7 @@ public void Delete_By_Value_Success_When_Delete_First() var deletedNode = list.Delete("The"); - PrintList(list); + PrintLinkedList(list); Assert.Equal("The", deletedNode.Value); Assert.Equal(8, list.Length); @@ -127,7 +128,7 @@ public void Delete_By_Value_Success_When_Delete_Last() var deletedNode = list.Delete("dog"); - PrintList(list); + PrintLinkedList(list); Assert.Equal("dog", deletedNode.Value); Assert.Equal(8, list.Length); @@ -141,7 +142,7 @@ public void Delete_Success_When_Position_Valid() var node = list.Delete(3); - PrintList(list); + PrintLinkedList(list); Assert.Equal("Brown", node.Value); Assert.Equal(8, list.Length); @@ -167,143 +168,5 @@ public void Clear_First_Is_Null() Assert.Null(list.First); } - [Fact] - public void Reverse_When_List_Is_Empty() - { - var list = new SingleLinkedList(); - - list.Reverse(); - - PrintList(list); - - Assert.Null(list.First); - } - - [Fact] - public void Reverse_When_List_Has_Many_Elements() - { - var list = new SingleLinkedList("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("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("The"); - - bool hasCycle = list.HasCycle(); - - Assert.False(hasCycle); - } - - [Fact] - public void HasCycle_False_When_List_Length_2() - { - var list = new SingleLinkedList("The", "Quick"); - - bool hasCycle = list.HasCycle(); - - Assert.False(hasCycle); - } - - [Fact] - public void HasCycle_True_When_List_Length_2() - { - var list = new SingleLinkedList(); - - 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("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(); - - // 初始化一个具有环的链表 - 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(1, 2, 4); - var list2 = new SingleLinkedList(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(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(1, 2, 3, 4, 5); - - LinkedListNode middleNode = list.FindMiddleNode(); - - Assert.True(middleNode.Value == 3); - } } } \ No newline at end of file diff --git a/csharp/Tests/_06_linkedlist_tests/_06_linkedlist_tests.csproj b/csharp/Tests/_06_linkedlist_tests/_06_linkedlist_tests.csproj new file mode 100644 index 00000000..dc95495f --- /dev/null +++ b/csharp/Tests/_06_linkedlist_tests/_06_linkedlist_tests.csproj @@ -0,0 +1,21 @@ + + + + netcoreapp2.2 + _06_linkedlist_tests + + false + + + + + + + + + + + + + + diff --git a/csharp/Tests/_07_linkedlist_tests/SingleLinkedListAlgo.Tests.cs b/csharp/Tests/_07_linkedlist_tests/SingleLinkedListAlgo.Tests.cs new file mode 100644 index 00000000..aa5f093c --- /dev/null +++ b/csharp/Tests/_07_linkedlist_tests/SingleLinkedListAlgo.Tests.cs @@ -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(); + + list.Reverse(); + + PrintLinkedList(list); + + Assert.Null(list.First); + } + + [Fact] + public void Reverse_When_List_Has_Many_Elements() + { + var list = new SingleLinkedListAlgo("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("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("The"); + + bool hasCycle = list.HasCycle(); + + Assert.False(hasCycle); + } + + [Fact] + public void HasCycle_False_When_List_Length_2() + { + var list = new SingleLinkedListAlgo("The", "Quick"); + + bool hasCycle = list.HasCycle(); + + Assert.False(hasCycle); + } + + [Fact] + public void HasCycle_True_When_List_Length_2() + { + var list = new SingleLinkedListAlgo(); + + 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("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(); + + // 初始化一个具有环的链表 + 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(1, 2, 4); + var list2 = new SingleLinkedListAlgo(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(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(1, 2, 3, 4, 5); + + ListNode middleNode = list.FindMiddleNode(); + + Assert.True(middleNode.Value == 3); + } + } +} \ No newline at end of file diff --git a/csharp/Tests/_07_linkedlist_tests/_07_linkedlist_tests.csproj b/csharp/Tests/_07_linkedlist_tests/_07_linkedlist_tests.csproj new file mode 100644 index 00000000..53f91206 --- /dev/null +++ b/csharp/Tests/_07_linkedlist_tests/_07_linkedlist_tests.csproj @@ -0,0 +1,21 @@ + + + + netcoreapp2.2 + + false + + + + + + + + + + + + + + + diff --git a/csharp/csharp.sln b/csharp/csharp.sln new file mode 100644 index 00000000..402e9695 --- /dev/null +++ b/csharp/csharp.sln @@ -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 diff --git a/csharp/csharp.sln.DotSettings.user b/csharp/csharp.sln.DotSettings.user new file mode 100644 index 00000000..3e96df59 --- /dev/null +++ b/csharp/csharp.sln.DotSettings.user @@ -0,0 +1,10 @@ + + True + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="" Style="AaBb_AaBb" /></Policy> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + True + True \ No newline at end of file