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  }