22
33# Default configuration constants
44DEFAULT_UNIT_SIZE = 3
5- DEFAULT_FILL_CHAR = "_"
6- DEFAULT_EMPTY_FILL_CHAR = "_"
5+ DEFAULT_VALUE_FILL_CHAR = "_"
6+ DEFAULT_GAP_FILL_CHAR = "_"
77
88
99class BinaryNode :
@@ -80,15 +80,15 @@ def center(val, unitSize=None, fillChar=None):
8080 Args:
8181 val: The value to center
8282 unitSize: The total width of the output string (uses DEFAULT_UNIT_SIZE if None)
83- fillChar: The character to use for padding (uses DEFAULT_FILL_CHAR "_" if None)
83+ fillChar: The character to use for padding (uses DEFAULT_VALUE_FILL_CHAR "_" if None)
8484
8585 Returns:
8686 A centered string representation of val
8787 """
8888 if unitSize is None :
8989 unitSize = DEFAULT_UNIT_SIZE
9090 if fillChar is None :
91- fillChar = DEFAULT_FILL_CHAR
91+ fillChar = DEFAULT_VALUE_FILL_CHAR
9292 return str (val ).center (unitSize , fillChar )
9393
9494
@@ -107,7 +107,7 @@ def getDepth(node: BinaryNode):
107107 return 1 + max (getDepth (node .left ), getDepth (node .right ))
108108
109109
110- def register (node : BinaryNode , fillChar = None , unitSize = None , code = "" , mem = None ):
110+ def register (node : BinaryNode , valueFillChar = None , unitSize = None , code = "" , mem = None ):
111111 """
112112 Recursively registers all nodes in a tree with their binary path codes.
113113
@@ -118,21 +118,21 @@ def register(node: BinaryNode, fillChar=None, unitSize=None, code="", mem=None):
118118
119119 Args:
120120 node: The current node being processed
121- fillChar : Character used for padding node values (uses DEFAULT_FILL_CHAR "_" if None)
121+ valueFillChar : Character used for padding node values (uses DEFAULT_VALUE_FILL_CHAR "_" if None)
122122 unitSize: Size for centering values (uses DEFAULT_UNIT_SIZE if None)
123123 code: The binary path code for the current node
124124 mem: Dictionary mapping binary codes to centered node values
125125 """
126126 if mem is None :
127127 mem = {}
128128 if node :
129- mem [code ] = center (node .val , unitSize = unitSize , fillChar = fillChar )
130- register (node .left , fillChar = fillChar , unitSize = unitSize , code = code + "0" , mem = mem )
131- register (node .right , fillChar = fillChar , unitSize = unitSize , code = code + "1" , mem = mem )
129+ mem [code ] = center (node .val , unitSize = unitSize , fillChar = valueFillChar )
130+ register (node .left , valueFillChar = valueFillChar , unitSize = unitSize , code = code + "0" , mem = mem )
131+ register (node .right , valueFillChar = valueFillChar , unitSize = unitSize , code = code + "1" , mem = mem )
132132 return mem
133133
134134
135- def nodeToMat (node : BinaryNode , depth = - 1 , fillChar = None , emptyFillChar = None , unitSize = None , removeEmpty = True ):
135+ def nodeToMat (node : BinaryNode , depth = - 1 , valueFillChar = None , gapFillChar = None , unitSize = None , removeEmpty = True ):
136136 """
137137 Converts a binary tree into a 2D matrix representation for visualization.
138138
@@ -143,8 +143,8 @@ def nodeToMat(node: BinaryNode, depth=-1, fillChar=None, emptyFillChar=None, uni
143143 Args:
144144 node: The root node of the tree to visualize
145145 depth: The depth of the tree (-1 for auto-calculation)
146- fillChar : Character for padding node values (uses DEFAULT_FILL_CHAR "_" if None)
147- emptyFillChar : Character for empty cells within valueIndexes (uses DEFAULT_EMPTY_FILL_CHAR "_" if None)
146+ valueFillChar : Character for padding node values (uses DEFAULT_VALUE_FILL_CHAR "_" if None)
147+ gapFillChar : Character for filling gaps between pairs (uses DEFAULT_GAP_FILL_CHAR "_" if None)
148148 unitSize: Size for centering (uses DEFAULT_UNIT_SIZE if None)
149149 removeEmpty: Whether to remove empty leading columns
150150
@@ -153,23 +153,24 @@ def nodeToMat(node: BinaryNode, depth=-1, fillChar=None, emptyFillChar=None, uni
153153 """
154154 if unitSize is None :
155155 unitSize = DEFAULT_UNIT_SIZE
156- if fillChar is None :
157- fillChar = DEFAULT_FILL_CHAR
158- if emptyFillChar is None :
159- emptyFillChar = DEFAULT_EMPTY_FILL_CHAR
156+ if valueFillChar is None :
157+ valueFillChar = DEFAULT_VALUE_FILL_CHAR
158+ if gapFillChar is None :
159+ gapFillChar = DEFAULT_GAP_FILL_CHAR
160160
161161 if depth == - 1 :
162162 depth = getDepth (node )
163163
164164 # Register all nodes with their binary path codes
165- tree = register (node , fillChar = fillChar , unitSize = unitSize , code = "" , mem = {})
165+ tree = register (node , valueFillChar = valueFillChar , unitSize = unitSize , code = "" , mem = {})
166166
167167 # Create matrix: (2*depth - 1) rows x (2^depth - 1) columns
168168 # Initialize with space-centered empty cells
169169 mat = [[center ("" , unitSize = unitSize , fillChar = " " ) for _ in range (2 ** depth - 1 )] for _ in range (2 * depth - 1 )]
170170
171171 # Start with all even column indices (where values can be placed)
172172 valueIndexes = [i for i in range (2 ** depth - 1 ) if i % 2 == 0 ]
173+ prev = None
173174
174175 # Build matrix from bottom to top
175176 for level in range (2 * (depth - 1 ), - 1 , - 1 ):
@@ -178,11 +179,20 @@ def nodeToMat(node: BinaryNode, depth=-1, fillChar=None, emptyFillChar=None, uni
178179 for i , index in enumerate (valueIndexes ):
179180 mat [level ][index ] = [center ("/" , unitSize = unitSize , fillChar = " " ), center ("\\ " , unitSize = unitSize , fillChar = " " )][i % 2 ]
180181
182+ # Fill gaps between pairs in previous level
183+ if prev is not None :
184+ for i in range (0 , len (prev ), 2 ):
185+ if i + 1 < len (prev ):
186+ # Fill columns between prev[i] and prev[i+1]
187+ for col in range (prev [i ] + 1 , prev [i + 1 ]):
188+ mat [level + 1 ][col ] = center ("" , unitSize = unitSize , fillChar = gapFillChar )
189+
181190 # Calculate parent positions (midpoints between child pairs)
182- newIndexes = []
191+ next = []
183192 for i in range (0 , len (valueIndexes ) - 1 , 2 ):
184- newIndexes .append ((valueIndexes [i ] + valueIndexes [i + 1 ]) // 2 )
185- valueIndexes = newIndexes
193+ next .append ((valueIndexes [i ] + valueIndexes [i + 1 ]) // 2 )
194+ prev = valueIndexes
195+ valueIndexes = next
186196 continue
187197
188198 # Even levels: place node values
@@ -191,7 +201,15 @@ def nodeToMat(node: BinaryNode, depth=-1, fillChar=None, emptyFillChar=None, uni
191201 codes = ["" .join (code ) for code in codes ]
192202
193203 for i , index in enumerate (valueIndexes ):
194- mat [level ][index ] = tree .get (codes [i ], center ("" , unitSize = unitSize , fillChar = emptyFillChar ))
204+ if codes [i ] in tree :
205+ mat [level ][index ] = tree [codes [i ]]
206+
207+ # Fill gaps for the last (bottom) level
208+ if prev is not None :
209+ for i in range (0 , len (prev ), 2 ):
210+ if i + 1 < len (prev ):
211+ for col in range (prev [i ] + 1 , prev [i + 1 ]):
212+ mat [2 * (depth - 1 )][col ] = center ("" , unitSize = unitSize , fillChar = gapFillChar )
195213
196214 # Remove empty leading columns if requested
197215 if removeEmpty :
@@ -214,20 +232,20 @@ def nodeToMat(node: BinaryNode, depth=-1, fillChar=None, emptyFillChar=None, uni
214232 return mat
215233
216234
217- def nodeToString (node : BinaryNode , depth = - 1 , fillChar = None , emptyFillChar = None , unitSize = None , removeEmpty = True ):
235+ def nodeToString (node : BinaryNode , depth = - 1 , valueFillChar = None , gapFillChar = None , unitSize = None , removeEmpty = True ):
218236 """
219237 Converts a binary tree into a string representation for visualization.
220238
221239 Args:
222240 node: The root node of the tree to visualize
223241 depth: The depth of the tree (-1 for auto-calculation)
224- fillChar : Character for padding node values (uses DEFAULT_FILL_CHAR if None)
225- emptyFillChar : Character for empty cells within valueIndexes (uses DEFAULT_EMPTY_FILL_CHAR if None)
242+ valueFillChar : Character for padding node values (uses DEFAULT_VALUE_FILL_CHAR "_" if None)
243+ gapFillChar : Character for filling gaps between pairs (uses DEFAULT_GAP_FILL_CHAR "_" if None)
226244 unitSize: Size for centering (uses DEFAULT_UNIT_SIZE if None)
227245 removeEmpty: Whether to remove empty leading columns
228246
229247 Returns:
230248 A string representation of the tree with each row on a new line
231249 """
232- mat = nodeToMat (node , depth = depth , fillChar = fillChar , emptyFillChar = emptyFillChar , unitSize = unitSize , removeEmpty = removeEmpty )
250+ mat = nodeToMat (node , depth = depth , valueFillChar = valueFillChar , gapFillChar = gapFillChar , unitSize = unitSize , removeEmpty = removeEmpty )
233251 return "\n " .join ("" .join (row ) for row in mat )
0 commit comments