³ò ñ]„Gc@sOdZddkZdd d„ƒYZdd d„ƒYZdd d„ƒYZdS( sÉpyskip.py: A container class for ordered sets in Python. $Revision: 1.22 $ $Date: 2008/01/09 05:38:30 $ For documentation, see: http://www.nmt.edu/tcc/help/lang/python/examples/pyskip/ iÿÿÿÿNt _SkipItemcBseZdZd„ZRS(sRepresents one child element of a SkipList. Exports: _SkipItem ( child, nLevels ): [ (child is a child object) and (nLevels is an integer >= 1) -> return a new _SkipItem with that child object and (nLevels) forward links, each set to None ] .child: [ as passed to constructor, read-only ] .links: [ if self is an active SkipList element -> a list of nLevels elements, read-write, containing pointers to a _SkipItem instance else -> a list of at least 1 whose first element is None ] cCs||_dg||_dS(sConstructor for _SkipItemN(tchildtNonetlinks(tselfRtnLevels((s-/u/www/docs/tcc/projects/pystyler/skiplist.pyt__init__Œs (t__name__t __module__t__doc__R(((s-/u/www/docs/tcc/projects/pystyler/skiplist.pyRxst_SkipListIteratorcBs)eZdZd„Zd„Zd„ZRS(s‘Represents an active iterator over a SkipList object. Exports: _SkipListIterator ( skipItem ): [ skipItem is a _SkipItem -> return a new iterator whose next item is skipItem, or which is at end of list if skipItem's forward link points to itself ] .skipItem: [ if self is exhausted -> a terminator _SkipItem else -> a _SkipItem containing the value that will be returned next time ] .__iter__(self): [ returns self ] .next(): [ if self.skipItem's level-0 link is None -> raise ValueError else if self.skipItem.links[0] == self.skipItem -> raise StopIteration else -> self.skipItem := self.skipItem.links[0] return self.skipItem.child ] # *Before* advancing! cCs ||_dS(s!Constructor for _SkipListIteratorN(tskipItem(RR ((s-/u/www/docs/tcc/projects/pystyler/skiplist.pyR¯scCso|iiddjo td‚nH|iid|ijo t‚n$|ii}|iid|_|SdS(s&Return the next child item and advanceis"Iterator points to a deleted item.N(R RRt ValueErrort StopIterationR(Rtresult((s-/u/www/docs/tcc/projects/pystyler/skiplist.pytnextµs   cCs|S(sReturns the iterator itself.((R((s-/u/www/docs/tcc/projects/pystyler/skiplist.pyt__iter__Ás(RRR RRR(((s-/u/www/docs/tcc/projects/pystyler/skiplist.pyR “s  tSkipListcBsïeZdZdZeeddd„Zd„Zd„Zd„Zd„Z d „Z d „Z d „Z d „Z d „Zd„Zd„Zd„Zd„Zd„Zd„Zd„Zd„Zd„Zd„Zd„Zd„Zd„ZRS(sd Container class for ordered sets. Exports: SkipList ( keyFun=None, cmpFun=None, allowDups=0, count=1000000 ): [ (keyFun is a function that returns the key for a given child object) and (cmpFun is a function that compares two keys, using the usual Python convention for the cmp() function, or None use the built-in cmp() function) and (allowDups is 0 to refuse duplicate entries or 1 to allow them) and (count is a worst-case maximum element count) -> return a new, empty SkipList instance with those properties ] .insert(c): [ c is a child object -> if ((self contains an object whose key equals the key of e) and (self.allowDups is false)) -> raise KeyError else -> self := self with e added as a new child object ] .delete(k): [ k is in the key domain -> if self contains any child objects with keys equal to k -> self := self with the first-inserted such child object deleted return that child object else -> return None ] .match(k): [ k is in the key domain -> if self contains any child objects whose keys equal k -> return the first such child object else -> raise KeyError ] .find(k): [ k is in the key domain -> if self contains any child objects whose keys are >= k -> return an iterator that will iterate over all child objects whose keys are >= k, in order ] .__len__(self): [ return the number of child objects in self ] .__iter__(self): [ return an iterator that will iterate over all the child objects in self in order ] .__contains__(self, k): [ if self contains any child objects whose keys equal k -> return 1 else -> return 0 ] .__delitem__(self, k): [ same as self.delete(k) ] .__getitem__(self, k): [ same as self.match(k) ] .nSearches: [INVARIANT: Number of searches performed ] .nCompares: [INVARIANT: Number of child pairs compared ] gÐ?ii@BcCs¿||_||_||_d|_d|_d|_d|_|i|ƒ|_t d|iƒ|_ t d|iƒ|_ x=t |iƒD],}|i |i i|<|i |i i| return ceiling(log base 4(n)) + 1 ] iii((RtnR((s-/u/www/docs/tcc/projects/pystyler/skiplist.pyt__estimateLevels;s  cCs—|i|ƒ}|i|ƒ}|d}|id}|i o3||ij o#|i||ƒdjo t‚n|i||ƒ|id|_dS(s.Insert a new child element into the skip list.iiN( t_SkipList__keyOft_SkipList__insertCutListRRRt_SkipList__compareItemKeyR t_SkipList__insertItemR(RRtkeytcutListtprevItemtnextItem((s-/u/www/docs/tcc/projects/pystyler/skiplist.pytinsertPs    cCs#|io|i|ƒSn|SdS(s}Return the child's key. [ child is in the child domain of self -> return key-of ( child ) ] N(R(RR((s-/u/www/docs/tcc/projects/pystyler/skiplist.pyt__keyOfts cCss|ig|i}|i}x@t|idddƒD]%}|i|||ƒ}||| return insertion-cut-list(key) ] iiÿÿÿÿ(RRRRt_SkipList__insertPointR(RR&Rt searchItemtlevel((s-/u/www/docs/tcc/projects/pystyler/skiplist.pyt__insertCutList€s  cCsE|}|i|}x+|i||ƒo|}|i|}qW|S(s®Find the insertion point at a given level. [ insertion-precedes(searchItem, key) -> return insertion-point-after ( level, key, searchItem) ] (Rt_SkipList__insertionPrecedes(RR-R.R&R(R)((s-/u/www/docs/tcc/projects/pystyler/skiplist.pyt __insertPointŸs  cCsP||ijodSn|i||ƒ}|io|djSn |djSdS(sÞDoes this _SkipItem precede this key for insertion? [ skipItem is not self.__heads -> return keys-are-ordered ( key-of ( skipItem's child ), key ) ] iN(RR$R(RR R&t comparison((s-/u/www/docs/tcc/projects/pystyler/skiplist.pyt__insertionPrecedes¾s  cCs/|i|iƒ}|id|_t||ƒS(s…Compare the key from a _SkipItem to a key in the key domain. [ return cmp ( key-of ( skipItem's child ), keyB ) ] i(R"RRtcmp(RR tkeyBtkeyA((s-/u/www/docs/tcc/projects/pystyler/skiplist.pyt__compareItemKeyàscCs2|iƒ}t||ƒ}|i|||ƒdS(sI [ cutList is insertion-cut-list(key-of(child)) -> self := self with a new _SkipItem, with child=(child), inserted after the items pointed at by the first n levels of cutList, where n is in the range [1,self.__maxLevels] ] N(t_SkipList__pickLevelRt_SkipList__insertRelink(RRR'tlevelstnewItem((s-/u/www/docs/tcc/projects/pystyler/skiplist.pyt __insertItemîs cCsmd}t|id|iƒ}x2tiƒ|ijo||jo|d}q"Wt|i|ƒ|_|S(sÞInto how many levels should an insertion be linked? [ self.__nLevels := max ( self.__nLevels, a randomly chosen integer in [1,self.__maxLevels] ) return that same integer ] i(tminRRtrandomtNEW_LEVEL_PROBABILITYtmax(RRt maxNewLevel((s-/u/www/docs/tcc/projects/pystyler/skiplist.pyt __pickLevel s cCsLxEt|ƒD]7}||}|i|}||i|<||i| self := self with newItem linked into the first (levels) lists, just after the element pointed at by the corresponding element of cutList ] N(RR(RR:R'R;RR(tsuccItem((s-/u/www/docs/tcc/projects/pystyler/skiplist.pyt__insertRelink!s    cCsË|i|ƒ}|d}|id}||ijp|i||ƒdjotSnxMt|iƒD]<}||}|i||jo|i||i| return search-cut-list ( key ) ] iiÿÿÿÿ(RRRRt_SkipList__searchPointR(RR&RR-R((s-/u/www/docs/tcc/projects/pystyler/skiplist.pyt__searchCutListns  cCsE|}|i|}x+|i||ƒo|}|i|}qW|S(sSearch one level of the skip list for a given key. [ ( level is in [0,self.__maxLevels ) ) and ( search-precedes ( searchItem, key ) ) -> return search-point-after ( level, key, searchItem ) ] (Rt_SkipList__searchPrecedes(RR-R.R&R(R)((s-/u/www/docs/tcc/projects/pystyler/skiplist.pyt __searchPointŒs  cCsA||ijodSn|i||ƒdjodSndSdS(sDoes this item precede the item with a given key? [ ( skipItem is a _SkipItem ) and ( key is in self's key domain) -> if search-precedes ( skipItem, key ) -> return 1 else -> return 0 ] iiN(RR$(RR R&((s-/u/www/docs/tcc/projects/pystyler/skiplist.pyt__searchPrecedes§s cCsa|i|ƒ}|id}||ij o$|i||ƒdjo |iSntd|‚dS(s;Return the first or only child with the given key. isKey not found: %sN(t_SkipList__searchCutItemRRR$RtKeyError(RR&R(R-((s-/u/www/docs/tcc/projects/pystyler/skiplist.pytmatchÀs   cCsV|i}x6t|idddƒD]}|i|||ƒ}q#W|id|_|S(s—Find the level-0 predecessor of the given key. [ key is in self's key domain -> return search-point(0, key).link[0] ] iiÿÿÿÿ(RRRRGR(RR&R-R((s-/u/www/docs/tcc/projects/pystyler/skiplist.pyt__searchCutItemÕs cCs&|i|ƒ}|id}t|ƒS(s8Return an iterator starting at a given position i(RLRR (RR&R(R-((s-/u/www/docs/tcc/projects/pystyler/skiplist.pytfindîs cCs|iS(s%Returns the number of child elements.(R(R((s-/u/www/docs/tcc/projects/pystyler/skiplist.pyt__len__ùscCst|iidƒS(sIterator for the entire listi(R RR(R((s-/u/www/docs/tcc/projects/pystyler/skiplist.pyRþscCs5y|i|ƒ}dSWntj o dSnXdS(s Does self contain the given key?iiN(RNRM(RR&R((s-/u/www/docs/tcc/projects/pystyler/skiplist.pyt __contains__s cCs|i|ƒdS(s/Delete the first or only item with a given key.N(RF(RR&((s-/u/www/docs/tcc/projects/pystyler/skiplist.pyt __delitem__ scCs |i|ƒS(s,Get the first or only item with a given key.(RN(RR&((s-/u/www/docs/tcc/projects/pystyler/skiplist.pyt __getitem__s(RRR R?RRRR*R"R#R,R0R$R%R8R9RFRERGRIRNRLRPRQRRRRSRT(((s-/u/www/docs/tcc/projects/pystyler/skiplist.pyRÆs46    $   "    % (        ((((R R>RR R(((s-/u/www/docs/tcc/projects/pystyler/skiplist.pyss p3