DoubleLinkedList.st
changeset 3920 6197499978a0
equal deleted inserted replaced
3919:57fbcf872e8d 3920:6197499978a0
       
     1 "
       
     2  COPYRIGHT (c) 2016 by eXept Software AG
       
     3               All Rights Reserved
       
     4 
       
     5  This software is furnished under a license and may be used
       
     6  only in accordance with the terms of that license and with the
       
     7  inclusion of the above copyright notice.   This software may not
       
     8  be provided or otherwise made available to, or used by, any
       
     9  other person.  No title to or ownership of the software is
       
    10  hereby transferred.
       
    11 "
       
    12 "{ Package: 'stx:libbasic2' }"
       
    13 
       
    14 "{ NameSpace: Smalltalk }"
       
    15 
       
    16 LinkedList subclass:#DoubleLinkedList
       
    17 	instanceVariableNames:''
       
    18 	classVariableNames:''
       
    19 	poolDictionaries:''
       
    20 	category:'Collections-Linked'
       
    21 !
       
    22 
       
    23 !DoubleLinkedList class methodsFor:'documentation'!
       
    24 
       
    25 copyright
       
    26 "
       
    27  COPYRIGHT (c) 2016 by eXept Software AG
       
    28               All Rights Reserved
       
    29 
       
    30  This software is furnished under a license and may be used
       
    31  only in accordance with the terms of that license and with the
       
    32  inclusion of the above copyright notice.   This software may not
       
    33  be provided or otherwise made available to, or used by, any
       
    34  other person.  No title to or ownership of the software is
       
    35  hereby transferred.
       
    36 "
       
    37 !
       
    38 
       
    39 examples
       
    40 "
       
    41                                                                         [exBegin]
       
    42     |l|
       
    43 
       
    44     l := DoubleLinkedList new.
       
    45     l addLast:'one'.
       
    46     l addLast:'two'.
       
    47     l addLast:'three'.
       
    48     l addLast:'four'.
       
    49     l inspect
       
    50                                                                         [exEnd]
       
    51 
       
    52 
       
    53                                                                         [exBegin]
       
    54     |l|
       
    55 
       
    56     l := LinkedList new.
       
    57     l addLast:(ValueDoubleLink new value:'one').
       
    58     l addLast:(ValueDoubleLink new value:'two').
       
    59     l addLast:(ValueDoubleLink new value:'three').
       
    60     l addLast:(ValueDoubleLink new value:'four').
       
    61     (l at:3) value inspect.        'slow operation for large lists'.
       
    62                                                                         [exEnd]
       
    63 
       
    64 
       
    65                                                                         [exBegin]
       
    66     |l link|
       
    67 
       
    68     l := LinkedList new.
       
    69     l addLast:(ValueDoubleLink new value:'one').
       
    70     l addLast:(ValueDoubleLink new value:'two').
       
    71     l addLast:(ValueDoubleLink new value:'three').
       
    72     l addLast:(ValueDoubleLink new value:'four').
       
    73     link := l removeFirst.
       
    74     l addLast:link.
       
    75     l inspect.
       
    76                                                                         [exEnd]
       
    77 "
       
    78 ! !
       
    79 
       
    80 !DoubleLinkedList methodsFor:'adding & removing'!
       
    81 
       
    82 add:aLinkOrAnyOtherObject
       
    83     "adds aLink to the end of the sequence. Returns aLink"
       
    84 
       
    85     |newLink|
       
    86 
       
    87     newLink := aLinkOrAnyOtherObject asDoubleLink.
       
    88 
       
    89     newLink nextLink:nil.
       
    90     newLink previousLink:lastLink.
       
    91     lastLink isNil ifTrue:[
       
    92         firstLink := newLink
       
    93     ] ifFalse: [
       
    94         lastLink nextLink:newLink
       
    95     ].
       
    96     lastLink := newLink.
       
    97     numberOfNodes := numberOfNodes + 1.
       
    98     ^ newLink
       
    99 
       
   100     "
       
   101      |l e1 e2|
       
   102      l := DoubleLinkedList new.
       
   103      e1 := l add:'one'.
       
   104      e2 := l add:'two'.
       
   105      self assert:(l firstLink == e1).
       
   106      self assert:(l lastLink == e2).
       
   107      self assert:(e1 nextLink == e2).
       
   108      self assert:(e2 nextLink isNil).
       
   109      self assert:(e1 previousLink isNil).
       
   110      self assert:(e2 previousLink == e1).
       
   111     "
       
   112 !
       
   113 
       
   114 add:aLinkOrAnyOtherObject after:aLinkOrValue
       
   115     |linkToAddAfter newLink this nextLink|
       
   116 
       
   117     aLinkOrValue asDoubleLink == aLinkOrValue ifTrue:[
       
   118         linkToAddAfter := aLinkOrValue
       
   119     ] ifFalse:[
       
   120         this := firstLink.
       
   121         [this notNil and:[this value ~~ aLinkOrAnyOtherObject]] whileTrue:[
       
   122             this := this nextLink
       
   123         ].
       
   124         this isNil ifTrue:[
       
   125             ^ self addLast:aLinkOrAnyOtherObject
       
   126         ].
       
   127         linkToAddAfter := this.
       
   128     ].
       
   129     newLink := aLinkOrAnyOtherObject asDoubleLink.
       
   130 
       
   131     newLink nextLink:(nextLink := linkToAddAfter nextLink).
       
   132     newLink previousLink:linkToAddAfter.
       
   133     linkToAddAfter nextLink:newLink.
       
   134     nextLink isNil ifTrue:[
       
   135         lastLink := newLink
       
   136     ] ifFalse:[
       
   137         nextLink previousLink:newLink.
       
   138     ].
       
   139     numberOfNodes := numberOfNodes + 1.
       
   140     ^ newLink
       
   141 
       
   142     "
       
   143      |l e1 e2 e3 e2_5 e4|
       
   144      l := DoubleLinkedList new.
       
   145      e1 := l add:'one'.
       
   146      e2 := l add:'two'.
       
   147      e3 := l add:'three'.
       
   148      self assert:(l firstLink == e1).
       
   149      self assert:(e1 nextLink == e2).
       
   150      self assert:(e2 nextLink == e3).
       
   151      self assert:(e3 nextLink isNil).
       
   152 
       
   153      self assert:(l lastLink == e3).
       
   154      self assert:(e3 previousLink == e2).
       
   155      self assert:(e2 previousLink == e1).
       
   156      self assert:(e1 previousLink isNil).
       
   157 
       
   158      e2_5 := l add:'twoPointFife' after:e2.
       
   159      self assert:(l firstLink == e1).
       
   160      self assert:(e1 nextLink == e2).
       
   161      self assert:(e2 nextLink == e2_5).
       
   162      self assert:(e2_5 nextLink == e3).
       
   163      self assert:(e3 nextLink isNil).
       
   164 
       
   165      self assert:(l lastLink == e3).
       
   166      self assert:(e3 previousLink == e2_5).
       
   167      self assert:(e2_5 previousLink == e2).
       
   168      self assert:(e2 previousLink == e1).
       
   169      self assert:(e1 previousLink isNil).
       
   170 
       
   171      e4 := l add:'four' after:e3.
       
   172      self assert:(l firstLink == e1).
       
   173      self assert:(e1 nextLink == e2).
       
   174      self assert:(e2 nextLink == e2_5).
       
   175      self assert:(e2_5 nextLink == e3).
       
   176      self assert:(e3 nextLink == e4).
       
   177      self assert:(e4 nextLink isNil).
       
   178 
       
   179      self assert:(l lastLink == e4).
       
   180      self assert:(e4 previousLink == e3).
       
   181      self assert:(e3 previousLink == e2_5).
       
   182      self assert:(e2_5 previousLink == e2).
       
   183      self assert:(e2 previousLink == e1).
       
   184      self assert:(e1 previousLink isNil).
       
   185     "
       
   186 !
       
   187 
       
   188 addFirst:aLinkOrAnyOtherObject
       
   189     "adds aLink to the beginning of the sequence. Returns aLink"
       
   190 
       
   191     |newLink|
       
   192 
       
   193     newLink := aLinkOrAnyOtherObject asDoubleLink.
       
   194 
       
   195     newLink nextLink:firstLink.
       
   196     firstLink isNil ifTrue:[
       
   197         lastLink := newLink
       
   198     ] ifFalse: [
       
   199         firstLink previousLink:newLink
       
   200     ].
       
   201     firstLink := newLink.
       
   202     numberOfNodes := numberOfNodes + 1.
       
   203     ^ newLink
       
   204 
       
   205     "
       
   206      |l e1 e0|
       
   207      l := DoubleLinkedList new.
       
   208      e1 := l add:'one'.
       
   209      e0 := l addFirst:'zero'.
       
   210      self assert:(l firstLink == e0).
       
   211      self assert:(l lastLink == e1).
       
   212      self assert:(e0 nextLink == e1).
       
   213      self assert:(e1 nextLink isNil).
       
   214      self assert:(e0 previousLink isNil).
       
   215      self assert:(e1 previousLink == e0).
       
   216     "
       
   217 !
       
   218 
       
   219 remove:aLinkOrValue ifAbsent:exceptionBlock
       
   220     "remove the argument, aLinkOrValue from the sequence and return it;
       
   221      if absent, evaluate the exceptionBlock."
       
   222 
       
   223     |linkToRemove this nextLink previousLink|
       
   224 
       
   225     aLinkOrValue asDoubleLink == aLinkOrValue ifTrue:[
       
   226         linkToRemove := aLinkOrValue
       
   227     ] ifFalse:[
       
   228         this := firstLink.
       
   229         [this notNil and:[this value ~= aLinkOrValue]] whileTrue:[
       
   230             this := this nextLink
       
   231         ].
       
   232         this isNil ifTrue:[
       
   233             ^ exceptionBlock value
       
   234         ].
       
   235         linkToRemove := this.
       
   236     ].
       
   237 
       
   238     nextLink := linkToRemove nextLink.
       
   239     previousLink := linkToRemove previousLink.
       
   240     nextLink notNil ifTrue:[
       
   241         nextLink previousLink:previousLink.
       
   242     ] ifFalse:[
       
   243         lastLink := previousLink
       
   244     ].
       
   245     previousLink notNil ifTrue:[
       
   246         previousLink nextLink:nextLink.
       
   247     ] ifFalse:[
       
   248         firstLink := nextLink
       
   249     ].
       
   250     numberOfNodes := numberOfNodes - 1.
       
   251     ^ linkToRemove
       
   252 
       
   253     "
       
   254      |l e1 e2 e3 e2_5 e4|
       
   255      l := DoubleLinkedList new.
       
   256      e1 := l add:'one'.
       
   257      e2 := l add:'two'.
       
   258      e3 := l add:'three'.
       
   259      self assert:(l firstLink == e1).
       
   260      self assert:(e1 nextLink == e2).
       
   261      self assert:(e2 nextLink == e3).
       
   262      self assert:(e3 nextLink isNil).
       
   263 
       
   264      self assert:(l lastLink == e3).
       
   265      self assert:(e3 previousLink == e2).
       
   266      self assert:(e2 previousLink == e1).
       
   267      self assert:(e1 previousLink isNil).
       
   268 
       
   269      l remove:'two'.
       
   270      self assert:(l firstLink == e1).
       
   271      self assert:(e1 nextLink == e3).
       
   272      self assert:(e3 nextLink isNil).
       
   273 
       
   274      self assert:(l lastLink == e3).
       
   275      self assert:(e3 previousLink == e1).
       
   276      self assert:(e1 previousLink isNil).
       
   277 
       
   278      l remove:'one'.
       
   279      self assert:(l firstLink == e3).
       
   280      self assert:(e3 nextLink isNil).
       
   281 
       
   282      self assert:(l lastLink == e3).
       
   283      self assert:(e3 previousLink isNil).
       
   284 
       
   285      l remove:'three'.
       
   286      self assert:(l size == 0).
       
   287     "
       
   288 !
       
   289 
       
   290 removeFirst
       
   291     "remove and return the first node from the sequence"
       
   292 
       
   293     |link|
       
   294 
       
   295     firstLink isNil ifTrue:[
       
   296         ^ self emptyCollectionError
       
   297     ].
       
   298     link := firstLink.
       
   299     firstLink := firstLink nextLink.
       
   300     firstLink isNil ifTrue:[
       
   301         lastLink := nil
       
   302     ] ifFalse:[ 
       
   303         firstLink previousLink:nil.
       
   304     ].        
       
   305     link nextLink:nil.
       
   306     link previousLink:nil.
       
   307     numberOfNodes := numberOfNodes - 1.
       
   308     ^ link
       
   309 
       
   310     "
       
   311      |l v1 v2 v3 e1 e2 e3 e2_5 e4|
       
   312 
       
   313      l := DoubleLinkedList new.
       
   314      e1 := l add:'one'.
       
   315      e2 := l add:'two'.
       
   316      e3 := l add:'three'.
       
   317      self assert:(l firstLink == e1).
       
   318      self assert:(e1 nextLink == e2).
       
   319      self assert:(e2 nextLink == e3).
       
   320      self assert:(e3 nextLink isNil).
       
   321 
       
   322      self assert:(l lastLink == e3).
       
   323      self assert:(e3 previousLink == e2).
       
   324      self assert:(e2 previousLink == e1).
       
   325      self assert:(e1 previousLink isNil).
       
   326 
       
   327      l removeFirst.
       
   328      self assert:(l firstLink == e2).
       
   329      self assert:(e2 nextLink == e3).
       
   330      self assert:(e3 nextLink isNil).
       
   331 
       
   332      self assert:(l lastLink == e3).
       
   333      self assert:(e3 previousLink == e2).
       
   334      self assert:(e2 previousLink isNil).
       
   335 
       
   336      l removeFirst.
       
   337      self assert:(l firstLink == e3).
       
   338      self assert:(e3 nextLink isNil).
       
   339 
       
   340      self assert:(l lastLink == e3).
       
   341      self assert:(e3 previousLink isNil).
       
   342 
       
   343      l removeFirst.
       
   344      self assert:(l size == 0).
       
   345     "
       
   346 !
       
   347 
       
   348 removeIdentical:aLinkOrValue ifAbsent:exceptionBlock
       
   349     "remove the argument, aLinkOrValue from the sequence and return it;
       
   350      if absent, evaluate the exceptionBlock."
       
   351 
       
   352     |linkToRemove this nextLink previousLink|
       
   353 
       
   354     aLinkOrValue asDoubleLink == aLinkOrValue ifTrue:[
       
   355         linkToRemove := aLinkOrValue
       
   356     ] ifFalse:[
       
   357         this := firstLink.
       
   358         [this notNil and:[this value ~~ aLinkOrValue]] whileTrue:[
       
   359             this := this nextLink
       
   360         ].
       
   361         this isNil ifTrue:[
       
   362             ^ exceptionBlock value
       
   363         ].
       
   364         linkToRemove := this.
       
   365     ].
       
   366 
       
   367     nextLink := linkToRemove nextLink.
       
   368     previousLink := linkToRemove previousLink.
       
   369     nextLink notNil ifTrue:[
       
   370         nextLink previousLink:previousLink.
       
   371     ] ifFalse:[
       
   372         lastLink := previousLink
       
   373     ].
       
   374     previousLink notNil ifTrue:[
       
   375         previousLink nextLink:nextLink.
       
   376     ] ifFalse:[
       
   377         firstLink := nextLink
       
   378     ].
       
   379     numberOfNodes := numberOfNodes - 1.
       
   380     ^ linkToRemove
       
   381 
       
   382     "
       
   383      |l v1 v2 v3 e1 e2 e3 e2_5 e4|
       
   384      l := DoubleLinkedList new.
       
   385      e1 := l add:(v1 := 'one').
       
   386      e2 := l add:(v2 := 'two').
       
   387      e3 := l add:(v3 := 'three').
       
   388      self assert:(l firstLink == e1).
       
   389      self assert:(e1 nextLink == e2).
       
   390      self assert:(e2 nextLink == e3).
       
   391      self assert:(e3 nextLink isNil).
       
   392 
       
   393      self assert:(l lastLink == e3).
       
   394      self assert:(e3 previousLink == e2).
       
   395      self assert:(e2 previousLink == e1).
       
   396      self assert:(e1 previousLink isNil).
       
   397 
       
   398      l removeIdentical:v2.
       
   399      self assert:(l firstLink == e1).
       
   400      self assert:(e1 nextLink == e3).
       
   401      self assert:(e3 nextLink isNil).
       
   402 
       
   403      self assert:(l lastLink == e3).
       
   404      self assert:(e3 previousLink == e1).
       
   405      self assert:(e1 previousLink isNil).
       
   406 
       
   407      l removeIdentical:v1.
       
   408      self assert:(l firstLink == e3).
       
   409      self assert:(e3 nextLink isNil).
       
   410 
       
   411      self assert:(l lastLink == e3).
       
   412      self assert:(e3 previousLink isNil).
       
   413 
       
   414      l removeIdentical:v3.
       
   415      self assert:(l size == 0).
       
   416     "
       
   417 !
       
   418 
       
   419 removeLast
       
   420     "remove and return the last node from the sequence"
       
   421 
       
   422     |link|
       
   423 
       
   424     lastLink isNil ifTrue:[
       
   425         ^ self emptyCollectionError
       
   426     ].
       
   427     link := lastLink.
       
   428     lastLink := lastLink previousLink.
       
   429     lastLink isNil ifTrue:[
       
   430         firstLink := nil
       
   431     ] ifFalse:[ 
       
   432         lastLink nextLink:nil.
       
   433     ].        
       
   434     link nextLink:nil.
       
   435     link previousLink:nil.
       
   436     numberOfNodes := numberOfNodes - 1.
       
   437     ^ link
       
   438 
       
   439     "
       
   440      |l v1 v2 v3 e1 e2 e3 e2_5 e4|
       
   441 
       
   442      l := DoubleLinkedList new.
       
   443      e1 := l add:'one'.
       
   444      e2 := l add:'two'.
       
   445      e3 := l add:'three'.
       
   446      self assert:(l firstLink == e1).
       
   447      self assert:(e1 nextLink == e2).
       
   448      self assert:(e2 nextLink == e3).
       
   449      self assert:(e3 nextLink isNil).
       
   450 
       
   451      self assert:(l lastLink == e3).
       
   452      self assert:(e3 previousLink == e2).
       
   453      self assert:(e2 previousLink == e1).
       
   454      self assert:(e1 previousLink isNil).
       
   455 
       
   456      l removeLast.
       
   457      self assert:(l firstLink == e1).
       
   458      self assert:(e1 nextLink == e2).
       
   459      self assert:(e2 nextLink isNil).
       
   460 
       
   461      self assert:(l lastLink == e2).
       
   462      self assert:(e2 previousLink == e1).
       
   463      self assert:(e1 previousLink isNil).
       
   464 
       
   465      l removeLast.
       
   466      self assert:(l firstLink == e1).
       
   467      self assert:(e1 nextLink isNil).
       
   468 
       
   469      self assert:(l lastLink == e1).
       
   470      self assert:(e1 previousLink isNil).
       
   471 
       
   472      l removeLast.
       
   473      self assert:(l size == 0).
       
   474     "
       
   475 ! !
       
   476 
       
   477 !DoubleLinkedList class methodsFor:'documentation'!
       
   478 
       
   479 version
       
   480     ^ '$Header$'
       
   481 !
       
   482 
       
   483 version_CVS
       
   484     ^ '$Header$'
       
   485 ! !
       
   486