github.com/benz9527/toy-box/algo@v0.0.0-20240221120937-66c0c6bd5abd/list/doubly_linkedlist_test.go (about) 1 package list 2 3 import ( 4 "container/list" 5 "testing" 6 7 "github.com/stretchr/testify/assert" 8 ) 9 10 func TestLinkedList_AppendValue(t *testing.T) { 11 dlist := NewLinkedList[int]() 12 elements := dlist.AppendValue(1, 2, 3, 4, 5) 13 assert.Equal(t, len(elements), 5) 14 dlist.ForEach(func(idx int64, e NodeElement[int]) { 15 t.Logf("index: %d, e: %v", idx, e) 16 assert.Equal(t, elements[idx], e) 17 t.Logf("addr: %p, return addr: %p", elements[idx], e) 18 }) 19 20 dlist2 := list.New() 21 dlist2.PushBack(1) 22 dlist2.PushBack(2) 23 dlist2.PushBack(3) 24 dlist2.PushBack(4) 25 dlist2.PushBack(5) 26 27 assert.Equal(t, dlist.Len(), int64(dlist2.Len())) 28 29 dlistItr := dlist.Front() 30 dlist2Itr := dlist2.Front() 31 for dlist2Itr != nil { 32 assert.Equal(t, dlistItr.GetValue(), dlist2Itr.Value) 33 dlist2Itr = dlist2Itr.Next() 34 dlistItr = dlistItr.GetNext() 35 } 36 } 37 38 func TestDoublyLinkedList_InsertBefore(t *testing.T) { 39 dlist := NewLinkedList[int]() 40 elements := dlist.AppendValue(1) 41 _2n := dlist.InsertBefore(2, elements[0]) 42 _3n := dlist.InsertBefore(3, _2n) 43 _4n := dlist.InsertBefore(4, _3n) 44 dlist.InsertBefore(5, _4n) 45 assert.Equal(t, int64(5), dlist.Len()) 46 47 dlist2 := list.New() 48 _1n_2 := dlist2.PushBack(1) 49 _2n_2 := dlist2.InsertBefore(2, _1n_2) 50 _3n_2 := dlist2.InsertBefore(3, _2n_2) 51 _4n_2 := dlist2.InsertBefore(4, _3n_2) 52 dlist2.InsertBefore(5, _4n_2) 53 54 assert.Equal(t, dlist.Len(), int64(dlist2.Len())) 55 56 dlistItr := dlist.Front() 57 dlist2Itr := dlist2.Front() 58 for dlist2Itr != nil { 59 assert.Equal(t, dlistItr.GetValue(), dlist2Itr.Value) 60 dlist2Itr = dlist2Itr.Next() 61 dlistItr = dlistItr.GetNext() 62 } 63 } 64 65 func TestDoublyLinkedList_InsertAfter(t *testing.T) { 66 dlist := NewLinkedList[int]() 67 elements := dlist.AppendValue(1) 68 _2n := dlist.InsertAfter(2, elements[0]) 69 _3n := dlist.InsertAfter(3, _2n) 70 _4n := dlist.InsertAfter(4, _3n) 71 dlist.InsertAfter(5, _4n) 72 assert.Equal(t, int64(5), dlist.Len()) 73 74 dlist2 := list.New() 75 _1n_2 := dlist2.PushBack(1) 76 _2n_2 := dlist2.InsertAfter(2, _1n_2) 77 _3n_2 := dlist2.InsertAfter(3, _2n_2) 78 _4n_2 := dlist2.InsertAfter(4, _3n_2) 79 dlist2.InsertAfter(5, _4n_2) 80 81 assert.Equal(t, dlist.Len(), int64(dlist2.Len())) 82 83 dlistItr := dlist.Front() 84 dlist2Itr := dlist2.Front() 85 for dlist2Itr != nil { 86 assert.Equal(t, dlistItr.GetValue(), dlist2Itr.Value) 87 dlist2Itr = dlist2Itr.Next() 88 dlistItr = dlistItr.GetNext() 89 } 90 } 91 92 func TestLinkedList_AppendValueThenRemove(t *testing.T) { 93 t.Log("test linked list append value") 94 dlist := NewLinkedList[int]() 95 dlist2 := list.New() 96 checkItems := func() { 97 dlistItr := dlist.Front() 98 dlist2Itr := dlist2.Front() 99 for dlist2Itr != nil { 100 assert.Equal(t, dlistItr.GetValue(), dlist2Itr.Value) 101 dlist2Itr = dlist2Itr.Next() 102 dlistItr = dlistItr.GetNext() 103 } 104 } 105 106 elements := dlist.AppendValue(1, 2, 3, 4, 5) 107 assert.Equal(t, len(elements), 5) 108 dlist.ForEach(func(idx int64, e NodeElement[int]) { 109 t.Logf("index: %d, e: %v", idx, e) 110 assert.Equal(t, elements[idx], e) 111 t.Logf("addr: %p, return addr: %p", elements[idx], e) 112 }) 113 114 dlist2.PushBack(1) 115 dlist2.PushBack(2) 116 _3n := dlist2.PushBack(3) 117 dlist2.PushBack(4) 118 dlist2.PushBack(5) 119 assert.Equal(t, dlist.Len(), int64(dlist2.Len())) 120 checkItems() 121 122 t.Log("test linked list remove middle") 123 dlist.Remove(elements[2]) 124 dlist2.Remove(_3n) 125 checkItems() 126 127 t.Log("test linked list remove head") 128 dlist.Remove(dlist.Front()) 129 dlist2.Remove(dlist2.Front()) 130 checkItems() 131 132 t.Log("test linked list remove tail") 133 dlist.Remove(dlist.Back()) 134 dlist2.Remove(dlist2.Back()) 135 checkItems() 136 137 t.Log("test linked list remove nil") 138 dlist.Remove(nil) 139 // dlist2.Remove(nil) // nil panic 140 checkItems() 141 142 t.Log("check released elements") 143 assert.Equal(t, int64(dlist2.Len()), dlist.Len()) 144 dlist.ForEach(func(idx int64, e NodeElement[int]) { 145 t.Logf("index: %d, e: %v", idx, e) 146 }) 147 for idx, e := range elements { 148 t.Logf("index: %d, ptr: %p, e: %v", idx, e, e) 149 } 150 } 151 152 // goos: linux 153 // goarch: amd64 154 // pkg: github.com/benz9527/toy-box/algo/list 155 // cpu: Intel(R) Core(TM) i5-4590 CPU @ 3.30GHz 156 // BenchmarkNewLinkedList_AppendValue 157 // BenchmarkNewLinkedList_AppendValue-4 3138679 394.3 ns/op 88 B/op 3 allocs/op 158 func BenchmarkNewLinkedList_AppendValue(b *testing.B) { 159 dlist := NewLinkedList[int]() 160 b.ResetTimer() 161 for i := 0; i < b.N; i++ { 162 dlist.AppendValue(i) 163 } 164 b.ReportAllocs() 165 } 166 167 // goos: linux 168 // goarch: amd64 169 // pkg: github.com/benz9527/toy-box/algo/list 170 // cpu: Intel(R) Core(TM) i5-4590 CPU @ 3.30GHz 171 // BenchmarkSDKLinkedList_PushBack 172 // BenchmarkSDKLinkedList_PushBack-4 4632534 237.2 ns/op 55 B/op 1 allocs/op 173 func BenchmarkSDKLinkedList_PushBack(b *testing.B) { 174 dlist := list.New() 175 b.ResetTimer() 176 for i := 0; i < b.N; i++ { 177 dlist.PushBack(i) 178 } 179 b.ReportAllocs() 180 } 181 182 func TestLinkedList_InsertAfterAndMove(t *testing.T) { 183 dlist := NewLinkedList[int]() 184 dlist2 := list.New() 185 checkItems := func() { 186 dlistItr := dlist.Front() 187 dlist2Itr := dlist2.Front() 188 assert.NotNil(t, dlistItr) 189 assert.NotNil(t, dlist2Itr) 190 assert.Equal(t, int64(dlist2.Len()), dlist.Len()) 191 for dlist2Itr != nil { 192 assert.Equal(t, dlist2Itr.Value, dlistItr.GetValue()) 193 dlist2Itr = dlist2Itr.Next() 194 dlistItr = dlistItr.GetNext() 195 } 196 } 197 198 elements := dlist.AppendValue(1, 2, 3, 4, 5) 199 _6n := dlist.InsertAfter(6, elements[len(elements)-1]) 200 _7n := dlist.InsertBefore(7, elements[0]) 201 assert.Equal(t, int64(7), dlist.Len()) 202 dlist.ForEach(func(idx int64, e NodeElement[int]) { 203 t.Logf("index: %d, addr: %p, e: %v", idx, e, e) 204 }) 205 dlist.ReverseForEach(func(idx int64, e NodeElement[int]) { 206 t.Logf("reverse: index: %d, addr: %p, e: %v", idx, e, e) 207 }) 208 209 dlist2.PushBack(1) 210 dlist2.PushBack(2) 211 dlist2.PushBack(3) 212 dlist2.PushBack(4) 213 dlist2.PushBack(5) 214 _6n_2 := dlist2.InsertAfter(6, dlist2.Back()) 215 _7n_2 := dlist2.InsertBefore(7, dlist2.Front()) 216 assert.Equal(t, int64(dlist2.Len()), dlist.Len()) 217 checkItems() 218 219 t.Log("test move after") 220 dlist.MoveToBack(_7n) 221 dlist2.MoveToBack(_7n_2) 222 checkItems() 223 dlist.ForEach(func(idx int64, e NodeElement[int]) { 224 t.Logf("index: %d, addr: %p, e: %v", idx, e, e) 225 }) 226 dlist.ReverseForEach(func(idx int64, e NodeElement[int]) { 227 t.Logf("reverse: index: %d, addr: %p, e: %v", idx, e, e) 228 }) 229 230 t.Log("test move to front") 231 dlist.MoveToFront(_6n) 232 dlist2.MoveToFront(_6n_2) 233 checkItems() 234 dlist.ForEach(func(idx int64, e NodeElement[int]) { 235 t.Logf("index: %d, addr: %p, e: %v", idx, e, e) 236 }) 237 dlist.ReverseForEach(func(idx int64, e NodeElement[int]) { 238 t.Logf("reverse: index: %d, addr: %p, e: %v", idx, e, e) 239 }) 240 241 t.Log("test move before") 242 dlist.MoveBefore(_6n, _7n) 243 dlist2.MoveBefore(_6n_2, _7n_2) 244 checkItems() 245 dlist.ForEach(func(idx int64, e NodeElement[int]) { 246 t.Logf("index: %d, addr: %p, e: %v", idx, e, e) 247 }) 248 dlist.ReverseForEach(func(idx int64, e NodeElement[int]) { 249 t.Logf("reverse: index: %d, addr: %p, e: %v", idx, e, e) 250 }) 251 252 t.Log("test move after") 253 dlist.MoveAfter(_7n, dlist.Front()) 254 dlist2.MoveAfter(_7n_2, dlist2.Front()) 255 checkItems() 256 dlist.ForEach(func(idx int64, e NodeElement[int]) { 257 t.Logf("index: %d, addr: %p, e: %v", idx, e, e) 258 }) 259 dlist.ReverseForEach(func(idx int64, e NodeElement[int]) { 260 t.Logf("reverse: index: %d, addr: %p, e: %v", idx, e, e) 261 }) 262 263 t.Log("test push front list") 264 dlist_1 := NewLinkedList[int]() 265 dlist_1.AppendValue(8, 9, 10) 266 dlist2_1 := list.New() 267 dlist2_1.PushBack(8) 268 dlist2_1.PushBack(9) 269 dlist2_1.PushBack(10) 270 271 dlist.PushFrontList(dlist_1) 272 dlist2.PushFrontList(dlist2_1) 273 checkItems() 274 dlist.ForEach(func(idx int64, e NodeElement[int]) { 275 t.Logf("index: %d, addr: %p, e: %v", idx, e, e) 276 }) 277 dlist.ReverseForEach(func(idx int64, e NodeElement[int]) { 278 t.Logf("reverse: index: %d, addr: %p, e: %v", idx, e, e) 279 }) 280 281 t.Log("test push back list") 282 dlist_2 := NewLinkedList[int]() 283 dlist_2.AppendValue(11, 12, 13) 284 dlist2_2 := list.New() 285 dlist2_2.PushBack(11) 286 dlist2_2.PushBack(12) 287 dlist2_2.PushBack(13) 288 289 dlist.PushBackList(dlist_2) 290 dlist2.PushBackList(dlist2_2) 291 checkItems() 292 dlist.ForEach(func(idx int64, e NodeElement[int]) { 293 t.Logf("index: %d, addr: %p, e: %v", idx, e, e) 294 }) 295 dlist.ReverseForEach(func(idx int64, e NodeElement[int]) { 296 t.Logf("reverse: index: %d, addr: %p, e: %v", idx, e, e) 297 }) 298 } 299 300 func TestLinkedList_PushBack(t *testing.T) { 301 dlist := NewLinkedList[int]() 302 element := dlist.PushBack(1) 303 assert.Equal(t, int64(1), dlist.Len()) 304 assert.Equal(t, element.GetValue(), 1) 305 306 element = dlist.PushBack(2) 307 assert.Equal(t, int64(2), dlist.Len()) 308 assert.Equal(t, element.GetValue(), 2) 309 310 expected := []int{1, 2} 311 dlist.ForEach(func(idx int64, e NodeElement[int]) { 312 assert.Equal(t, expected[idx], e.GetValue()) 313 }) 314 315 reverseExpected := []int{2, 1} 316 dlist.ReverseForEach(func(idx int64, e NodeElement[int]) { 317 assert.Equal(t, reverseExpected[idx], e.GetValue()) 318 }) 319 } 320 321 func TestLinkedList_PushFront(t *testing.T) { 322 dlist := NewLinkedList[int]() 323 element := dlist.PushFront(1) 324 assert.Equal(t, int64(1), dlist.Len()) 325 assert.Equal(t, element.GetValue(), 1) 326 327 element = dlist.PushFront(2) 328 assert.Equal(t, int64(2), dlist.Len()) 329 assert.Equal(t, element.GetValue(), 2) 330 331 expected := []int{2, 1} 332 dlist.ForEach(func(idx int64, e NodeElement[int]) { 333 assert.Equal(t, expected[idx], e.GetValue()) 334 }) 335 336 reverseExpected := []int{1, 2} 337 dlist.ReverseForEach(func(idx int64, e NodeElement[int]) { 338 assert.Equal(t, reverseExpected[idx], e.GetValue()) 339 }) 340 } 341 342 // goos: linux 343 // goarch: amd64 344 // pkg: github.com/benz9527/toy-box/algo/list 345 // cpu: Intel(R) Core(TM) i5-4590 CPU @ 3.30GHz 346 // BenchmarkDoublyLinkedList_PushBack 347 // BenchmarkDoublyLinkedList_PushBack-4 3944040 258.9 ns/op 64 B/op 1 allocs/op 348 func BenchmarkDoublyLinkedList_PushBack(b *testing.B) { 349 dlist := NewLinkedList[int]() 350 b.ResetTimer() 351 for i := 0; i < b.N; i++ { 352 dlist.PushBack(i) 353 } 354 b.ReportAllocs() 355 } 356 357 // goos: linux 358 // goarch: amd64 359 // pkg: github.com/benz9527/toy-box/algo/list 360 // cpu: Intel(R) Core(TM) i5-4590 CPU @ 3.30GHz 361 // BenchmarkDoublyLinkedList_Append 362 // BenchmarkDoublyLinkedList_Append-4 9450279 127.1 ns/op 16 B/op 1 allocs/op 363 func BenchmarkDoublyLinkedList_Append(b *testing.B) { 364 dlist := NewLinkedList[int]() 365 elements := make([]NodeElement[int], 0, b.N) 366 for i := 0; i < b.N; i++ { 367 elements = append(elements, newNodeElement[int](i, dlist)) 368 } 369 b.ResetTimer() 370 for i := 0; i < b.N; i++ { 371 dlist.Append(elements[i]) 372 } 373 b.StopTimer() 374 b.ReportAllocs() 375 assert.Equal(b, int64(b.N), dlist.Len()) 376 } 377 378 func TestDoublyLinkedList_InsertBefore2(t *testing.T) { 379 dlist := NewLinkedList[int]() 380 _2n := dlist.InsertBefore(2, dlist.Front()) 381 assert.Equal(t, int64(1), dlist.Len()) 382 assert.Equal(t, _2n.GetValue(), 2) 383 dlist.ForEach(func(idx int64, e NodeElement[int]) { 384 t.Logf("index: %d, addr: %p, e: %v", idx, e, e) 385 }) 386 dlist.ReverseForEach(func(idx int64, e NodeElement[int]) { 387 t.Logf("reverse: index: %d, addr: %p, e: %v", idx, e, e) 388 }) 389 }