core-data-structures 1.3.0__tar.gz → 1.4.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {core_data_structures-1.3.0 → core_data_structures-1.4.1}/PKG-INFO +3 -2
- {core_data_structures-1.3.0 → core_data_structures-1.4.1}/core_data_structures.egg-info/PKG-INFO +3 -2
- {core_data_structures-1.3.0 → core_data_structures-1.4.1}/core_data_structures.egg-info/SOURCES.txt +1 -0
- {core_data_structures-1.3.0 → core_data_structures-1.4.1}/core_data_structures.egg-info/requires.txt +1 -1
- {core_data_structures-1.3.0 → core_data_structures-1.4.1}/data_structures/__init__.py +1 -5
- {core_data_structures-1.3.0 → core_data_structures-1.4.1}/data_structures/base.py +5 -8
- {core_data_structures-1.3.0 → core_data_structures-1.4.1}/data_structures/graphs/__init__.py +1 -4
- {core_data_structures-1.3.0 → core_data_structures-1.4.1}/data_structures/graphs/graphs.py +28 -28
- {core_data_structures-1.3.0 → core_data_structures-1.4.1}/data_structures/graphs/vertex.py +9 -12
- {core_data_structures-1.3.0 → core_data_structures-1.4.1}/data_structures/lists/base.py +15 -17
- {core_data_structures-1.3.0 → core_data_structures-1.4.1}/data_structures/lists/double_linked_list.py +7 -8
- {core_data_structures-1.3.0 → core_data_structures-1.4.1}/data_structures/lists/singly_linked_list.py +1 -4
- {core_data_structures-1.3.0 → core_data_structures-1.4.1}/data_structures/trees/__init__.py +0 -3
- core_data_structures-1.4.1/data_structures/trees/base.py +44 -0
- core_data_structures-1.4.1/data_structures/trees/binary_tree.py +247 -0
- {core_data_structures-1.3.0 → core_data_structures-1.4.1}/data_structures/trees/simple_tree.py +2 -6
- {core_data_structures-1.3.0 → core_data_structures-1.4.1}/pyproject.toml +3 -2
- core_data_structures-1.4.1/setup.py +5 -0
- core_data_structures-1.3.0/data_structures/trees/binary_tree.py +0 -230
- core_data_structures-1.3.0/setup.py +0 -6
- {core_data_structures-1.3.0 → core_data_structures-1.4.1}/LICENSE +0 -0
- {core_data_structures-1.3.0 → core_data_structures-1.4.1}/README.rst +0 -0
- {core_data_structures-1.3.0 → core_data_structures-1.4.1}/core_data_structures.egg-info/dependency_links.txt +0 -0
- {core_data_structures-1.3.0 → core_data_structures-1.4.1}/core_data_structures.egg-info/top_level.txt +0 -0
- {core_data_structures-1.3.0 → core_data_structures-1.4.1}/data_structures/lists/__init__.py +0 -0
- {core_data_structures-1.3.0 → core_data_structures-1.4.1}/data_structures/py.typed +0 -0
- {core_data_structures-1.3.0 → core_data_structures-1.4.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: core-data-structures
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.1
|
|
4
4
|
Summary: This project/library contains commons data structures...
|
|
5
5
|
Author-email: Alejandro Cora González <alek.cora.glez@gmail.com>
|
|
6
6
|
Maintainer: Alejandro Cora González
|
|
@@ -22,6 +22,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
22
22
|
Classifier: Programming Language :: Python :: 3.13
|
|
23
23
|
Classifier: Programming Language :: Python :: 3.14
|
|
24
24
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
25
|
+
Classifier: Typing :: Typed
|
|
25
26
|
Requires-Python: >=3.9
|
|
26
27
|
Description-Content-Type: text/x-rst
|
|
27
28
|
License-File: LICENSE
|
|
@@ -29,7 +30,7 @@ Requires-Dist: core-mixins>=3.2.0
|
|
|
29
30
|
Requires-Dist: typing-extensions>=4.8.0
|
|
30
31
|
Provides-Extra: dev
|
|
31
32
|
Requires-Dist: core-dev-tools>=2.1.0; extra == "dev"
|
|
32
|
-
Requires-Dist: core-tests>=2.
|
|
33
|
+
Requires-Dist: core-tests>=2.3.0; extra == "dev"
|
|
33
34
|
Dynamic: license-file
|
|
34
35
|
|
|
35
36
|
core-data-structures
|
{core_data_structures-1.3.0 → core_data_structures-1.4.1}/core_data_structures.egg-info/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: core-data-structures
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.1
|
|
4
4
|
Summary: This project/library contains commons data structures...
|
|
5
5
|
Author-email: Alejandro Cora González <alek.cora.glez@gmail.com>
|
|
6
6
|
Maintainer: Alejandro Cora González
|
|
@@ -22,6 +22,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
22
22
|
Classifier: Programming Language :: Python :: 3.13
|
|
23
23
|
Classifier: Programming Language :: Python :: 3.14
|
|
24
24
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
25
|
+
Classifier: Typing :: Typed
|
|
25
26
|
Requires-Python: >=3.9
|
|
26
27
|
Description-Content-Type: text/x-rst
|
|
27
28
|
License-File: LICENSE
|
|
@@ -29,7 +30,7 @@ Requires-Dist: core-mixins>=3.2.0
|
|
|
29
30
|
Requires-Dist: typing-extensions>=4.8.0
|
|
30
31
|
Provides-Extra: dev
|
|
31
32
|
Requires-Dist: core-dev-tools>=2.1.0; extra == "dev"
|
|
32
|
-
Requires-Dist: core-tests>=2.
|
|
33
|
+
Requires-Dist: core-tests>=2.3.0; extra == "dev"
|
|
33
34
|
Dynamic: license-file
|
|
34
35
|
|
|
35
36
|
core-data-structures
|
{core_data_structures-1.3.0 → core_data_structures-1.4.1}/core_data_structures.egg-info/SOURCES.txt
RENAMED
|
@@ -18,5 +18,6 @@ data_structures/lists/base.py
|
|
|
18
18
|
data_structures/lists/double_linked_list.py
|
|
19
19
|
data_structures/lists/singly_linked_list.py
|
|
20
20
|
data_structures/trees/__init__.py
|
|
21
|
+
data_structures/trees/base.py
|
|
21
22
|
data_structures/trees/binary_tree.py
|
|
22
23
|
data_structures/trees/simple_tree.py
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
|
|
3
1
|
"""Core data structures package."""
|
|
4
2
|
|
|
5
|
-
from importlib.metadata import PackageNotFoundError
|
|
6
|
-
from importlib.metadata import version
|
|
7
|
-
|
|
3
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
8
4
|
|
|
9
5
|
try:
|
|
10
6
|
__version__ = version("core-data-structures")
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
|
|
3
1
|
"""Base node used as a building block across data structures."""
|
|
4
2
|
|
|
5
|
-
from
|
|
6
|
-
from typing import Optional
|
|
7
|
-
from typing import TypeVar
|
|
3
|
+
from __future__ import annotations
|
|
8
4
|
|
|
5
|
+
from typing import Generic, TypeVar
|
|
9
6
|
|
|
10
7
|
__all__ = [
|
|
11
8
|
"Node",
|
|
@@ -21,15 +18,15 @@ class Node(Generic[T]): # pylint: disable=too-few-public-methods
|
|
|
21
18
|
subclassed by concrete node types.
|
|
22
19
|
"""
|
|
23
20
|
|
|
24
|
-
def __init__(self, value:
|
|
21
|
+
def __init__(self, value: T | None = None) -> None:
|
|
25
22
|
self._value = value
|
|
26
23
|
|
|
27
24
|
def __repr__(self):
|
|
28
25
|
return f"[{self._value}]"
|
|
29
26
|
|
|
30
27
|
@property
|
|
31
|
-
def value(self) ->
|
|
32
|
-
"""
|
|
28
|
+
def value(self) -> T | None:
|
|
29
|
+
"""The value held by the node."""
|
|
33
30
|
return self._value
|
|
34
31
|
|
|
35
32
|
@value.setter
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
|
|
3
1
|
"""Graph data structure with common traversal and path-finding algorithms."""
|
|
4
2
|
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
5
|
import json
|
|
6
6
|
from queue import Queue
|
|
7
|
-
from typing import Any
|
|
7
|
+
from typing import Any
|
|
8
8
|
|
|
9
9
|
from .vertex import Vertex
|
|
10
10
|
|
|
@@ -29,13 +29,9 @@ class Graph:
|
|
|
29
29
|
E --- F
|
|
30
30
|
"""
|
|
31
31
|
|
|
32
|
-
return cls.build_graph(
|
|
33
|
-
"A": ["B", "C"],
|
|
34
|
-
|
|
35
|
-
"C": ["D"],
|
|
36
|
-
"D": ["E", "F"],
|
|
37
|
-
"E": ["F"]
|
|
38
|
-
})
|
|
32
|
+
return cls.build_graph(
|
|
33
|
+
{"A": ["B", "C"], "B": ["C", "D"], "C": ["D"], "D": ["E", "F"], "E": ["F"]}
|
|
34
|
+
)
|
|
39
35
|
|
|
40
36
|
def __iter__(self):
|
|
41
37
|
return iter(self.vertices.values())
|
|
@@ -44,19 +40,23 @@ class Graph:
|
|
|
44
40
|
return key in self.vertices
|
|
45
41
|
|
|
46
42
|
def __str__(self):
|
|
47
|
-
return json.dumps(
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
43
|
+
return json.dumps(
|
|
44
|
+
{
|
|
45
|
+
key: list(vertex.get_connections_ids())
|
|
46
|
+
for key, vertex in self.vertices.items()
|
|
47
|
+
}
|
|
48
|
+
)
|
|
51
49
|
|
|
52
50
|
def __repr__(self):
|
|
53
|
-
return json.dumps(
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
51
|
+
return json.dumps(
|
|
52
|
+
{
|
|
53
|
+
key: list(vertex.get_connections_ids())
|
|
54
|
+
for key, vertex in self.vertices.items()
|
|
55
|
+
}
|
|
56
|
+
)
|
|
57
57
|
|
|
58
58
|
@classmethod
|
|
59
|
-
def build_graph(cls, graph_definition:
|
|
59
|
+
def build_graph(cls, graph_definition: dict[Any, list]):
|
|
60
60
|
"""
|
|
61
61
|
Create a Graph
|
|
62
62
|
|
|
@@ -75,23 +75,23 @@ class Graph:
|
|
|
75
75
|
return graph
|
|
76
76
|
|
|
77
77
|
def add_vertex(self, key) -> Vertex:
|
|
78
|
-
"""
|
|
78
|
+
"""Add a vertex for the given key if it does not already exist and return it."""
|
|
79
79
|
|
|
80
80
|
if key not in self.vertices:
|
|
81
81
|
self.vertices[key] = Vertex(key)
|
|
82
82
|
|
|
83
83
|
return self.vertices[key]
|
|
84
84
|
|
|
85
|
-
def get_vertex(self, key) ->
|
|
86
|
-
"""
|
|
85
|
+
def get_vertex(self, key) -> Vertex | None:
|
|
86
|
+
"""Return a vertex by key"""
|
|
87
87
|
return self.vertices.get(key, None)
|
|
88
88
|
|
|
89
|
-
def get_vertices(self) ->
|
|
90
|
-
"""
|
|
89
|
+
def get_vertices(self) -> dict:
|
|
90
|
+
"""Return all vertices"""
|
|
91
91
|
return self.vertices
|
|
92
92
|
|
|
93
93
|
def add_edge(self, key_vertex1, key_vertex2, weight=0):
|
|
94
|
-
"""
|
|
94
|
+
"""Add a directed edge from key_vertex1 to key_vertex2 with an optional weight."""
|
|
95
95
|
|
|
96
96
|
if key_vertex1 not in self.vertices:
|
|
97
97
|
self.add_vertex(key_vertex1)
|
|
@@ -124,7 +124,7 @@ class Graph:
|
|
|
124
124
|
|
|
125
125
|
return visited
|
|
126
126
|
|
|
127
|
-
def depth_first_search(self, node_id, visited:
|
|
127
|
+
def depth_first_search(self, node_id, visited: list | None = None):
|
|
128
128
|
"""
|
|
129
129
|
Depth First Traversal Algorithm...
|
|
130
130
|
|
|
@@ -147,7 +147,7 @@ class Graph:
|
|
|
147
147
|
|
|
148
148
|
return visited
|
|
149
149
|
|
|
150
|
-
def find_path(self, start, end, path:
|
|
150
|
+
def find_path(self, start, end, path: list | None = None):
|
|
151
151
|
"""
|
|
152
152
|
Determine a path between two nodes...
|
|
153
153
|
|
|
@@ -178,7 +178,7 @@ class Graph:
|
|
|
178
178
|
|
|
179
179
|
return None
|
|
180
180
|
|
|
181
|
-
def find_all_paths(self, start, end, path:
|
|
181
|
+
def find_all_paths(self, start, end, path: list | None = None):
|
|
182
182
|
"""
|
|
183
183
|
Determine all paths between two nodes...
|
|
184
184
|
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
|
|
3
1
|
"""Vertex node used within graph data structures."""
|
|
4
2
|
|
|
5
3
|
import sys
|
|
6
|
-
from typing import Dict, List
|
|
7
4
|
|
|
8
|
-
if sys.version_info >= (3, 11):
|
|
5
|
+
if sys.version_info >= (3, 11): # pragma: no cover
|
|
9
6
|
from typing import Self
|
|
10
7
|
else: # pragma: no cover
|
|
11
8
|
from typing_extensions import Self
|
|
@@ -15,7 +12,7 @@ class Vertex:
|
|
|
15
12
|
"""Represents a node in a graph with weighted connections to neighbors."""
|
|
16
13
|
|
|
17
14
|
def __init__(self, key):
|
|
18
|
-
"""
|
|
15
|
+
"""Initialize the vertex with a key and no connections."""
|
|
19
16
|
|
|
20
17
|
self._id = key
|
|
21
18
|
self._connections = {}
|
|
@@ -25,7 +22,7 @@ class Vertex:
|
|
|
25
22
|
|
|
26
23
|
@property
|
|
27
24
|
def id(self):
|
|
28
|
-
"""
|
|
25
|
+
"""The vertex identifier."""
|
|
29
26
|
return self._id
|
|
30
27
|
|
|
31
28
|
@id.setter
|
|
@@ -33,17 +30,17 @@ class Vertex:
|
|
|
33
30
|
self._id = value
|
|
34
31
|
|
|
35
32
|
def get_weight(self, vertex: Self):
|
|
36
|
-
"""
|
|
33
|
+
"""Retrieve the weight to reach the neighbor"""
|
|
37
34
|
return self._connections[vertex]
|
|
38
35
|
|
|
39
|
-
def get_connections(self) ->
|
|
40
|
-
"""
|
|
36
|
+
def get_connections(self) -> dict:
|
|
37
|
+
"""Return the connections"""
|
|
41
38
|
return self._connections
|
|
42
39
|
|
|
43
|
-
def get_connections_ids(self) ->
|
|
44
|
-
"""
|
|
40
|
+
def get_connections_ids(self) -> list:
|
|
41
|
+
"""Return the connections ids"""
|
|
45
42
|
return [vertex.id for vertex in self.get_connections()]
|
|
46
43
|
|
|
47
44
|
def add_neighbor(self, vertex: Self, weight=0):
|
|
48
|
-
"""
|
|
45
|
+
"""Add or update a connection"""
|
|
49
46
|
self._connections[vertex] = weight
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
|
|
3
1
|
"""Abstract interface shared by every list implementation in this package."""
|
|
4
2
|
|
|
5
|
-
from
|
|
6
|
-
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from abc import ABC, abstractmethod
|
|
6
|
+
from collections.abc import Iterator
|
|
7
7
|
from contextlib import suppress
|
|
8
|
-
from typing import Generic,
|
|
8
|
+
from typing import Generic, TypeVar, cast
|
|
9
9
|
|
|
10
10
|
from core_mixins.compatibility import Self
|
|
11
11
|
|
|
@@ -18,26 +18,26 @@ class Node(BaseNode[T]):
|
|
|
18
18
|
|
|
19
19
|
def __init__(
|
|
20
20
|
self,
|
|
21
|
-
value:
|
|
22
|
-
next_node:
|
|
21
|
+
value: T | None = None,
|
|
22
|
+
next_node: Self | None = None,
|
|
23
23
|
) -> None:
|
|
24
24
|
super().__init__(value=value)
|
|
25
25
|
self._next = next_node
|
|
26
26
|
|
|
27
27
|
@property
|
|
28
|
-
def next(self) ->
|
|
28
|
+
def next(self) -> Self | None:
|
|
29
29
|
"""The next node in the list, if any."""
|
|
30
30
|
return self._next
|
|
31
31
|
|
|
32
32
|
@next.setter
|
|
33
|
-
def next(self, next_node:
|
|
33
|
+
def next(self, next_node: Self | None) -> None:
|
|
34
34
|
self._next = next_node
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
NodeT = TypeVar("NodeT", bound=Node)
|
|
38
38
|
|
|
39
39
|
|
|
40
|
-
class IList(Generic[T]
|
|
40
|
+
class IList(ABC, Generic[T]):
|
|
41
41
|
"""Abstract base class (interface) for all list implementations."""
|
|
42
42
|
|
|
43
43
|
def __init__(self, length: int = 0):
|
|
@@ -177,13 +177,11 @@ class IList(Generic[T], ABC):
|
|
|
177
177
|
"""Reverses the list in place."""
|
|
178
178
|
|
|
179
179
|
|
|
180
|
-
class ILinkedList(IList[T], Generic[T, NodeT]
|
|
180
|
+
class ILinkedList(IList[T], ABC, Generic[T, NodeT]):
|
|
181
181
|
"""Interface for linked list implementations, parametrized by their node type."""
|
|
182
182
|
|
|
183
|
-
def __init__(self, value:
|
|
184
|
-
self._head:
|
|
185
|
-
None if value is None else self._create_node(value)
|
|
186
|
-
)
|
|
183
|
+
def __init__(self, value: T | None = None) -> None:
|
|
184
|
+
self._head: NodeT | None = None if value is None else self._create_node(value)
|
|
187
185
|
|
|
188
186
|
super().__init__(0 if value is None else 1)
|
|
189
187
|
self._end = self._head
|
|
@@ -202,12 +200,12 @@ class ILinkedList(IList[T], Generic[T, NodeT], ABC):
|
|
|
202
200
|
"""Creates a new, unlinked node of the concrete node type used by this list."""
|
|
203
201
|
|
|
204
202
|
@property
|
|
205
|
-
def head(self) ->
|
|
203
|
+
def head(self) -> NodeT | None:
|
|
206
204
|
"""The first node in the list."""
|
|
207
205
|
return self._head
|
|
208
206
|
|
|
209
207
|
@property
|
|
210
|
-
def end(self) ->
|
|
208
|
+
def end(self) -> NodeT | None:
|
|
211
209
|
"""The end node in the list."""
|
|
212
210
|
return self._end
|
|
213
211
|
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
|
|
3
1
|
"""
|
|
4
2
|
A doubly linked list is a linear data structure composed of a sequence
|
|
5
3
|
of nodes where each node contains data and pointers (or references) to
|
|
@@ -12,7 +10,8 @@ direction.
|
|
|
12
10
|
# ILinkedList rather than parent/child, so their mutators intentionally
|
|
13
11
|
# don't share an implementation, even where the resulting code overlaps.
|
|
14
12
|
|
|
15
|
-
from
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
16
15
|
from typing import cast
|
|
17
16
|
|
|
18
17
|
from core_mixins.compatibility import Self
|
|
@@ -30,20 +29,20 @@ class Node(LinkedNode[T]):
|
|
|
30
29
|
|
|
31
30
|
def __init__(
|
|
32
31
|
self,
|
|
33
|
-
value:
|
|
34
|
-
next_node:
|
|
35
|
-
prev_node:
|
|
32
|
+
value: T | None = None,
|
|
33
|
+
next_node: Self | None = None,
|
|
34
|
+
prev_node: Self | None = None,
|
|
36
35
|
) -> None:
|
|
37
36
|
super().__init__(value=value, next_node=next_node)
|
|
38
37
|
self._prev = prev_node
|
|
39
38
|
|
|
40
39
|
@property
|
|
41
|
-
def prev(self) ->
|
|
40
|
+
def prev(self) -> Self | None:
|
|
42
41
|
"""The previous node in the list, if any."""
|
|
43
42
|
return self._prev
|
|
44
43
|
|
|
45
44
|
@prev.setter
|
|
46
|
-
def prev(self, prev_node:
|
|
45
|
+
def prev(self, prev_node: Self | None) -> None:
|
|
47
46
|
self._prev = prev_node
|
|
48
47
|
|
|
49
48
|
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
|
|
3
1
|
"""
|
|
4
2
|
A linked list is a linear data structure composed of a sequence
|
|
5
3
|
of nodes where each node contains data and a pointer (or reference)
|
|
@@ -11,8 +9,7 @@ across your system's RAM.
|
|
|
11
9
|
from typing import cast
|
|
12
10
|
|
|
13
11
|
from data_structures.base import T
|
|
14
|
-
from data_structures.lists.base import ILinkedList
|
|
15
|
-
from data_structures.lists.base import Node
|
|
12
|
+
from data_structures.lists.base import ILinkedList, Node
|
|
16
13
|
|
|
17
14
|
|
|
18
15
|
class SinglyLinkedList(ILinkedList[T, Node[T]]):
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""Node with left/right child references, shared by every binary tree."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from core_mixins.compatibility import Self
|
|
6
|
+
|
|
7
|
+
from data_structures.base import Node as BaseNode
|
|
8
|
+
from data_structures.base import T
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"Node",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Node(BaseNode[T]):
|
|
16
|
+
"""Node with references to its left and right children."""
|
|
17
|
+
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
value: T | None = None,
|
|
21
|
+
left: Self | None = None,
|
|
22
|
+
right: Self | None = None,
|
|
23
|
+
) -> None:
|
|
24
|
+
super().__init__(value=value)
|
|
25
|
+
self._left = left
|
|
26
|
+
self._right = right
|
|
27
|
+
|
|
28
|
+
@property
|
|
29
|
+
def left(self) -> Self | None:
|
|
30
|
+
"""The left child of the node, if any."""
|
|
31
|
+
return self._left
|
|
32
|
+
|
|
33
|
+
@left.setter
|
|
34
|
+
def left(self, node: Self | None) -> None:
|
|
35
|
+
self._left = node
|
|
36
|
+
|
|
37
|
+
@property
|
|
38
|
+
def right(self) -> Self | None:
|
|
39
|
+
"""The right child of the node, if any."""
|
|
40
|
+
return self._right
|
|
41
|
+
|
|
42
|
+
@right.setter
|
|
43
|
+
def right(self, node: Self | None) -> None:
|
|
44
|
+
self._right = node
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
"""Binary tree data structure with recursive and iterative traversal algorithms."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Iterator
|
|
6
|
+
from queue import Queue
|
|
7
|
+
from typing import Generic, cast
|
|
8
|
+
|
|
9
|
+
from data_structures.base import T
|
|
10
|
+
from data_structures.trees.base import Node
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class BinaryTree(Generic[T]):
|
|
14
|
+
"""
|
|
15
|
+
In computer science, a binary tree is a tree data structure in which
|
|
16
|
+
each node has at most two children, referred to as the left child
|
|
17
|
+
and the right child.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def __init__(self, value: T | None = None) -> None:
|
|
21
|
+
self._root: Node[T] | None = None if value is None else Node(value)
|
|
22
|
+
|
|
23
|
+
def __iter__(self) -> Iterator[T]:
|
|
24
|
+
yield from self._iter(self._root)
|
|
25
|
+
|
|
26
|
+
@classmethod
|
|
27
|
+
def _iter(cls, node: Node[T] | None) -> Iterator[T]:
|
|
28
|
+
if node is None:
|
|
29
|
+
return
|
|
30
|
+
|
|
31
|
+
yield from cls._iter(node.left)
|
|
32
|
+
yield cast(T, node.value)
|
|
33
|
+
yield from cls._iter(node.right)
|
|
34
|
+
|
|
35
|
+
def __len__(self) -> int:
|
|
36
|
+
return self._count(self._root)
|
|
37
|
+
|
|
38
|
+
@classmethod
|
|
39
|
+
def _count(cls, node: Node[T] | None) -> int:
|
|
40
|
+
if node is None:
|
|
41
|
+
return 0
|
|
42
|
+
|
|
43
|
+
return 1 + cls._count(node.left) + cls._count(node.right)
|
|
44
|
+
|
|
45
|
+
def __contains__(self, value: T) -> bool:
|
|
46
|
+
return any(node_value == value for node_value in self)
|
|
47
|
+
|
|
48
|
+
def __repr__(self) -> str:
|
|
49
|
+
return f"{type(self).__name__}({self.level_order()!r})"
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def root(self) -> Node[T] | None:
|
|
53
|
+
"""The root node of the tree."""
|
|
54
|
+
return self._root
|
|
55
|
+
|
|
56
|
+
def pre_order(self) -> list[T]:
|
|
57
|
+
"""
|
|
58
|
+
>>> tree = create_example_tree()
|
|
59
|
+
>>> tree.pre_order()
|
|
60
|
+
[1, 2, 4, 8, 9, 5, 10, 11, 3, 6, 12, 13, 7, 14, 15]
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
return self._pre_order(self._root)
|
|
64
|
+
|
|
65
|
+
@classmethod
|
|
66
|
+
def _pre_order(cls, node: Node[T] | None) -> list[T]:
|
|
67
|
+
if node is None:
|
|
68
|
+
return []
|
|
69
|
+
|
|
70
|
+
res = [cast(T, node.value)]
|
|
71
|
+
res.extend(cls._pre_order(node.left))
|
|
72
|
+
res.extend(cls._pre_order(node.right))
|
|
73
|
+
return res
|
|
74
|
+
|
|
75
|
+
def pre_order_iterative(self) -> list[T]:
|
|
76
|
+
"""
|
|
77
|
+
>>> tree = create_example_tree()
|
|
78
|
+
>>> tree.pre_order_iterative()
|
|
79
|
+
[1, 2, 4, 8, 9, 5, 10, 11, 3, 6, 12, 13, 7, 14, 15]
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
stack: list[Node[T]] = []
|
|
83
|
+
node: Node[T] | None = self._root
|
|
84
|
+
res: list[T] = []
|
|
85
|
+
|
|
86
|
+
while stack or node:
|
|
87
|
+
while node:
|
|
88
|
+
res.append(cast(T, node.value))
|
|
89
|
+
stack.append(node)
|
|
90
|
+
node = node.left
|
|
91
|
+
|
|
92
|
+
node = stack.pop()
|
|
93
|
+
node = node.right
|
|
94
|
+
|
|
95
|
+
return res
|
|
96
|
+
|
|
97
|
+
def in_order(self) -> list[T]:
|
|
98
|
+
"""
|
|
99
|
+
>>> tree = create_example_tree()
|
|
100
|
+
>>> tree.in_order()
|
|
101
|
+
[8, 4, 9, 2, 10, 5, 11, 1, 12, 6, 13, 3, 14, 7, 15]
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
return self._in_order(self._root)
|
|
105
|
+
|
|
106
|
+
@classmethod
|
|
107
|
+
def _in_order(cls, node: Node[T] | None) -> list[T]:
|
|
108
|
+
if node is None:
|
|
109
|
+
return []
|
|
110
|
+
|
|
111
|
+
res = cls._in_order(node.left)
|
|
112
|
+
res.append(cast(T, node.value))
|
|
113
|
+
res.extend(cls._in_order(node.right))
|
|
114
|
+
return res
|
|
115
|
+
|
|
116
|
+
def in_order_iterative(self) -> list[T]:
|
|
117
|
+
"""
|
|
118
|
+
>>> tree = create_example_tree()
|
|
119
|
+
>>> tree.in_order_iterative()
|
|
120
|
+
[8, 4, 9, 2, 10, 5, 11, 1, 12, 6, 13, 3, 14, 7, 15]
|
|
121
|
+
"""
|
|
122
|
+
|
|
123
|
+
res: list[T] = []
|
|
124
|
+
stack: list[Node[T]] = []
|
|
125
|
+
node: Node[T] | None = self._root
|
|
126
|
+
|
|
127
|
+
while stack or node:
|
|
128
|
+
while node:
|
|
129
|
+
stack.append(node)
|
|
130
|
+
node = node.left
|
|
131
|
+
|
|
132
|
+
node = stack.pop()
|
|
133
|
+
res.append(cast(T, node.value))
|
|
134
|
+
node = node.right
|
|
135
|
+
|
|
136
|
+
return res
|
|
137
|
+
|
|
138
|
+
def post_order(self) -> list[T]:
|
|
139
|
+
"""
|
|
140
|
+
>>> tree = create_example_tree()
|
|
141
|
+
>>> tree.post_order()
|
|
142
|
+
[8, 9, 4, 10, 11, 5, 2, 12, 13, 6, 14, 15, 7, 3, 1]
|
|
143
|
+
"""
|
|
144
|
+
|
|
145
|
+
return self._post_order(self._root)
|
|
146
|
+
|
|
147
|
+
@classmethod
|
|
148
|
+
def _post_order(cls, node: Node[T] | None) -> list[T]:
|
|
149
|
+
if node is None:
|
|
150
|
+
return []
|
|
151
|
+
|
|
152
|
+
res = cls._post_order(node.left)
|
|
153
|
+
res.extend(cls._post_order(node.right))
|
|
154
|
+
res.append(cast(T, node.value))
|
|
155
|
+
return res
|
|
156
|
+
|
|
157
|
+
def post_order_iterative(self) -> list[T]:
|
|
158
|
+
"""
|
|
159
|
+
>>> tree = create_example_tree()
|
|
160
|
+
>>> tree.post_order_iterative()
|
|
161
|
+
[8, 9, 4, 10, 11, 5, 2, 12, 13, 6, 14, 15, 7, 3, 1]
|
|
162
|
+
"""
|
|
163
|
+
|
|
164
|
+
if self._root is None:
|
|
165
|
+
return []
|
|
166
|
+
|
|
167
|
+
stack: list[Node[T]] = [self._root]
|
|
168
|
+
stack_tmp: list[Node[T]] = []
|
|
169
|
+
|
|
170
|
+
while stack:
|
|
171
|
+
node = stack.pop()
|
|
172
|
+
if node.left:
|
|
173
|
+
stack.append(node.left)
|
|
174
|
+
|
|
175
|
+
if node.right:
|
|
176
|
+
stack.append(node.right)
|
|
177
|
+
|
|
178
|
+
stack_tmp.append(node)
|
|
179
|
+
|
|
180
|
+
res: list[T] = []
|
|
181
|
+
while stack_tmp:
|
|
182
|
+
res.append(cast(T, stack_tmp.pop().value))
|
|
183
|
+
|
|
184
|
+
return res
|
|
185
|
+
|
|
186
|
+
def level_order(self) -> list[T]:
|
|
187
|
+
"""
|
|
188
|
+
>>> tree = create_example_tree()
|
|
189
|
+
>>> tree.level_order()
|
|
190
|
+
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
|
|
191
|
+
"""
|
|
192
|
+
|
|
193
|
+
res: list[T] = []
|
|
194
|
+
if self._root is None:
|
|
195
|
+
return res
|
|
196
|
+
|
|
197
|
+
q: Queue[Node[T]] = Queue()
|
|
198
|
+
q.put(self._root)
|
|
199
|
+
|
|
200
|
+
while not q.empty():
|
|
201
|
+
node_dequeued = q.get()
|
|
202
|
+
res.append(cast(T, node_dequeued.value))
|
|
203
|
+
|
|
204
|
+
if node_dequeued.left:
|
|
205
|
+
q.put(node_dequeued.left)
|
|
206
|
+
|
|
207
|
+
if node_dequeued.right:
|
|
208
|
+
q.put(node_dequeued.right)
|
|
209
|
+
|
|
210
|
+
return res
|
|
211
|
+
|
|
212
|
+
def depth(self) -> int:
|
|
213
|
+
"""
|
|
214
|
+
The maximum depth of a binary tree is the number of nodes from the
|
|
215
|
+
root down to the furthest leaf node. In other words, it is
|
|
216
|
+
the height of a binary tree.
|
|
217
|
+
|
|
218
|
+
>>> tree = create_example_tree()
|
|
219
|
+
>>> tree.depth()
|
|
220
|
+
4
|
|
221
|
+
"""
|
|
222
|
+
|
|
223
|
+
return self._depth(self._root)
|
|
224
|
+
|
|
225
|
+
@classmethod
|
|
226
|
+
def _depth(cls, node: Node[T] | None) -> int:
|
|
227
|
+
if node is None:
|
|
228
|
+
return 0
|
|
229
|
+
|
|
230
|
+
return 1 + max(cls._depth(node.left), cls._depth(node.right))
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def create_example_tree() -> BinaryTree[int]:
|
|
234
|
+
"""Build and return a complete binary tree with 15 nodes for testing."""
|
|
235
|
+
|
|
236
|
+
tree = BinaryTree(1)
|
|
237
|
+
root = cast(Node[int], tree.root)
|
|
238
|
+
nodes = [Node(value) for value in range(2, 16)]
|
|
239
|
+
|
|
240
|
+
root.left, root.right = nodes[0], nodes[1]
|
|
241
|
+
nodes[0].left, nodes[0].right = nodes[2], nodes[3]
|
|
242
|
+
nodes[1].left, nodes[1].right = nodes[4], nodes[5]
|
|
243
|
+
nodes[2].left, nodes[2].right = nodes[6], nodes[7]
|
|
244
|
+
nodes[3].left, nodes[3].right = nodes[8], nodes[9]
|
|
245
|
+
nodes[4].left, nodes[4].right = nodes[10], nodes[11]
|
|
246
|
+
nodes[5].left, nodes[5].right = nodes[12], nodes[13]
|
|
247
|
+
return tree
|
{core_data_structures-1.3.0 → core_data_structures-1.4.1}/data_structures/trees/simple_tree.py
RENAMED
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
|
|
3
1
|
"""Simple tree data structure backed by a nested dictionary."""
|
|
4
2
|
|
|
5
|
-
from typing import Dict
|
|
6
|
-
|
|
7
3
|
|
|
8
|
-
class Tree(
|
|
9
|
-
"""
|
|
4
|
+
class Tree(dict):
|
|
5
|
+
"""Basic implementation based on Dictionary"""
|
|
10
6
|
|
|
11
7
|
def __missing__(self, key):
|
|
12
8
|
value = self[key] = type(self)()
|
|
@@ -9,7 +9,7 @@ build-backend = "setuptools.build_meta"
|
|
|
9
9
|
[project]
|
|
10
10
|
name = "core-data-structures"
|
|
11
11
|
description = "This project/library contains commons data structures..."
|
|
12
|
-
version = "1.
|
|
12
|
+
version = "1.4.1"
|
|
13
13
|
|
|
14
14
|
authors = [
|
|
15
15
|
{name = "Alejandro Cora González", email = "alek.cora.glez@gmail.com"}
|
|
@@ -37,6 +37,7 @@ classifiers = [
|
|
|
37
37
|
"Programming Language :: Python :: 3.13",
|
|
38
38
|
"Programming Language :: Python :: 3.14",
|
|
39
39
|
"Programming Language :: Python :: Implementation :: PyPy",
|
|
40
|
+
"Typing :: Typed",
|
|
40
41
|
]
|
|
41
42
|
|
|
42
43
|
dependencies = [
|
|
@@ -47,7 +48,7 @@ dependencies = [
|
|
|
47
48
|
[project.optional-dependencies]
|
|
48
49
|
dev = [
|
|
49
50
|
"core-dev-tools>=2.1.0",
|
|
50
|
-
"core-tests>=2.
|
|
51
|
+
"core-tests>=2.3.0",
|
|
51
52
|
]
|
|
52
53
|
|
|
53
54
|
[project.urls]
|
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
|
|
3
|
-
"""Binary tree data structure with recursive and iterative traversal algorithms."""
|
|
4
|
-
|
|
5
|
-
from queue import Queue
|
|
6
|
-
from typing import List, Optional
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class BinaryTree:
|
|
10
|
-
"""
|
|
11
|
-
In computer science, a binary tree is a tree data structure in which
|
|
12
|
-
each node has at most two children, which are referred to as the
|
|
13
|
-
left child and the right child...
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
def __init__(self, value) -> None:
|
|
17
|
-
self.value = value
|
|
18
|
-
self.right: Optional[BinaryTree] = None
|
|
19
|
-
self.left: Optional[BinaryTree] = None
|
|
20
|
-
|
|
21
|
-
@staticmethod
|
|
22
|
-
def create_example_tree():
|
|
23
|
-
""" Build and return a complete binary tree with 15 nodes for testing. """
|
|
24
|
-
|
|
25
|
-
root = BinaryTree(1)
|
|
26
|
-
tree_node2, tree_node3 = BinaryTree(2), BinaryTree(3)
|
|
27
|
-
tree_node4, tree_node5 = BinaryTree(4), BinaryTree(5)
|
|
28
|
-
tree_node6, tree_node7 = BinaryTree(6), BinaryTree(7)
|
|
29
|
-
tree_node8, tree_node9 = BinaryTree(8), BinaryTree(9)
|
|
30
|
-
tree_node10, tree_node11 = BinaryTree(10), BinaryTree(11)
|
|
31
|
-
tree_node12, tree_node13 = BinaryTree(12), BinaryTree(13)
|
|
32
|
-
tree_node14, tree_node15 = BinaryTree(14), BinaryTree(15)
|
|
33
|
-
|
|
34
|
-
root.left, root.right = tree_node2, tree_node3
|
|
35
|
-
tree_node2.left, tree_node2.right = tree_node4, tree_node5
|
|
36
|
-
tree_node3.left, tree_node3.right = tree_node6, tree_node7
|
|
37
|
-
tree_node4.left, tree_node4.right = tree_node8, tree_node9
|
|
38
|
-
tree_node5.left, tree_node5.right = tree_node10, tree_node11
|
|
39
|
-
tree_node6.left, tree_node6.right = tree_node12, tree_node13
|
|
40
|
-
tree_node7.left, tree_node7.right = tree_node14, tree_node15
|
|
41
|
-
return root
|
|
42
|
-
|
|
43
|
-
def pre_order(self) -> List:
|
|
44
|
-
"""
|
|
45
|
-
>>> root = BinaryTree.create_example_tree()
|
|
46
|
-
>>> root.pre_order()
|
|
47
|
-
[1, 2, 4, 8, 9, 5, 10, 11, 3, 6, 12, 13, 7, 14, 15]
|
|
48
|
-
"""
|
|
49
|
-
|
|
50
|
-
res = [self.value]
|
|
51
|
-
if self.left:
|
|
52
|
-
res.extend(self.left.pre_order())
|
|
53
|
-
|
|
54
|
-
if self.right:
|
|
55
|
-
res.extend(self.right.pre_order())
|
|
56
|
-
|
|
57
|
-
return res
|
|
58
|
-
|
|
59
|
-
def pre_order_iterative(self) -> List:
|
|
60
|
-
"""
|
|
61
|
-
>>> root = BinaryTree.create_example_tree()
|
|
62
|
-
>>> root.pre_order_iterative()
|
|
63
|
-
[1, 2, 4, 8, 9, 5, 10, 11, 3, 6, 12, 13, 7, 14, 15]
|
|
64
|
-
"""
|
|
65
|
-
|
|
66
|
-
stack: List[BinaryTree] = []
|
|
67
|
-
node: Optional[BinaryTree] = self
|
|
68
|
-
res = []
|
|
69
|
-
|
|
70
|
-
while stack or node:
|
|
71
|
-
while node:
|
|
72
|
-
res.append(node.value)
|
|
73
|
-
stack.append(node)
|
|
74
|
-
node = node.left
|
|
75
|
-
|
|
76
|
-
node = stack.pop()
|
|
77
|
-
node = node.right
|
|
78
|
-
|
|
79
|
-
return res
|
|
80
|
-
|
|
81
|
-
def in_order(self) -> List:
|
|
82
|
-
"""
|
|
83
|
-
>>> root = BinaryTree.create_example_tree()
|
|
84
|
-
>>> root.in_order()
|
|
85
|
-
[8, 4, 9, 2, 10, 5, 11, 1, 12, 6, 13, 3, 14, 7, 15]
|
|
86
|
-
"""
|
|
87
|
-
|
|
88
|
-
res = []
|
|
89
|
-
if self.left:
|
|
90
|
-
res.extend(self.left.in_order())
|
|
91
|
-
|
|
92
|
-
res.append(self.value)
|
|
93
|
-
|
|
94
|
-
if self.right:
|
|
95
|
-
res.extend(self.right.in_order())
|
|
96
|
-
|
|
97
|
-
return res
|
|
98
|
-
|
|
99
|
-
def in_order_iterative(self) -> List:
|
|
100
|
-
"""
|
|
101
|
-
>>> root = BinaryTree.create_example_tree()
|
|
102
|
-
>>> root.in_order_iterative()
|
|
103
|
-
[8, 4, 9, 2, 10, 5, 11, 1, 12, 6, 13, 3, 14, 7, 15]
|
|
104
|
-
"""
|
|
105
|
-
|
|
106
|
-
res = []
|
|
107
|
-
stack: List[BinaryTree] = []
|
|
108
|
-
node: Optional[BinaryTree] = self
|
|
109
|
-
|
|
110
|
-
while stack or node:
|
|
111
|
-
while node:
|
|
112
|
-
stack.append(node)
|
|
113
|
-
node = node.left
|
|
114
|
-
|
|
115
|
-
node = stack.pop()
|
|
116
|
-
res.append(node.value)
|
|
117
|
-
node = node.right
|
|
118
|
-
|
|
119
|
-
return res
|
|
120
|
-
|
|
121
|
-
def post_order(self) -> List:
|
|
122
|
-
"""
|
|
123
|
-
>>> root = BinaryTree.create_example_tree()
|
|
124
|
-
>>> root.post_order()
|
|
125
|
-
[8, 9, 4, 10, 11, 5, 2, 12, 13, 6, 14, 15, 7, 3, 1]
|
|
126
|
-
"""
|
|
127
|
-
|
|
128
|
-
res = []
|
|
129
|
-
if self.left:
|
|
130
|
-
res.extend(self.left.post_order())
|
|
131
|
-
|
|
132
|
-
if self.right:
|
|
133
|
-
res.extend(self.right.post_order())
|
|
134
|
-
|
|
135
|
-
res.append(self.value)
|
|
136
|
-
return res
|
|
137
|
-
|
|
138
|
-
def post_order_iterative(self) -> List:
|
|
139
|
-
"""
|
|
140
|
-
>>> root = BinaryTree.create_example_tree()
|
|
141
|
-
>>> root.post_order_iterative()
|
|
142
|
-
[8, 9, 4, 10, 11, 5, 2, 12, 13, 6, 14, 15, 7, 3, 1]
|
|
143
|
-
"""
|
|
144
|
-
|
|
145
|
-
stack: List[BinaryTree] = [self]
|
|
146
|
-
stack_tmp: List[BinaryTree] = []
|
|
147
|
-
|
|
148
|
-
while stack:
|
|
149
|
-
node = stack.pop()
|
|
150
|
-
if node.left:
|
|
151
|
-
stack.append(node.left)
|
|
152
|
-
|
|
153
|
-
if node.right:
|
|
154
|
-
stack.append(node.right)
|
|
155
|
-
|
|
156
|
-
stack_tmp.append(node)
|
|
157
|
-
|
|
158
|
-
res = []
|
|
159
|
-
while stack_tmp:
|
|
160
|
-
res.append(stack_tmp.pop().value)
|
|
161
|
-
|
|
162
|
-
return res
|
|
163
|
-
|
|
164
|
-
def level_order(self) -> List:
|
|
165
|
-
"""
|
|
166
|
-
>>> root = BinaryTree.create_example_tree()
|
|
167
|
-
>>> root.level_order()
|
|
168
|
-
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
|
|
169
|
-
"""
|
|
170
|
-
|
|
171
|
-
res = []
|
|
172
|
-
q: Queue[BinaryTree] = Queue()
|
|
173
|
-
q.put(self)
|
|
174
|
-
|
|
175
|
-
while not q.empty():
|
|
176
|
-
node_dequeued = q.get()
|
|
177
|
-
res.append(node_dequeued.value)
|
|
178
|
-
|
|
179
|
-
if node_dequeued.left:
|
|
180
|
-
q.put(node_dequeued.left)
|
|
181
|
-
|
|
182
|
-
if node_dequeued.right:
|
|
183
|
-
q.put(node_dequeued.right)
|
|
184
|
-
|
|
185
|
-
return res
|
|
186
|
-
|
|
187
|
-
# def level_order_iterative(self) -> List:
|
|
188
|
-
# """
|
|
189
|
-
# >>> root = BinaryTree.create_example_tree()
|
|
190
|
-
# >>> root.post_order_iterative()
|
|
191
|
-
# [8, 9, 4, 10, 11, 5, 2, 12, 13, 6, 14, 15, 7, 3, 1]
|
|
192
|
-
# """
|
|
193
|
-
#
|
|
194
|
-
# stack: List[BinaryTree] = []
|
|
195
|
-
# node, res = self, []
|
|
196
|
-
#
|
|
197
|
-
# while stack or node:
|
|
198
|
-
# while node.left:
|
|
199
|
-
# stack.append(node)
|
|
200
|
-
# node = node.left
|
|
201
|
-
#
|
|
202
|
-
# res.append(node.value)
|
|
203
|
-
# node = stack.pop()
|
|
204
|
-
# node = node.right
|
|
205
|
-
#
|
|
206
|
-
# return res
|
|
207
|
-
|
|
208
|
-
def depth(self):
|
|
209
|
-
"""
|
|
210
|
-
The maximum depth of a binary tree is the number of nodes from the
|
|
211
|
-
root down to the furthest leaf node. In other words, it is
|
|
212
|
-
the height of a binary tree.
|
|
213
|
-
|
|
214
|
-
>>> root = BinaryTree.create_example_tree()
|
|
215
|
-
>>> root.depth()
|
|
216
|
-
4
|
|
217
|
-
"""
|
|
218
|
-
|
|
219
|
-
if not self.left and not self.right:
|
|
220
|
-
return 1
|
|
221
|
-
|
|
222
|
-
depth_left = 0
|
|
223
|
-
if self.left:
|
|
224
|
-
depth_left = self.left.depth()
|
|
225
|
-
|
|
226
|
-
depth_right = 0
|
|
227
|
-
if self.right:
|
|
228
|
-
depth_right = self.right.depth()
|
|
229
|
-
|
|
230
|
-
return 1 + max(depth_left, depth_right)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|