@@ -1614,44 +1614,32 @@ def zfill(self, width):
16141614
16151615import collections .abc
16161616import heapq
1617- from typing import Any , Dict , Iterator , List , Optional , Tuple , TypeVar , Union
1617+ import sys
16181618
1619- K = TypeVar ('K' )
1620- V = TypeVar ('V' )
1619+ # Use string forward references for type annotations to avoid circular imports
1620+ if sys .version_info >= (3 , 7 ):
1621+ from __future__ import annotations
16211622
16221623class HeapDict (collections .abc .MutableMapping ):
16231624 """Dictionary that maintains heap property based on values.
16241625
16251626 HeapDict combines the functionality of a dictionary with a heap,
16261627 providing efficient access to key-value pairs while maintaining
16271628 a heap property for priority-based operations.
1628-
1629- Basic operations:
1630- - d[key] = value: Set a key-value pair
1631- - value = d[key]: Get value by key
1632- - del d[key]: Remove a key-value pair
1633- - key in d: Test if key exists
1634- - len(d): Get number of items
1635- - iter(d): Iterate through keys
1636-
1637- Heap operations:
1638- - d.popmin(): Remove and return the (key, value) pair with minimum value
1639- - d.peekmin(): Return the (key, value) pair with minimum value without removing
1640- - d.update_priority(key, new_value): Update the value/priority of an existing key
16411629 """
16421630
16431631 def __init__ (self , * args , ** kwargs ):
16441632 """Initialize a new HeapDict with optional initial values."""
1645- self ._dict : Dict [ K , V ] = {} # Maps keys to values
1646- self ._heap : List [ Tuple [ V , K , int ]] = [] # List of (value, key, counter)
1633+ self ._dict = {} # Maps keys to values
1634+ self ._heap = [] # List of (value, key, counter)
16471635 self ._counter = 0 # Used to break ties for values that compare equal
16481636 self ._removed_keys = set () # Track removed keys for lazy deletion
16491637
16501638 # Add initial items
16511639 if args or kwargs :
16521640 self .update (* args , ** kwargs )
16531641
1654- def __setitem__ (self , key : K , value : V ) -> None :
1642+ def __setitem__ (self , key , value ) :
16551643 """Set a key-value pair, maintaining heap property."""
16561644 if key in self ._dict :
16571645 self .update_priority (key , value )
@@ -1661,37 +1649,32 @@ def __setitem__(self, key: K, value: V) -> None:
16611649 self ._counter += 1
16621650 heapq .heappush (self ._heap , (value , key , count ))
16631651
1664- def __getitem__ (self , key : K ) -> V :
1652+ def __getitem__ (self , key ) :
16651653 """Get value by key."""
16661654 return self ._dict [key ]
16671655
1668- def __delitem__ (self , key : K ) -> None :
1656+ def __delitem__ (self , key ) :
16691657 """Remove a key-value pair."""
16701658 if key not in self ._dict :
16711659 raise KeyError (key )
16721660
16731661 # Mark the key as removed
16741662 self ._removed_keys .add (key )
1675-
1676- # Remove from dictionary
16771663 del self ._dict [key ]
1678-
1679- # Note: We don't remove from the heap here for efficiency.
1680- # Instead, we do lazy deletion during heap operations.
16811664
1682- def __iter__ (self ) -> Iterator [ K ] :
1665+ def __iter__ (self ):
16831666 """Iterate through keys."""
16841667 return iter (self ._dict )
16851668
1686- def __len__ (self ) -> int :
1669+ def __len__ (self ):
16871670 """Return the number of items."""
16881671 return len (self ._dict )
16891672
1690- def __repr__ (self ) -> str :
1673+ def __repr__ (self ):
16911674 """Return string representation."""
16921675 return f"{ self .__class__ .__name__ } ({ dict (self .items ())} )"
16931676
1694- def _clean_heap (self ) -> None :
1677+ def _clean_heap (self ):
16951678 """Clean the heap by removing marked items."""
16961679 if len (self ._removed_keys ) > len (self ._heap ) // 2 :
16971680 # If too many removed items, rebuild the heap
@@ -1700,7 +1683,7 @@ def _clean_heap(self) -> None:
17001683 self ._heap = new_heap
17011684 self ._removed_keys .clear ()
17021685
1703- def popmin (self ) -> Tuple [ K , V ] :
1686+ def popmin (self ):
17041687 """Remove and return the (key, value) pair with minimum value."""
17051688 if not self ._dict :
17061689 raise KeyError ("popmin from an empty HeapDict" )
@@ -1712,10 +1695,9 @@ def popmin(self) -> Tuple[K, V]:
17121695 del self ._dict [key ]
17131696 return key , value
17141697
1715- # This should never happen if the data structure is consistent
17161698 raise RuntimeError ("Heap is inconsistent with dictionary" )
17171699
1718- def peekmin (self ) -> Tuple [ K , V ] :
1700+ def peekmin (self ):
17191701 """Return the (key, value) pair with minimum value without removing it."""
17201702 if not self ._dict :
17211703 raise KeyError ("peekmin from an empty HeapDict" )
@@ -1725,29 +1707,38 @@ def peekmin(self) -> Tuple[K, V]:
17251707 value , key , _ = self ._heap [0 ]
17261708 if key not in self ._removed_keys and key in self ._dict :
17271709 return key , value
1728-
1729- # If the top item is removed, pop it and continue
17301710 heapq .heappop (self ._heap )
17311711
1732- # This should never happen if the data structure is consistent
17331712 raise RuntimeError ("Heap is inconsistent with dictionary" )
17341713
1735- def update_priority (self , key : K , new_value : V ) -> None :
1714+ def update_priority (self , key , new_value ) :
17361715 """Update the value/priority of an existing key."""
17371716 if key not in self ._dict :
17381717 raise KeyError (key )
17391718
17401719 # Update the dictionary
17411720 self ._dict [key ] = new_value
1742-
1743- # Mark the old entry as removed
17441721 self ._removed_keys .add (key )
1745-
1746- # Add a new entry to the heap
17471722 count = self ._counter
17481723 self ._counter += 1
17491724 heapq .heappush (self ._heap , (new_value , key , count ))
17501725
1751- # Clean the heap if there are too many removed items
17521726 if len (self ._removed_keys ) > len (self ._heap ) // 2 :
1753- self ._clean_heap ()
1727+ self ._clean_heap ()
1728+
1729+ # Add type hints for older Python versions or static type checkers
1730+ if sys .version_info < (3 , 7 ) or typing .TYPE_CHECKING :
1731+ from typing import Any , Dict , Iterator , List , Optional , Tuple , TypeVar , Union
1732+ K = TypeVar ('K' )
1733+ V = TypeVar ('V' )
1734+ HeapDict .__annotations__ = {
1735+ '_dict' : Dict [K , V ],
1736+ '_heap' : List [Tuple [V , K , int ]],
1737+ '__setitem__' : None ,
1738+ '__getitem__' : None ,
1739+ '__delitem__' : None ,
1740+ '__iter__' : Iterator [K ],
1741+ 'popmin' : Tuple [K , V ],
1742+ 'peekmin' : Tuple [K , V ],
1743+ 'update_priority' : None
1744+ }
0 commit comments