因爲最近在工做中須要用到樹形結構來解決一些問題,因此萌生了系統學習「數據結構和算法」的想法,因而乎從最簡單的表結構開始。因爲數組是最簡單的表結構的實現,也是各個編程語言內置的數據類型,因此不作更多的記錄。表結構中如下實現打算學習:node
本篇爲學習數據結構的第一篇隨筆,從最簡單的單向鏈表開始吧。算法
平臺:dotNet Core 1.0, C#編程
IDE:VSCode數組
若是考慮算法複用的話,能夠實現泛型。數據結構
1 public class SingleLinkedList 2 { 3 //Inner class, represents a node of linked list. Each node consists of data and a link to next node
4 class Node 5 { 6 public Node() { } 7 public Node(object item) 8 { 9 Data = item; 10 Next = null; 11 } 12 public object Data { get; set; } 13 public Node Next { get; set; } 14
15 public override string ToString() 16 { 17 return "Node:" + Data.ToString(); 18 } 19 } 20
21 public SingleLinkedList() 22 { 23 header = null; 24 } 25
26 #region Public API
27
28 //Add item before first node
29 public void AddFirst(object item) 30 { 31 if (header == null) 32 { 33 header = new Node(item); 34 } 35 else
36 { 37 var newNode = new Node(item); 38 newNode.Next = header; 39 header = newNode; 40 } 41 } 42
43 //Add item after last node
44 public void AddLast(object item) 45 { 46 if (header == null) 47 { 48 header = new Node(item); 49 } 50 else
51 { 52 LastNode().Next = new Node(item); 53 } 54 } 55
56 public void Insert(int index, object item) 57 { 58 if (index < 0) throw new ArgumentOutOfRangeException(); 59 if (index == 0) 60 { 61 AddFirst(item); 62 return; 63 } 64 if (header == null) throw new ArgumentOutOfRangeException(); 65
66 var node = GetNode(index - 1); 67 var newNode = new Node(item); 68 newNode.Next = node.Next; 69 node.Next = newNode; 70 } 71
72 public object Get(int index) 73 { 74 return GetNode(index).Data; 75 } 76
77 //Find index of specified data
78 public int IndexOf(object item) 79 { 80 if (header == null) return -1; 81
82 var curIndex = 0; 83 for (var cur = new Node { Next = header }; cur.Next != null; cur = cur.Next, curIndex++) 84 { 85 if (!cur.Next.Data.Equals(item)) continue; 86 return curIndex; 87 } 88
89 return -1; 90 } 91
92 //Remove specified data of its first occurance
93 public void Remove(object item) 94 { 95 if (header == null) return; 96
97 //Add a fake node pointing to header, so we don't need set up a local variable pointing to header. This is simple. Nice trick.
98 for (var cur = new Node { Next = header }; cur.Next != null; cur = cur.Next) 99 { 100 if (!cur.Next.Data.Equals(item)) continue; 101 if (cur.Next == header) 102 { 103 header = header.Next; 104 } 105 else
106 { 107 cur.Next = cur.Next.Next; 108 } 109 } 110 } 111
112 //此方法能夠理解爲先獲取index-1位置的Node,而後設置此Node的下一個節點跳過index處的節點
113 public void RemoveAt(int index) 114 { 115 if (index < 0 || header == null) throw new ArgumentOutOfRangeException(); 116 else if (index == 0) 117 { 118 header = header.Next; 119 } 120 else
121 { 122 Node pre = GetNode(index - 1); 123 pre.Next = pre.Next.Next; 124 } 125 } 126
127 public bool Contains(object item) 128 { 129 if (header == null) return false; 130 var current = header; 131 while (current != null && !current.Data.Equals(item)) 132 { 133 current = current.Next; 134 } 135 return current != null; 136 } 137
138 public void Clear() 139 { 140 header = null; 141 } 142
143 public bool IsEmpty() 144 { 145 return header == null; 146 } 147
148 public int Count() 149 { 150 if (IsEmpty()) return 0; 151 int count = 1; 152 for (var cur = header; cur.Next != null; cur = cur.Next, count++) 153 { 154 } 155 return count; 156 } 157
158 public override string ToString() 159 { 160 if (header == null) return "Empty"; 161 StringBuilder sb = new StringBuilder(); 162 for (Node current = header; current != null; current = current.Next) 163 { 164 sb.Append(current.Data.ToString()); 165 if (current.Next != null) sb.Append("->"); 166 } 167 return sb.ToString(); 168 } 169
170 #endregion
171
172 #region Private Method
173
174 private Node LastNode() 175 { 176 if (header == null) throw new InvalidOperationException(); 177
178 var current = header; 179 while (current.Next != null) 180 { 181 current = current.Next; 182 } 183 return current; 184 } 185
186 private Node GetNode(int index) 187 { 188 if (header == null) throw new ArgumentOutOfRangeException(); 189
190 int curIndex = 0; 191 var cur = header; 192 while (cur != null && curIndex != index) 193 { 194 cur = cur.Next; 195 curIndex++; 196 } 197
198 if (cur == null) 199 { 200 throw new ArgumentOutOfRangeException(); 201 } 202 else
203 { 204 return cur; 205 } 206 } 207
208
209 #endregion
210
211 #region Fields
212
213 private Node header; 214
215 #endregion
216 }
1 public static void Main(string[] args) 2 { 3 Can_Add_First(); 4 Can_Add_Last(); 5 Can_Insert(); 6 Other(); 7 8 Console.ReadKey(); 9 } 10 11 static void Can_Add_First() 12 { 13 var list = new SingleLinkedList(); 14 //add when list is empty 15 list.AddFirst("First"); 16 Expect(list, "First"); 17 //add when list is not empty 18 list.AddFirst("Second"); 19 list.AddFirst("Third"); 20 Expect(list, "Third->Second->First"); 21 } 22 23 static void Can_Add_Last() 24 { 25 var list = new SingleLinkedList(); 26 //add when list is empty 27 list.AddLast("First"); 28 Expect(list, "First"); 29 //add when list is not empty 30 list.AddLast("Second"); 31 list.AddLast("Third"); 32 Expect(list, "First->Second->Third"); 33 } 34 35 static void Can_Insert() 36 { 37 var list = new SingleLinkedList(); 38 //insert when list is empty 39 list.Insert(0, "First"); 40 Expect(list, "First"); 41 //insert when list is not empty 42 list.Insert(1, "Second"); 43 Expect(list, "First->Second"); 44 list.Insert(1, "Third"); 45 Expect(list, "First->Third->Second"); 46 list.Insert(0, "Forth"); 47 Expect(list, "Forth->First->Third->Second"); 48 } 49 50 static void Other() 51 { 52 var list = new SingleLinkedList(); 53 list.AddLast("First"); 54 list.AddLast("Second"); 55 list.AddLast("Third"); 56 Console.WriteLine("object Get(int) Passed: " + (list.Get(1) as string == "Second")); 57 58 Console.WriteLine("int IndexOf(object) Passsed: " + ((int)list.IndexOf("Third") == 2)); 59 Console.WriteLine("int IndexOf(object) Passsed: " + ((int)list.IndexOf("Forth") == -1)); 60 61 list.Remove("First"); 62 Expect(list, "Second->Third"); 63 list.RemoveAt(1); 64 Expect(list, "Second"); 65 66 Console.WriteLine("bool Contains(object) Passed: " + (list.Contains("Second") == true)); 67 Console.WriteLine("bool Contains(object) Passed: " + (list.Contains("First") == false)); 68 Console.WriteLine("int Count() Passed: " + (list.Count() == 1)); 69 Console.WriteLine("bool IsEmpty() Passed: " + (list.IsEmpty() == false)); 70 71 list.Clear(); 72 Console.WriteLine("int Count() Passed: " + (list.Count() == 0)); 73 Console.WriteLine("bool IsEmpty() Passed: " + (list.IsEmpty() == true)); 74 }