From 8c3b8b3325d269d1513a02aae5ee365202128727 Mon Sep 17 00:00:00 2001 From: Dhruv Agarwal <92450489+Dhruv127@users.noreply.github.com> Date: Sun, 1 Oct 2023 14:44:20 +0530 Subject: [PATCH 01/32] Fix #9095 : Implement Fibonacci Heap data structure This commit introduces the Fibonacci Heap data structure along with its relevant methods. --- data_structures/heap/fibonacci_heap.py | 144 +++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 data_structures/heap/fibonacci_heap.py diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py new file mode 100644 index 000000000000..9fd62c2008f9 --- /dev/null +++ b/data_structures/heap/fibonacci_heap.py @@ -0,0 +1,144 @@ +# Implementation of a Fibonacci Heap based on the concepts described in "Introduction to Algorithms" by Cormen, Leiserson, Rivest, and Stein. +# Reference: https://en.wikipedia.org/wiki/Fibonacci_heap + +from __future__ import annotations +from collections.abc import Iterable, Iterator +from typing import Any, Generic, TypeVar + +T = TypeVar("T", bound=int) + + +class FibonacciNode(Generic[T]): + def __init__(self, key: T) -> None: + """ + Create a new FibonacciNode with the given key. + + Args: + key (T): The key value associated with the node. + """ + self.key: T = key + self.degree: int = 0 + self.parent: FibonacciNode[T] | None = None + self.child: FibonacciNode[T] | None = None + self.is_marked: bool = False + self.next: FibonacciNode[T] = self + self.prev: FibonacciNode[T] = self + + +class FibonacciHeap(Generic[T]): + def __init__(self) -> None: + """ + Create a new Fibonacci Heap. + + The Fibonacci Heap is initialized as an empty heap. + """ + self.min_node: FibonacciNode[T] | None = None + self.num_nodes: int = 0 + + def insert(self, key: T) -> None: + """ + Insert a new node with the given key into the Fibonacci Heap. + + Args: + key (T): The key value to insert. + """ + new_node = FibonacciNode(key) + if self.min_node is None: + self.min_node = new_node + else: + self._link_nodes(self.min_node, new_node) + if key < self.min_node.key: + self.min_node = new_node + self.num_nodes += 1 + + def _link_nodes(self, min_node: FibonacciNode[T], new_node: FibonacciNode[T]) -> None: + """ + Link two nodes together in the Fibonacci Heap. + + Args: + min_node (FibonacciNode): The minimum node. + new_node (FibonacciNode): The new node to be linked. + """ + new_node.next = min_node.next + min_node.next = new_node + new_node.prev = min_node + new_node.next.prev = new_node + + def _consolidate(self) -> None: + """ + Consolidate the heap by combining trees with the same degree. + + This is an internal method used to maintain the Fibonacci Heap's properties. + """ + max_degree = int(self.num_nodes ** 0.5) + 1 + degree_buckets: list[FibonacciNode[T] | None] = [None] * max_degree + + current_node = self.min_node + nodes_to_visit = [current_node] + while True: + current_node = current_node.next + if current_node == self.min_node: + break + nodes_to_visit.append(current_node) + + for node in nodes_to_visit: + degree = node.degree + while degree_buckets[degree]: + other = degree_buckets[degree] + if node.key > other.key: + node, other = other, node + self._link_nodes(node, other) + degree_buckets[degree] = None + degree += 1 + degree_buckets[degree] = node + + self.min_node = None + for node in degree_buckets: + if node: + if self.min_node is None or node.key < self.min_node.key: + self.min_node = node + + def extract_min(self) -> T | None: + """ + Extract the minimum element from the Fibonacci Heap. + + Returns: + T | None: The minimum element, or None if the heap is empty. + """ + min_node = self.min_node + if min_node: + if min_node.child: + child = min_node.child + while True: + next_child = child.next + child.prev = min_node.prev + child.next = min_node.next + min_node.prev.next = child + min_node.next.prev = child + min_node.child = None + if next_child == min_node.child: + break + child = next_child + self._remove_node(min_node) + if min_node == min_node.next: + self.min_node = None + else: + self.min_node = min_node.next + self._consolidate() + self.num_nodes -= 1 + return min_node.key if min_node else None + + def _remove_node(self, node: FibonacciNode[T]) -> None: + """ + Remove a node from the doubly linked list of nodes. + + Args: + node (FibonacciNode): The node to remove. + """ + node.prev.next = node.next + node.next.prev = node.prev + +if __name__ == "__main__": + import doctest + doctest.testmod() + From 23a39fce7f1811b6a15deaa86e5aee17725b6c0d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 09:16:18 +0000 Subject: [PATCH 02/32] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/heap/fibonacci_heap.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index 9fd62c2008f9..a2715005d534 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -51,7 +51,9 @@ def insert(self, key: T) -> None: self.min_node = new_node self.num_nodes += 1 - def _link_nodes(self, min_node: FibonacciNode[T], new_node: FibonacciNode[T]) -> None: + def _link_nodes( + self, min_node: FibonacciNode[T], new_node: FibonacciNode[T] + ) -> None: """ Link two nodes together in the Fibonacci Heap. @@ -70,7 +72,7 @@ def _consolidate(self) -> None: This is an internal method used to maintain the Fibonacci Heap's properties. """ - max_degree = int(self.num_nodes ** 0.5) + 1 + max_degree = int(self.num_nodes**0.5) + 1 degree_buckets: list[FibonacciNode[T] | None] = [None] * max_degree current_node = self.min_node @@ -138,7 +140,8 @@ def _remove_node(self, node: FibonacciNode[T]) -> None: node.prev.next = node.next node.next.prev = node.prev + if __name__ == "__main__": import doctest - doctest.testmod() + doctest.testmod() From ef2c1eed57b23589f0851291d985f40851569579 Mon Sep 17 00:00:00 2001 From: Dhruv Agarwal <92450489+Dhruv127@users.noreply.github.com> Date: Sun, 1 Oct 2023 14:59:14 +0530 Subject: [PATCH 03/32] Add missing doctests --- data_structures/heap/fibonacci_heap.py | 54 ++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index a2715005d534..09201053bb51 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -41,6 +41,17 @@ def insert(self, key: T) -> None: Args: key (T): The key value to insert. + + >>> fh = FibonacciHeap() + >>> fh.insert(5) + >>> fh.insert(3) + >>> fh.insert(8) + >>> fh.extract_min() + 3 + >>> fh.extract_min() + 5 + >>> fh.extract_min() + 8 """ new_node = FibonacciNode(key) if self.min_node is None: @@ -51,15 +62,20 @@ def insert(self, key: T) -> None: self.min_node = new_node self.num_nodes += 1 - def _link_nodes( - self, min_node: FibonacciNode[T], new_node: FibonacciNode[T] - ) -> None: + def _link_nodes(self, min_node: FibonacciNode[T], new_node: FibonacciNode[T]) -> None: """ Link two nodes together in the Fibonacci Heap. Args: min_node (FibonacciNode): The minimum node. new_node (FibonacciNode): The new node to be linked. + + >>> fh = FibonacciHeap() + >>> node1 = FibonacciNode(3) + >>> node2 = FibonacciNode(5) + >>> fh._link_nodes(node1, node2) + >>> node1.next == node2 and node2.prev == node1 + True """ new_node.next = min_node.next min_node.next = new_node @@ -71,8 +87,16 @@ def _consolidate(self) -> None: Consolidate the heap by combining trees with the same degree. This is an internal method used to maintain the Fibonacci Heap's properties. + + >>> fh = FibonacciHeap() + >>> fh.insert(5) + >>> fh.insert(3) + >>> fh.insert(8) + >>> fh._consolidate() + >>> fh.min_node.key + 3 """ - max_degree = int(self.num_nodes**0.5) + 1 + max_degree = int(self.num_nodes ** 0.5) + 1 degree_buckets: list[FibonacciNode[T] | None] = [None] * max_degree current_node = self.min_node @@ -106,6 +130,18 @@ def extract_min(self) -> T | None: Returns: T | None: The minimum element, or None if the heap is empty. + + >>> fh = FibonacciHeap() + >>> fh.insert(5) + >>> fh.insert(3) + >>> fh.insert(8) + >>> fh.extract_min() + 3 + >>> fh.extract_min() + 5 + >>> fh.extract_min() + 8 + >>> fh.extract_min() """ min_node = self.min_node if min_node: @@ -129,19 +165,23 @@ def extract_min(self) -> T | None: self._consolidate() self.num_nodes -= 1 return min_node.key if min_node else None - + def _remove_node(self, node: FibonacciNode[T]) -> None: """ Remove a node from the doubly linked list of nodes. Args: node (FibonacciNode): The node to remove. + + >>> fh = FibonacciHeap() + >>> node1 = FibonacciNode(3) + >>> fh._remove_node(node1) + >>> node1.next == node1.prev == node1 + True """ node.prev.next = node.next node.next.prev = node.prev - if __name__ == "__main__": import doctest - doctest.testmod() From 32aa637ae9508c557150974f28cc9b0078a793b1 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 09:29:47 +0000 Subject: [PATCH 04/32] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/heap/fibonacci_heap.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index 09201053bb51..222b2f2e79bf 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -62,7 +62,9 @@ def insert(self, key: T) -> None: self.min_node = new_node self.num_nodes += 1 - def _link_nodes(self, min_node: FibonacciNode[T], new_node: FibonacciNode[T]) -> None: + def _link_nodes( + self, min_node: FibonacciNode[T], new_node: FibonacciNode[T] + ) -> None: """ Link two nodes together in the Fibonacci Heap. @@ -96,7 +98,7 @@ def _consolidate(self) -> None: >>> fh.min_node.key 3 """ - max_degree = int(self.num_nodes ** 0.5) + 1 + max_degree = int(self.num_nodes**0.5) + 1 degree_buckets: list[FibonacciNode[T] | None] = [None] * max_degree current_node = self.min_node @@ -165,7 +167,7 @@ def extract_min(self) -> T | None: self._consolidate() self.num_nodes -= 1 return min_node.key if min_node else None - + def _remove_node(self, node: FibonacciNode[T]) -> None: """ Remove a node from the doubly linked list of nodes. @@ -182,6 +184,8 @@ def _remove_node(self, node: FibonacciNode[T]) -> None: node.prev.next = node.next node.next.prev = node.prev + if __name__ == "__main__": import doctest + doctest.testmod() From 06fb015f689efd31e2e1a3fde6036ce68d7e14c1 Mon Sep 17 00:00:00 2001 From: Dhruv Agarwal <92450489+Dhruv127@users.noreply.github.com> Date: Sun, 1 Oct 2023 15:19:41 +0530 Subject: [PATCH 05/32] Ensured proper type annotations and removed unused imports. - Fixed potential issues with accessing attributes on None objects. --- data_structures/heap/fibonacci_heap.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index 222b2f2e79bf..607e11b0ab64 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -2,8 +2,7 @@ # Reference: https://en.wikipedia.org/wiki/Fibonacci_heap from __future__ import annotations -from collections.abc import Iterable, Iterator -from typing import Any, Generic, TypeVar +from typing import Generic, TypeVar T = TypeVar("T", bound=int) @@ -62,9 +61,7 @@ def insert(self, key: T) -> None: self.min_node = new_node self.num_nodes += 1 - def _link_nodes( - self, min_node: FibonacciNode[T], new_node: FibonacciNode[T] - ) -> None: + def _link_nodes(self, min_node: FibonacciNode[T], new_node: FibonacciNode[T]) -> None: """ Link two nodes together in the Fibonacci Heap. @@ -79,6 +76,9 @@ def _link_nodes( >>> node1.next == node2 and node2.prev == node1 True """ + if min_node is None or new_node is None: + raise ValueError("min_node and new_node cannot be None") + new_node.next = min_node.next min_node.next = new_node new_node.prev = min_node @@ -98,7 +98,7 @@ def _consolidate(self) -> None: >>> fh.min_node.key 3 """ - max_degree = int(self.num_nodes**0.5) + 1 + max_degree = int(self.num_nodes ** 0.5) + 1 degree_buckets: list[FibonacciNode[T] | None] = [None] * max_degree current_node = self.min_node @@ -181,11 +181,12 @@ def _remove_node(self, node: FibonacciNode[T]) -> None: >>> node1.next == node1.prev == node1 True """ + if node is None: + raise ValueError("node cannot be None") + node.prev.next = node.next node.next.prev = node.prev - if __name__ == "__main__": import doctest - doctest.testmod() From dd6acd507a44404bb5f3f286d700a85f794ab3db Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 09:50:45 +0000 Subject: [PATCH 06/32] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/heap/fibonacci_heap.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index 607e11b0ab64..af6202a38c50 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -61,7 +61,9 @@ def insert(self, key: T) -> None: self.min_node = new_node self.num_nodes += 1 - def _link_nodes(self, min_node: FibonacciNode[T], new_node: FibonacciNode[T]) -> None: + def _link_nodes( + self, min_node: FibonacciNode[T], new_node: FibonacciNode[T] + ) -> None: """ Link two nodes together in the Fibonacci Heap. @@ -98,7 +100,7 @@ def _consolidate(self) -> None: >>> fh.min_node.key 3 """ - max_degree = int(self.num_nodes ** 0.5) + 1 + max_degree = int(self.num_nodes**0.5) + 1 degree_buckets: list[FibonacciNode[T] | None] = [None] * max_degree current_node = self.min_node @@ -187,6 +189,8 @@ def _remove_node(self, node: FibonacciNode[T]) -> None: node.prev.next = node.next node.next.prev = node.prev + if __name__ == "__main__": import doctest + doctest.testmod() From f0ddb4e40d60ca0aad021a42f5c0655166a948c3 Mon Sep 17 00:00:00 2001 From: Dhruv Agarwal <92450489+Dhruv127@users.noreply.github.com> Date: Sun, 1 Oct 2023 15:31:41 +0530 Subject: [PATCH 07/32] Fixed line length issues for better readability. - Removed future import statements as they are not supported in newer Python versions. --- data_structures/heap/fibonacci_heap.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index af6202a38c50..e5be2b83c8d1 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -1,12 +1,9 @@ -# Implementation of a Fibonacci Heap based on the concepts described in "Introduction to Algorithms" by Cormen, Leiserson, Rivest, and Stein. # Reference: https://en.wikipedia.org/wiki/Fibonacci_heap -from __future__ import annotations from typing import Generic, TypeVar T = TypeVar("T", bound=int) - class FibonacciNode(Generic[T]): def __init__(self, key: T) -> None: """ @@ -62,7 +59,9 @@ def insert(self, key: T) -> None: self.num_nodes += 1 def _link_nodes( - self, min_node: FibonacciNode[T], new_node: FibonacciNode[T] + self, + min_node: FibonacciNode[T] | None, + new_node: FibonacciNode[T] | None, ) -> None: """ Link two nodes together in the Fibonacci Heap. @@ -100,7 +99,7 @@ def _consolidate(self) -> None: >>> fh.min_node.key 3 """ - max_degree = int(self.num_nodes**0.5) + 1 + max_degree = int(self.num_nodes ** 0.5) + 1 degree_buckets: list[FibonacciNode[T] | None] = [None] * max_degree current_node = self.min_node @@ -189,8 +188,6 @@ def _remove_node(self, node: FibonacciNode[T]) -> None: node.prev.next = node.next node.next.prev = node.prev - if __name__ == "__main__": import doctest - doctest.testmod() From 46a719156f9958ed23ec0918ab2cb39dfa32c002 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 10:02:19 +0000 Subject: [PATCH 08/32] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/heap/fibonacci_heap.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index e5be2b83c8d1..04587a285b00 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -4,6 +4,7 @@ T = TypeVar("T", bound=int) + class FibonacciNode(Generic[T]): def __init__(self, key: T) -> None: """ @@ -99,7 +100,7 @@ def _consolidate(self) -> None: >>> fh.min_node.key 3 """ - max_degree = int(self.num_nodes ** 0.5) + 1 + max_degree = int(self.num_nodes**0.5) + 1 degree_buckets: list[FibonacciNode[T] | None] = [None] * max_degree current_node = self.min_node @@ -188,6 +189,8 @@ def _remove_node(self, node: FibonacciNode[T]) -> None: node.prev.next = node.next node.next.prev = node.prev + if __name__ == "__main__": import doctest + doctest.testmod() From 5da268b1bf370a5c066c42081be4e8f420abda7b Mon Sep 17 00:00:00 2001 From: Dhruv Agarwal <92450489+Dhruv127@users.noreply.github.com> Date: Sun, 1 Oct 2023 15:41:38 +0530 Subject: [PATCH 09/32] Update fibonacci_heap.py Addressed AttributeError and NoneType errors. --- data_structures/heap/fibonacci_heap.py | 27 +++++++++++++------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index 04587a285b00..ee7142c5c25a 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -4,7 +4,6 @@ T = TypeVar("T", bound=int) - class FibonacciNode(Generic[T]): def __init__(self, key: T) -> None: """ @@ -100,27 +99,29 @@ def _consolidate(self) -> None: >>> fh.min_node.key 3 """ - max_degree = int(self.num_nodes**0.5) + 1 + max_degree = int(self.num_nodes ** 0.5) + 1 degree_buckets: list[FibonacciNode[T] | None] = [None] * max_degree current_node = self.min_node nodes_to_visit = [current_node] while True: - current_node = current_node.next + current_node = current_node.next if current_node.next is not None else current_node if current_node == self.min_node: break nodes_to_visit.append(current_node) for node in nodes_to_visit: - degree = node.degree - while degree_buckets[degree]: - other = degree_buckets[degree] - if node.key > other.key: - node, other = other, node - self._link_nodes(node, other) - degree_buckets[degree] = None - degree += 1 - degree_buckets[degree] = node + if node is not None: + degree = node.degree + while degree_buckets[degree]: + other = degree_buckets[degree] + if node.key is not None and other.key is not None: + if node.key > other.key: + node, other = other, node + self._link_nodes(node, other) + degree_buckets[degree] = None + degree += 1 + degree_buckets[degree] = node self.min_node = None for node in degree_buckets: @@ -189,8 +190,6 @@ def _remove_node(self, node: FibonacciNode[T]) -> None: node.prev.next = node.next node.next.prev = node.prev - if __name__ == "__main__": import doctest - doctest.testmod() From 8cd50d48a949807e67cdb272f74826235beb086a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 10:12:12 +0000 Subject: [PATCH 10/32] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/heap/fibonacci_heap.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index ee7142c5c25a..f94eda3c750a 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -4,6 +4,7 @@ T = TypeVar("T", bound=int) + class FibonacciNode(Generic[T]): def __init__(self, key: T) -> None: """ @@ -99,13 +100,15 @@ def _consolidate(self) -> None: >>> fh.min_node.key 3 """ - max_degree = int(self.num_nodes ** 0.5) + 1 + max_degree = int(self.num_nodes**0.5) + 1 degree_buckets: list[FibonacciNode[T] | None] = [None] * max_degree current_node = self.min_node nodes_to_visit = [current_node] while True: - current_node = current_node.next if current_node.next is not None else current_node + current_node = ( + current_node.next if current_node.next is not None else current_node + ) if current_node == self.min_node: break nodes_to_visit.append(current_node) @@ -190,6 +193,8 @@ def _remove_node(self, node: FibonacciNode[T]) -> None: node.prev.next = node.next node.next.prev = node.prev + if __name__ == "__main__": import doctest + doctest.testmod() From 044afb0be79b4ac89565b776d08c2afd8e94277b Mon Sep 17 00:00:00 2001 From: Dhruv Agarwal <92450489+Dhruv127@users.noreply.github.com> Date: Sun, 1 Oct 2023 15:46:36 +0530 Subject: [PATCH 11/32] Update fibonacci_heap.py --- data_structures/heap/fibonacci_heap.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index f94eda3c750a..961f69db2d4b 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -1,10 +1,9 @@ # Reference: https://en.wikipedia.org/wiki/Fibonacci_heap -from typing import Generic, TypeVar +from typing import Generic, TypeVar, Optional T = TypeVar("T", bound=int) - class FibonacciNode(Generic[T]): def __init__(self, key: T) -> None: """ @@ -15,8 +14,8 @@ def __init__(self, key: T) -> None: """ self.key: T = key self.degree: int = 0 - self.parent: FibonacciNode[T] | None = None - self.child: FibonacciNode[T] | None = None + self.parent: Optional[FibonacciNode[T]] = None + self.child: Optional[FibonacciNode[T]] = None self.is_marked: bool = False self.next: FibonacciNode[T] = self self.prev: FibonacciNode[T] = self @@ -100,15 +99,13 @@ def _consolidate(self) -> None: >>> fh.min_node.key 3 """ - max_degree = int(self.num_nodes**0.5) + 1 + max_degree = int(self.num_nodes ** 0.5) + 1 degree_buckets: list[FibonacciNode[T] | None] = [None] * max_degree current_node = self.min_node nodes_to_visit = [current_node] while True: - current_node = ( - current_node.next if current_node.next is not None else current_node - ) + current_node = current_node.next if current_node.next is not None else current_node if current_node == self.min_node: break nodes_to_visit.append(current_node) @@ -193,8 +190,6 @@ def _remove_node(self, node: FibonacciNode[T]) -> None: node.prev.next = node.next node.next.prev = node.prev - if __name__ == "__main__": import doctest - doctest.testmod() From 774ba120011b1e9e9268ada4b1094fdbbaf39823 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 10:17:08 +0000 Subject: [PATCH 12/32] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/heap/fibonacci_heap.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index 961f69db2d4b..4535206f400a 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -4,6 +4,7 @@ T = TypeVar("T", bound=int) + class FibonacciNode(Generic[T]): def __init__(self, key: T) -> None: """ @@ -99,13 +100,15 @@ def _consolidate(self) -> None: >>> fh.min_node.key 3 """ - max_degree = int(self.num_nodes ** 0.5) + 1 + max_degree = int(self.num_nodes**0.5) + 1 degree_buckets: list[FibonacciNode[T] | None] = [None] * max_degree current_node = self.min_node nodes_to_visit = [current_node] while True: - current_node = current_node.next if current_node.next is not None else current_node + current_node = ( + current_node.next if current_node.next is not None else current_node + ) if current_node == self.min_node: break nodes_to_visit.append(current_node) @@ -190,6 +193,8 @@ def _remove_node(self, node: FibonacciNode[T]) -> None: node.prev.next = node.next node.next.prev = node.prev + if __name__ == "__main__": import doctest + doctest.testmod() From fee3f04ee472f9df14249e506eddd5755c664492 Mon Sep 17 00:00:00 2001 From: Dhruv Agarwal <92450489+Dhruv127@users.noreply.github.com> Date: Sun, 1 Oct 2023 16:06:45 +0530 Subject: [PATCH 13/32] Update fibonacci_heap.py --- data_structures/heap/fibonacci_heap.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index 4535206f400a..d0d2d2013864 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -4,7 +4,6 @@ T = TypeVar("T", bound=int) - class FibonacciNode(Generic[T]): def __init__(self, key: T) -> None: """ @@ -15,8 +14,8 @@ def __init__(self, key: T) -> None: """ self.key: T = key self.degree: int = 0 - self.parent: Optional[FibonacciNode[T]] = None - self.child: Optional[FibonacciNode[T]] = None + self.parent: Optional[FibonacciNode[T] | None] = None + self.child: Optional[FibonacciNode[T] | None] = None self.is_marked: bool = False self.next: FibonacciNode[T] = self self.prev: FibonacciNode[T] = self @@ -100,15 +99,13 @@ def _consolidate(self) -> None: >>> fh.min_node.key 3 """ - max_degree = int(self.num_nodes**0.5) + 1 + max_degree = int(self.num_nodes ** 0.5) + 1 degree_buckets: list[FibonacciNode[T] | None] = [None] * max_degree current_node = self.min_node nodes_to_visit = [current_node] while True: - current_node = ( - current_node.next if current_node.next is not None else current_node - ) + current_node = current_node.next if current_node.next is not None else current_node if current_node == self.min_node: break nodes_to_visit.append(current_node) @@ -193,8 +190,6 @@ def _remove_node(self, node: FibonacciNode[T]) -> None: node.prev.next = node.next node.next.prev = node.prev - if __name__ == "__main__": import doctest - doctest.testmod() From 053b55f606a775b0ed7031438623e13652b87f55 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 10:37:18 +0000 Subject: [PATCH 14/32] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/heap/fibonacci_heap.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index d0d2d2013864..a11a22320c6e 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -4,6 +4,7 @@ T = TypeVar("T", bound=int) + class FibonacciNode(Generic[T]): def __init__(self, key: T) -> None: """ @@ -99,13 +100,15 @@ def _consolidate(self) -> None: >>> fh.min_node.key 3 """ - max_degree = int(self.num_nodes ** 0.5) + 1 + max_degree = int(self.num_nodes**0.5) + 1 degree_buckets: list[FibonacciNode[T] | None] = [None] * max_degree current_node = self.min_node nodes_to_visit = [current_node] while True: - current_node = current_node.next if current_node.next is not None else current_node + current_node = ( + current_node.next if current_node.next is not None else current_node + ) if current_node == self.min_node: break nodes_to_visit.append(current_node) @@ -190,6 +193,8 @@ def _remove_node(self, node: FibonacciNode[T]) -> None: node.prev.next = node.next node.next.prev = node.prev + if __name__ == "__main__": import doctest + doctest.testmod() From f969985dc1b3af88961a287bf3a30f3dffe2c027 Mon Sep 17 00:00:00 2001 From: Dhruv Agarwal <92450489+Dhruv127@users.noreply.github.com> Date: Sun, 1 Oct 2023 16:11:53 +0530 Subject: [PATCH 15/32] Update fibonacci_heap.py --- data_structures/heap/fibonacci_heap.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index a11a22320c6e..42e9646bfda0 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -4,7 +4,6 @@ T = TypeVar("T", bound=int) - class FibonacciNode(Generic[T]): def __init__(self, key: T) -> None: """ @@ -15,8 +14,8 @@ def __init__(self, key: T) -> None: """ self.key: T = key self.degree: int = 0 - self.parent: Optional[FibonacciNode[T] | None] = None - self.child: Optional[FibonacciNode[T] | None] = None + self.parent: Optional[FibonacciNode[T]] | None = None + self.child: Optional[FibonacciNode[T]] | None = None self.is_marked: bool = False self.next: FibonacciNode[T] = self self.prev: FibonacciNode[T] = self @@ -100,15 +99,13 @@ def _consolidate(self) -> None: >>> fh.min_node.key 3 """ - max_degree = int(self.num_nodes**0.5) + 1 + max_degree = int(self.num_nodes ** 0.5) + 1 degree_buckets: list[FibonacciNode[T] | None] = [None] * max_degree current_node = self.min_node nodes_to_visit = [current_node] while True: - current_node = ( - current_node.next if current_node.next is not None else current_node - ) + current_node = current_node.next if current_node.next is not None else current_node if current_node == self.min_node: break nodes_to_visit.append(current_node) @@ -193,8 +190,6 @@ def _remove_node(self, node: FibonacciNode[T]) -> None: node.prev.next = node.next node.next.prev = node.prev - if __name__ == "__main__": import doctest - doctest.testmod() From aef5090e3a667eb99a291198c09cd16c6d4517f2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 10:42:32 +0000 Subject: [PATCH 16/32] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/heap/fibonacci_heap.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index 42e9646bfda0..85e23494712b 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -4,6 +4,7 @@ T = TypeVar("T", bound=int) + class FibonacciNode(Generic[T]): def __init__(self, key: T) -> None: """ @@ -99,13 +100,15 @@ def _consolidate(self) -> None: >>> fh.min_node.key 3 """ - max_degree = int(self.num_nodes ** 0.5) + 1 + max_degree = int(self.num_nodes**0.5) + 1 degree_buckets: list[FibonacciNode[T] | None] = [None] * max_degree current_node = self.min_node nodes_to_visit = [current_node] while True: - current_node = current_node.next if current_node.next is not None else current_node + current_node = ( + current_node.next if current_node.next is not None else current_node + ) if current_node == self.min_node: break nodes_to_visit.append(current_node) @@ -190,6 +193,8 @@ def _remove_node(self, node: FibonacciNode[T]) -> None: node.prev.next = node.next node.next.prev = node.prev + if __name__ == "__main__": import doctest + doctest.testmod() From 4b162518379ee8cbd953f107c3b1f040681ac4fe Mon Sep 17 00:00:00 2001 From: Dhruv Agarwal <92450489+Dhruv127@users.noreply.github.com> Date: Sun, 1 Oct 2023 19:01:04 +0530 Subject: [PATCH 17/32] Update fibonacci_heap.py --- data_structures/heap/fibonacci_heap.py | 284 ++++++++++--------------- 1 file changed, 114 insertions(+), 170 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index 85e23494712b..13991755a4d8 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -1,200 +1,144 @@ -# Reference: https://en.wikipedia.org/wiki/Fibonacci_heap - -from typing import Generic, TypeVar, Optional - -T = TypeVar("T", bound=int) +# Reference: https://en.wikipedia.org/wiki/Fibonacci_heap -class FibonacciNode(Generic[T]): - def __init__(self, key: T) -> None: - """ - Create a new FibonacciNode with the given key. - - Args: - key (T): The key value associated with the node. - """ - self.key: T = key - self.degree: int = 0 - self.parent: Optional[FibonacciNode[T]] | None = None - self.child: Optional[FibonacciNode[T]] | None = None - self.is_marked: bool = False - self.next: FibonacciNode[T] = self - self.prev: FibonacciNode[T] = self +import math +class FibonacciTree: + """ + FibonacciTree represents a node in a Fibonacci heap. -class FibonacciHeap(Generic[T]): - def __init__(self) -> None: - """ - Create a new Fibonacci Heap. + Attributes: + key (int): The key value associated with the node. + children (list): A list of child nodes. + order (int): The number of children the node has. + """ - The Fibonacci Heap is initialized as an empty heap. - """ - self.min_node: FibonacciNode[T] | None = None - self.num_nodes: int = 0 + def __init__(self, key): + self.key = key + self.children = [] + self.order = 0 - def insert(self, key: T) -> None: + def add_at_end(self, t): """ - Insert a new node with the given key into the Fibonacci Heap. + Adds a child node 't' to the end of the children list. Args: - key (T): The key value to insert. - - >>> fh = FibonacciHeap() - >>> fh.insert(5) - >>> fh.insert(3) - >>> fh.insert(8) - >>> fh.extract_min() - 3 - >>> fh.extract_min() - 5 - >>> fh.extract_min() - 8 + t (FibonacciTree): The child node to add. """ - new_node = FibonacciNode(key) - if self.min_node is None: - self.min_node = new_node - else: - self._link_nodes(self.min_node, new_node) - if key < self.min_node.key: - self.min_node = new_node - self.num_nodes += 1 - - def _link_nodes( - self, - min_node: FibonacciNode[T] | None, - new_node: FibonacciNode[T] | None, - ) -> None: + self.children.append(t) + self.order = self.order + 1 + + +class FibonacciHeap: + """ + FibonacciHeap represents a priority queue data structure with efficient + amortized time complexities for various operations. + + Usage: + >>> heap = FibonacciHeap() + >>> heap.insert(5) + >>> heap.insert(3) + >>> heap.insert(7) + >>> heap.get_min() + 3 + >>> heap.extract_min() + 3 + >>> heap.get_min() + 5 + + Attributes: + trees (list): A list of FibonacciTree objects. + least (FibonacciTree): A reference to the node with the minimum key. + count (int): The total number of nodes in the heap. + """ + + def __init__(self): + self.trees = [] + self.least = None + self.count = 0 + + def insert(self, key): """ - Link two nodes together in the Fibonacci Heap. + Inserts a new node with the given key into the Fibonacci heap. Args: - min_node (FibonacciNode): The minimum node. - new_node (FibonacciNode): The new node to be linked. - - >>> fh = FibonacciHeap() - >>> node1 = FibonacciNode(3) - >>> node2 = FibonacciNode(5) - >>> fh._link_nodes(node1, node2) - >>> node1.next == node2 and node2.prev == node1 - True + key (int): The key to insert. """ - if min_node is None or new_node is None: - raise ValueError("min_node and new_node cannot be None") + new_tree = FibonacciTree(key) + self.trees.append(new_tree) + if (self.least is None or key < self.least.key): + self.least = new_tree + self.count = self.count + 1 - new_node.next = min_node.next - min_node.next = new_node - new_node.prev = min_node - new_node.next.prev = new_node - - def _consolidate(self) -> None: + def get_min(self): """ - Consolidate the heap by combining trees with the same degree. - - This is an internal method used to maintain the Fibonacci Heap's properties. + Returns the minimum key in the Fibonacci heap. - >>> fh = FibonacciHeap() - >>> fh.insert(5) - >>> fh.insert(3) - >>> fh.insert(8) - >>> fh._consolidate() - >>> fh.min_node.key - 3 + Returns: + int: The minimum key. """ - max_degree = int(self.num_nodes**0.5) + 1 - degree_buckets: list[FibonacciNode[T] | None] = [None] * max_degree - - current_node = self.min_node - nodes_to_visit = [current_node] - while True: - current_node = ( - current_node.next if current_node.next is not None else current_node - ) - if current_node == self.min_node: - break - nodes_to_visit.append(current_node) - - for node in nodes_to_visit: - if node is not None: - degree = node.degree - while degree_buckets[degree]: - other = degree_buckets[degree] - if node.key is not None and other.key is not None: - if node.key > other.key: - node, other = other, node - self._link_nodes(node, other) - degree_buckets[degree] = None - degree += 1 - degree_buckets[degree] = node - - self.min_node = None - for node in degree_buckets: - if node: - if self.min_node is None or node.key < self.min_node.key: - self.min_node = node - - def extract_min(self) -> T | None: + if self.least is None: + return None + return self.least.key + + def extract_min(self): """ - Extract the minimum element from the Fibonacci Heap. + Removes and returns the node with the minimum key from the Fibonacci heap. Returns: - T | None: The minimum element, or None if the heap is empty. - - >>> fh = FibonacciHeap() - >>> fh.insert(5) - >>> fh.insert(3) - >>> fh.insert(8) - >>> fh.extract_min() - 3 - >>> fh.extract_min() - 5 - >>> fh.extract_min() - 8 - >>> fh.extract_min() + int: The minimum key. """ - min_node = self.min_node - if min_node: - if min_node.child: - child = min_node.child - while True: - next_child = child.next - child.prev = min_node.prev - child.next = min_node.next - min_node.prev.next = child - min_node.next.prev = child - min_node.child = None - if next_child == min_node.child: - break - child = next_child - self._remove_node(min_node) - if min_node == min_node.next: - self.min_node = None + smallest = self.least + if smallest is not None: + for child in smallest.children: + self.trees.append(child) + self.trees.remove(smallest) + if self.trees == []: + self.least = None else: - self.min_node = min_node.next - self._consolidate() - self.num_nodes -= 1 - return min_node.key if min_node else None + self.least = self.trees[0] + self.consolidate() + self.count = self.count - 1 + return smallest.key - def _remove_node(self, node: FibonacciNode[T]) -> None: + def consolidate(self): """ - Remove a node from the doubly linked list of nodes. - - Args: - node (FibonacciNode): The node to remove. - - >>> fh = FibonacciHeap() - >>> node1 = FibonacciNode(3) - >>> fh._remove_node(node1) - >>> node1.next == node1.prev == node1 - True + Consolidates trees in the Fibonacci heap to maintain the heap's structure. """ - if node is None: - raise ValueError("node cannot be None") - - node.prev.next = node.next - node.next.prev = node.prev - + aux = (floor_log2(self.count) + 1) * [None] + + while self.trees != []: + x = self.trees[0] + order = x.order + self.trees.remove(x) + while aux[order] is not None: + y = aux[order] + if x.key > y.key: + x, y = y, x + x.add_at_end(y) + aux[order] = None + order = order + 1 + aux[order] = x + + self.least = None + for k in aux: + if k is not None: + self.trees.append(k) + if (self.least is None or k.key < self.least.key): + self.least = k + +def floor_log2(x): + """ + Computes the floor of the base-2 logarithm of 'x'. + + Args: + x (int): The input number. + + Returns: + int: The floor of the base-2 logarithm of 'x'. + """ + return math.frexp(x)[1] - 1 if __name__ == "__main__": import doctest - doctest.testmod() From b554801181541a579454b8dc1e2ba5b85cb66da9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 13:31:40 +0000 Subject: [PATCH 18/32] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/heap/fibonacci_heap.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index 13991755a4d8..4bdf5c3d765c 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -1,8 +1,8 @@ - # Reference: https://en.wikipedia.org/wiki/Fibonacci_heap import math + class FibonacciTree: """ FibonacciTree represents a node in a Fibonacci heap. @@ -66,7 +66,7 @@ def insert(self, key): """ new_tree = FibonacciTree(key) self.trees.append(new_tree) - if (self.least is None or key < self.least.key): + if self.least is None or key < self.least.key: self.least = new_tree self.count = self.count + 1 @@ -88,8 +88,7 @@ def extract_min(self): Returns: int: The minimum key. """ - smallest = self.least - if smallest is not None: + if (smallest := self.least) is not None: for child in smallest.children: self.trees.append(child) self.trees.remove(smallest) @@ -124,9 +123,10 @@ def consolidate(self): for k in aux: if k is not None: self.trees.append(k) - if (self.least is None or k.key < self.least.key): + if self.least is None or k.key < self.least.key: self.least = k + def floor_log2(x): """ Computes the floor of the base-2 logarithm of 'x'. @@ -139,6 +139,8 @@ def floor_log2(x): """ return math.frexp(x)[1] - 1 + if __name__ == "__main__": import doctest + doctest.testmod() From 908891c6fc7530535c69908bed2ffdccae0f18c2 Mon Sep 17 00:00:00 2001 From: Dhruv Agarwal <92450489+Dhruv127@users.noreply.github.com> Date: Sun, 1 Oct 2023 19:30:14 +0530 Subject: [PATCH 19/32] Update fibonacci_heap.py --- data_structures/heap/fibonacci_heap.py | 42 +++++++++++++++----------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index 4bdf5c3d765c..4c60b6a0869e 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -1,3 +1,4 @@ + # Reference: https://en.wikipedia.org/wiki/Fibonacci_heap import math @@ -13,21 +14,26 @@ class FibonacciTree: order (int): The number of children the node has. """ - def __init__(self, key): + def __init__(self, key:int) -> None: self.key = key self.children = [] self.order = 0 - def add_at_end(self, t): + def add_at_end(self, child_node: 'FibonacciTree') -> None: """ - Adds a child node 't' to the end of the children list. + Adds a child node 'child_node' to the end of the children list. Args: - t (FibonacciTree): The child node to add. + child_node (FibonacciTree): The child node to add. """ - self.children.append(t) + self.children.append(child_node) self.order = self.order + 1 +# Doctest for add_at_end +if __name__ == "__main__": + import doctest + doctest.testmod() + class FibonacciHeap: """ @@ -52,12 +58,12 @@ class FibonacciHeap: count (int): The total number of nodes in the heap. """ - def __init__(self): + def __init__(self)->None: self.trees = [] self.least = None self.count = 0 - def insert(self, key): + def insert(self,key:int)->None: """ Inserts a new node with the given key into the Fibonacci heap. @@ -66,11 +72,11 @@ def insert(self, key): """ new_tree = FibonacciTree(key) self.trees.append(new_tree) - if self.least is None or key < self.least.key: + if (self.least is None or key < self.least.key): self.least = new_tree self.count = self.count + 1 - def get_min(self): + def get_min(self)->int: """ Returns the minimum key in the Fibonacci heap. @@ -81,14 +87,15 @@ def get_min(self): return None return self.least.key - def extract_min(self): + def extract_min(self)->int: """ Removes and returns the node with the minimum key from the Fibonacci heap. Returns: int: The minimum key. """ - if (smallest := self.least) is not None: + smallest = self.least + if smallest is not None: for child in smallest.children: self.trees.append(child) self.trees.remove(smallest) @@ -100,7 +107,7 @@ def extract_min(self): self.count = self.count - 1 return smallest.key - def consolidate(self): + def consolidate(self)->None: """ Consolidates trees in the Fibonacci heap to maintain the heap's structure. """ @@ -123,11 +130,10 @@ def consolidate(self): for k in aux: if k is not None: self.trees.append(k) - if self.least is None or k.key < self.least.key: + if (self.least is None or k.key < self.least.key): self.least = k - -def floor_log2(x): +def floor_log2(x: int) -> int: """ Computes the floor of the base-2 logarithm of 'x'. @@ -138,9 +144,11 @@ def floor_log2(x): int: The floor of the base-2 logarithm of 'x'. """ return math.frexp(x)[1] - 1 - - +# Doctest for floor_log2 if __name__ == "__main__": import doctest + doctest.testmod() +if __name__ == "__main__": + import doctest doctest.testmod() From f08e1897aefbcc612ac2842dbfe60fb0c4217884 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 14:00:48 +0000 Subject: [PATCH 20/32] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/heap/fibonacci_heap.py | 29 +++++++++++++++----------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index 4c60b6a0869e..6c23197ab916 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -1,4 +1,3 @@ - # Reference: https://en.wikipedia.org/wiki/Fibonacci_heap import math @@ -14,12 +13,12 @@ class FibonacciTree: order (int): The number of children the node has. """ - def __init__(self, key:int) -> None: + def __init__(self, key: int) -> None: self.key = key self.children = [] self.order = 0 - def add_at_end(self, child_node: 'FibonacciTree') -> None: + def add_at_end(self, child_node: "FibonacciTree") -> None: """ Adds a child node 'child_node' to the end of the children list. @@ -29,9 +28,11 @@ def add_at_end(self, child_node: 'FibonacciTree') -> None: self.children.append(child_node) self.order = self.order + 1 + # Doctest for add_at_end if __name__ == "__main__": import doctest + doctest.testmod() @@ -58,12 +59,12 @@ class FibonacciHeap: count (int): The total number of nodes in the heap. """ - def __init__(self)->None: + def __init__(self) -> None: self.trees = [] self.least = None self.count = 0 - def insert(self,key:int)->None: + def insert(self, key: int) -> None: """ Inserts a new node with the given key into the Fibonacci heap. @@ -72,11 +73,11 @@ def insert(self,key:int)->None: """ new_tree = FibonacciTree(key) self.trees.append(new_tree) - if (self.least is None or key < self.least.key): + if self.least is None or key < self.least.key: self.least = new_tree self.count = self.count + 1 - def get_min(self)->int: + def get_min(self) -> int: """ Returns the minimum key in the Fibonacci heap. @@ -87,15 +88,14 @@ def get_min(self)->int: return None return self.least.key - def extract_min(self)->int: + def extract_min(self) -> int: """ Removes and returns the node with the minimum key from the Fibonacci heap. Returns: int: The minimum key. """ - smallest = self.least - if smallest is not None: + if (smallest := self.least) is not None: for child in smallest.children: self.trees.append(child) self.trees.remove(smallest) @@ -107,7 +107,7 @@ def extract_min(self)->int: self.count = self.count - 1 return smallest.key - def consolidate(self)->None: + def consolidate(self) -> None: """ Consolidates trees in the Fibonacci heap to maintain the heap's structure. """ @@ -130,9 +130,10 @@ def consolidate(self)->None: for k in aux: if k is not None: self.trees.append(k) - if (self.least is None or k.key < self.least.key): + if self.least is None or k.key < self.least.key: self.least = k + def floor_log2(x: int) -> int: """ Computes the floor of the base-2 logarithm of 'x'. @@ -144,11 +145,15 @@ def floor_log2(x: int) -> int: int: The floor of the base-2 logarithm of 'x'. """ return math.frexp(x)[1] - 1 + + # Doctest for floor_log2 if __name__ == "__main__": import doctest + doctest.testmod() if __name__ == "__main__": import doctest + doctest.testmod() From e67a442b44e3a4cf565dcf4c57133ca0e4ac3e17 Mon Sep 17 00:00:00 2001 From: Dhruv Agarwal <92450489+Dhruv127@users.noreply.github.com> Date: Sun, 1 Oct 2023 19:41:13 +0530 Subject: [PATCH 21/32] Update fibonacci_heap.py --- data_structures/heap/fibonacci_heap.py | 38 ++++++++++++-------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index 6c23197ab916..72f57f64681c 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -1,6 +1,8 @@ + # Reference: https://en.wikipedia.org/wiki/Fibonacci_heap import math +from typing import List class FibonacciTree: @@ -13,12 +15,12 @@ class FibonacciTree: order (int): The number of children the node has. """ - def __init__(self, key: int) -> None: + def __init__(self, key:int) -> None: self.key = key - self.children = [] + self.children: List[FibonacciTree] = [] self.order = 0 - def add_at_end(self, child_node: "FibonacciTree") -> None: + def add_at_end(self, child_node: 'FibonacciTree') -> None: """ Adds a child node 'child_node' to the end of the children list. @@ -28,11 +30,9 @@ def add_at_end(self, child_node: "FibonacciTree") -> None: self.children.append(child_node) self.order = self.order + 1 - # Doctest for add_at_end if __name__ == "__main__": import doctest - doctest.testmod() @@ -59,12 +59,12 @@ class FibonacciHeap: count (int): The total number of nodes in the heap. """ - def __init__(self) -> None: - self.trees = [] + def __init__(self)->None: + self.trees: List[FibonacciTree] = [] self.least = None self.count = 0 - def insert(self, key: int) -> None: + def insert(self,key:int)->None: """ Inserts a new node with the given key into the Fibonacci heap. @@ -73,11 +73,11 @@ def insert(self, key: int) -> None: """ new_tree = FibonacciTree(key) self.trees.append(new_tree) - if self.least is None or key < self.least.key: + if (self.least is None or key < self.least.key): self.least = new_tree self.count = self.count + 1 - def get_min(self) -> int: + def get_min(self)->int: """ Returns the minimum key in the Fibonacci heap. @@ -85,17 +85,19 @@ def get_min(self) -> int: int: The minimum key. """ if self.least is None: - return None + return -1 return self.least.key - def extract_min(self) -> int: + def extract_min(self)->int: """ Removes and returns the node with the minimum key from the Fibonacci heap. Returns: int: The minimum key. """ - if (smallest := self.least) is not None: + smallest = None + if self.least is not None: + smallest = self.least for child in smallest.children: self.trees.append(child) self.trees.remove(smallest) @@ -106,8 +108,9 @@ def extract_min(self) -> int: self.consolidate() self.count = self.count - 1 return smallest.key + return -1 - def consolidate(self) -> None: + def consolidate(self)->None: """ Consolidates trees in the Fibonacci heap to maintain the heap's structure. """ @@ -130,10 +133,9 @@ def consolidate(self) -> None: for k in aux: if k is not None: self.trees.append(k) - if self.least is None or k.key < self.least.key: + if (self.least is None or k.key < self.least.key): self.least = k - def floor_log2(x: int) -> int: """ Computes the floor of the base-2 logarithm of 'x'. @@ -145,15 +147,11 @@ def floor_log2(x: int) -> int: int: The floor of the base-2 logarithm of 'x'. """ return math.frexp(x)[1] - 1 - - # Doctest for floor_log2 if __name__ == "__main__": import doctest - doctest.testmod() if __name__ == "__main__": import doctest - doctest.testmod() From dab519f47d95afada8968c13d4eb5e3b2d528692 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 14:11:45 +0000 Subject: [PATCH 22/32] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/heap/fibonacci_heap.py | 28 ++++++++++++++++---------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index 72f57f64681c..fd609134460c 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -1,4 +1,3 @@ - # Reference: https://en.wikipedia.org/wiki/Fibonacci_heap import math @@ -15,12 +14,12 @@ class FibonacciTree: order (int): The number of children the node has. """ - def __init__(self, key:int) -> None: + def __init__(self, key: int) -> None: self.key = key self.children: List[FibonacciTree] = [] self.order = 0 - def add_at_end(self, child_node: 'FibonacciTree') -> None: + def add_at_end(self, child_node: "FibonacciTree") -> None: """ Adds a child node 'child_node' to the end of the children list. @@ -30,9 +29,11 @@ def add_at_end(self, child_node: 'FibonacciTree') -> None: self.children.append(child_node) self.order = self.order + 1 + # Doctest for add_at_end if __name__ == "__main__": import doctest + doctest.testmod() @@ -59,12 +60,12 @@ class FibonacciHeap: count (int): The total number of nodes in the heap. """ - def __init__(self)->None: + def __init__(self) -> None: self.trees: List[FibonacciTree] = [] self.least = None self.count = 0 - def insert(self,key:int)->None: + def insert(self, key: int) -> None: """ Inserts a new node with the given key into the Fibonacci heap. @@ -73,11 +74,11 @@ def insert(self,key:int)->None: """ new_tree = FibonacciTree(key) self.trees.append(new_tree) - if (self.least is None or key < self.least.key): + if self.least is None or key < self.least.key: self.least = new_tree self.count = self.count + 1 - def get_min(self)->int: + def get_min(self) -> int: """ Returns the minimum key in the Fibonacci heap. @@ -88,14 +89,14 @@ def get_min(self)->int: return -1 return self.least.key - def extract_min(self)->int: + def extract_min(self) -> int: """ Removes and returns the node with the minimum key from the Fibonacci heap. Returns: int: The minimum key. """ - smallest = None + smallest = None if self.least is not None: smallest = self.least for child in smallest.children: @@ -110,7 +111,7 @@ def extract_min(self)->int: return smallest.key return -1 - def consolidate(self)->None: + def consolidate(self) -> None: """ Consolidates trees in the Fibonacci heap to maintain the heap's structure. """ @@ -133,9 +134,10 @@ def consolidate(self)->None: for k in aux: if k is not None: self.trees.append(k) - if (self.least is None or k.key < self.least.key): + if self.least is None or k.key < self.least.key: self.least = k + def floor_log2(x: int) -> int: """ Computes the floor of the base-2 logarithm of 'x'. @@ -147,11 +149,15 @@ def floor_log2(x: int) -> int: int: The floor of the base-2 logarithm of 'x'. """ return math.frexp(x)[1] - 1 + + # Doctest for floor_log2 if __name__ == "__main__": import doctest + doctest.testmod() if __name__ == "__main__": import doctest + doctest.testmod() From 11d84fe669bdd4786fa5abe22c0cec9b72d0d99d Mon Sep 17 00:00:00 2001 From: Dhruv Agarwal <92450489+Dhruv127@users.noreply.github.com> Date: Sun, 1 Oct 2023 19:46:03 +0530 Subject: [PATCH 23/32] Update fibonacci_heap.py --- data_structures/heap/fibonacci_heap.py | 51 ++++++++++---------------- 1 file changed, 20 insertions(+), 31 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index fd609134460c..7b6a2d4ebab9 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -1,7 +1,7 @@ # Reference: https://en.wikipedia.org/wiki/Fibonacci_heap import math -from typing import List +from typing import Optional class FibonacciTree: @@ -16,10 +16,10 @@ class FibonacciTree: def __init__(self, key: int) -> None: self.key = key - self.children: List[FibonacciTree] = [] + self.children: list['FibonacciTree'] = [] self.order = 0 - def add_at_end(self, child_node: "FibonacciTree") -> None: + def add_at_end(self, child_node: 'FibonacciTree') -> None: """ Adds a child node 'child_node' to the end of the children list. @@ -30,13 +30,6 @@ def add_at_end(self, child_node: "FibonacciTree") -> None: self.order = self.order + 1 -# Doctest for add_at_end -if __name__ == "__main__": - import doctest - - doctest.testmod() - - class FibonacciHeap: """ FibonacciHeap represents a priority queue data structure with efficient @@ -61,8 +54,8 @@ class FibonacciHeap: """ def __init__(self) -> None: - self.trees: List[FibonacciTree] = [] - self.least = None + self.trees: list['FibonacciTree'] = [] + self.least: Optional['FibonacciTree'] = None self.count = 0 def insert(self, key: int) -> None: @@ -74,11 +67,11 @@ def insert(self, key: int) -> None: """ new_tree = FibonacciTree(key) self.trees.append(new_tree) - if self.least is None or key < self.least.key: + if (self.least is None or key < self.least.key): self.least = new_tree self.count = self.count + 1 - def get_min(self) -> int: + def get_min(self) -> Optional[int]: """ Returns the minimum key in the Fibonacci heap. @@ -86,30 +79,30 @@ def get_min(self) -> int: int: The minimum key. """ if self.least is None: - return -1 + return None return self.least.key - def extract_min(self) -> int: + def extract_min(self) -> Optional[int]: """ Removes and returns the node with the minimum key from the Fibonacci heap. Returns: int: The minimum key. """ - smallest = None - if self.least is not None: - smallest = self.least + smallest = self.least + if smallest is not None: for child in smallest.children: - self.trees.append(child) + if child is not None: + self.trees.append(child) self.trees.remove(smallest) - if self.trees == []: - self.least = None - else: + if self.trees: self.least = self.trees[0] self.consolidate() + else: + self.least = None self.count = self.count - 1 return smallest.key - return -1 + return None def consolidate(self) -> None: """ @@ -117,7 +110,7 @@ def consolidate(self) -> None: """ aux = (floor_log2(self.count) + 1) * [None] - while self.trees != []: + while self.trees: x = self.trees[0] order = x.order self.trees.remove(x) @@ -134,10 +127,9 @@ def consolidate(self) -> None: for k in aux: if k is not None: self.trees.append(k) - if self.least is None or k.key < self.least.key: + if (self.least is None or k.key < self.least.key): self.least = k - def floor_log2(x: int) -> int: """ Computes the floor of the base-2 logarithm of 'x'. @@ -148,16 +140,13 @@ def floor_log2(x: int) -> int: Returns: int: The floor of the base-2 logarithm of 'x'. """ - return math.frexp(x)[1] - 1 - + return math.floor(math.log2(x)) if x > 0 else 0 # Doctest for floor_log2 if __name__ == "__main__": import doctest - doctest.testmod() if __name__ == "__main__": import doctest - doctest.testmod() From d864b47a69e6ef3ea9889a3be502834c0c6d2645 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 14:16:36 +0000 Subject: [PATCH 24/32] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/heap/fibonacci_heap.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index 7b6a2d4ebab9..b7b6a22407cf 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -16,10 +16,10 @@ class FibonacciTree: def __init__(self, key: int) -> None: self.key = key - self.children: list['FibonacciTree'] = [] + self.children: list["FibonacciTree"] = [] self.order = 0 - def add_at_end(self, child_node: 'FibonacciTree') -> None: + def add_at_end(self, child_node: "FibonacciTree") -> None: """ Adds a child node 'child_node' to the end of the children list. @@ -54,8 +54,8 @@ class FibonacciHeap: """ def __init__(self) -> None: - self.trees: list['FibonacciTree'] = [] - self.least: Optional['FibonacciTree'] = None + self.trees: list["FibonacciTree"] = [] + self.least: Optional["FibonacciTree"] = None self.count = 0 def insert(self, key: int) -> None: @@ -67,7 +67,7 @@ def insert(self, key: int) -> None: """ new_tree = FibonacciTree(key) self.trees.append(new_tree) - if (self.least is None or key < self.least.key): + if self.least is None or key < self.least.key: self.least = new_tree self.count = self.count + 1 @@ -89,8 +89,7 @@ def extract_min(self) -> Optional[int]: Returns: int: The minimum key. """ - smallest = self.least - if smallest is not None: + if (smallest := self.least) is not None: for child in smallest.children: if child is not None: self.trees.append(child) @@ -127,9 +126,10 @@ def consolidate(self) -> None: for k in aux: if k is not None: self.trees.append(k) - if (self.least is None or k.key < self.least.key): + if self.least is None or k.key < self.least.key: self.least = k + def floor_log2(x: int) -> int: """ Computes the floor of the base-2 logarithm of 'x'. @@ -142,11 +142,14 @@ def floor_log2(x: int) -> int: """ return math.floor(math.log2(x)) if x > 0 else 0 + # Doctest for floor_log2 if __name__ == "__main__": import doctest + doctest.testmod() if __name__ == "__main__": import doctest + doctest.testmod() From 9fc373dd9ccf258febae1e7c644fd1410c0588c4 Mon Sep 17 00:00:00 2001 From: Dhruv Agarwal <92450489+Dhruv127@users.noreply.github.com> Date: Sun, 1 Oct 2023 19:53:38 +0530 Subject: [PATCH 25/32] Update fibonacci_heap.py --- data_structures/heap/fibonacci_heap.py | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index b7b6a22407cf..efc9ef60a29e 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -1,7 +1,6 @@ # Reference: https://en.wikipedia.org/wiki/Fibonacci_heap import math -from typing import Optional class FibonacciTree: @@ -16,10 +15,10 @@ class FibonacciTree: def __init__(self, key: int) -> None: self.key = key - self.children: list["FibonacciTree"] = [] + self.children: list['FibonacciTree'] = [] self.order = 0 - def add_at_end(self, child_node: "FibonacciTree") -> None: + def add_at_end(self, child_node: 'FibonacciTree') -> None: """ Adds a child node 'child_node' to the end of the children list. @@ -49,13 +48,13 @@ class FibonacciHeap: Attributes: trees (list): A list of FibonacciTree objects. - least (FibonacciTree): A reference to the node with the minimum key. + least (FibonacciTree | None): A reference to the node with the minimum key. count (int): The total number of nodes in the heap. """ def __init__(self) -> None: - self.trees: list["FibonacciTree"] = [] - self.least: Optional["FibonacciTree"] = None + self.trees: list['FibonacciTree'] = [] + self.least: 'FibonacciTree' | None = None self.count = 0 def insert(self, key: int) -> None: @@ -67,11 +66,11 @@ def insert(self, key: int) -> None: """ new_tree = FibonacciTree(key) self.trees.append(new_tree) - if self.least is None or key < self.least.key: + if (self.least is None or key < self.least.key): self.least = new_tree self.count = self.count + 1 - def get_min(self) -> Optional[int]: + def get_min(self) -> int | None: """ Returns the minimum key in the Fibonacci heap. @@ -82,14 +81,15 @@ def get_min(self) -> Optional[int]: return None return self.least.key - def extract_min(self) -> Optional[int]: + def extract_min(self) -> int | None: """ Removes and returns the node with the minimum key from the Fibonacci heap. Returns: int: The minimum key. """ - if (smallest := self.least) is not None: + smallest = self.least + if smallest is not None: for child in smallest.children: if child is not None: self.trees.append(child) @@ -126,10 +126,9 @@ def consolidate(self) -> None: for k in aux: if k is not None: self.trees.append(k) - if self.least is None or k.key < self.least.key: + if (self.least is None or k.key < self.least.key): self.least = k - def floor_log2(x: int) -> int: """ Computes the floor of the base-2 logarithm of 'x'. @@ -142,14 +141,11 @@ def floor_log2(x: int) -> int: """ return math.floor(math.log2(x)) if x > 0 else 0 - # Doctest for floor_log2 if __name__ == "__main__": import doctest - doctest.testmod() if __name__ == "__main__": import doctest - doctest.testmod() From 0a897c3219473a3e353af384b615a51ab5b95348 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 14:24:10 +0000 Subject: [PATCH 26/32] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/heap/fibonacci_heap.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index efc9ef60a29e..efca0a74e8cc 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -15,10 +15,10 @@ class FibonacciTree: def __init__(self, key: int) -> None: self.key = key - self.children: list['FibonacciTree'] = [] + self.children: list["FibonacciTree"] = [] self.order = 0 - def add_at_end(self, child_node: 'FibonacciTree') -> None: + def add_at_end(self, child_node: "FibonacciTree") -> None: """ Adds a child node 'child_node' to the end of the children list. @@ -53,8 +53,8 @@ class FibonacciHeap: """ def __init__(self) -> None: - self.trees: list['FibonacciTree'] = [] - self.least: 'FibonacciTree' | None = None + self.trees: list["FibonacciTree"] = [] + self.least: "FibonacciTree" | None = None self.count = 0 def insert(self, key: int) -> None: @@ -66,7 +66,7 @@ def insert(self, key: int) -> None: """ new_tree = FibonacciTree(key) self.trees.append(new_tree) - if (self.least is None or key < self.least.key): + if self.least is None or key < self.least.key: self.least = new_tree self.count = self.count + 1 @@ -88,8 +88,7 @@ def extract_min(self) -> int | None: Returns: int: The minimum key. """ - smallest = self.least - if smallest is not None: + if (smallest := self.least) is not None: for child in smallest.children: if child is not None: self.trees.append(child) @@ -126,9 +125,10 @@ def consolidate(self) -> None: for k in aux: if k is not None: self.trees.append(k) - if (self.least is None or k.key < self.least.key): + if self.least is None or k.key < self.least.key: self.least = k + def floor_log2(x: int) -> int: """ Computes the floor of the base-2 logarithm of 'x'. @@ -141,11 +141,14 @@ def floor_log2(x: int) -> int: """ return math.floor(math.log2(x)) if x > 0 else 0 + # Doctest for floor_log2 if __name__ == "__main__": import doctest + doctest.testmod() if __name__ == "__main__": import doctest + doctest.testmod() From b2df7cd18be383edc54382bf45a54dfd5b491605 Mon Sep 17 00:00:00 2001 From: Dhruv Agarwal <92450489+Dhruv127@users.noreply.github.com> Date: Sun, 1 Oct 2023 20:03:16 +0530 Subject: [PATCH 27/32] Update fibonacci_heap.py --- data_structures/heap/fibonacci_heap.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index efca0a74e8cc..b1660d3aab3a 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -15,10 +15,10 @@ class FibonacciTree: def __init__(self, key: int) -> None: self.key = key - self.children: list["FibonacciTree"] = [] + self.children: list['FibonacciTree'] = [] self.order = 0 - def add_at_end(self, child_node: "FibonacciTree") -> None: + def add_at_end(self, child_node: 'FibonacciTree') -> None: """ Adds a child node 'child_node' to the end of the children list. @@ -53,8 +53,8 @@ class FibonacciHeap: """ def __init__(self) -> None: - self.trees: list["FibonacciTree"] = [] - self.least: "FibonacciTree" | None = None + self.trees: list['FibonacciTree'] = [] + self.least: 'FibonacciTree' | None = None self.count = 0 def insert(self, key: int) -> None: @@ -66,7 +66,7 @@ def insert(self, key: int) -> None: """ new_tree = FibonacciTree(key) self.trees.append(new_tree) - if self.least is None or key < self.least.key: + if (self.least is None or key < self.least.key): self.least = new_tree self.count = self.count + 1 @@ -88,7 +88,8 @@ def extract_min(self) -> int | None: Returns: int: The minimum key. """ - if (smallest := self.least) is not None: + smallest = self.least + if smallest is not None: for child in smallest.children: if child is not None: self.trees.append(child) @@ -110,6 +111,9 @@ def consolidate(self) -> None: while self.trees: x = self.trees[0] + if x is None: + self.trees.pop(0) # Remove the None value + continue # Skip processing None values order = x.order self.trees.remove(x) while aux[order] is not None: @@ -125,10 +129,9 @@ def consolidate(self) -> None: for k in aux: if k is not None: self.trees.append(k) - if self.least is None or k.key < self.least.key: + if (self.least is None or k.key < self.least.key): self.least = k - - + def floor_log2(x: int) -> int: """ Computes the floor of the base-2 logarithm of 'x'. @@ -141,14 +144,11 @@ def floor_log2(x: int) -> int: """ return math.floor(math.log2(x)) if x > 0 else 0 - # Doctest for floor_log2 if __name__ == "__main__": import doctest - doctest.testmod() if __name__ == "__main__": import doctest - doctest.testmod() From e4216106b18bb66a81daf2e8b3e5bf611ed9025d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 14:33:49 +0000 Subject: [PATCH 28/32] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/heap/fibonacci_heap.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index b1660d3aab3a..4145ab467755 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -15,10 +15,10 @@ class FibonacciTree: def __init__(self, key: int) -> None: self.key = key - self.children: list['FibonacciTree'] = [] + self.children: list["FibonacciTree"] = [] self.order = 0 - def add_at_end(self, child_node: 'FibonacciTree') -> None: + def add_at_end(self, child_node: "FibonacciTree") -> None: """ Adds a child node 'child_node' to the end of the children list. @@ -53,8 +53,8 @@ class FibonacciHeap: """ def __init__(self) -> None: - self.trees: list['FibonacciTree'] = [] - self.least: 'FibonacciTree' | None = None + self.trees: list["FibonacciTree"] = [] + self.least: "FibonacciTree" | None = None self.count = 0 def insert(self, key: int) -> None: @@ -66,7 +66,7 @@ def insert(self, key: int) -> None: """ new_tree = FibonacciTree(key) self.trees.append(new_tree) - if (self.least is None or key < self.least.key): + if self.least is None or key < self.least.key: self.least = new_tree self.count = self.count + 1 @@ -88,8 +88,7 @@ def extract_min(self) -> int | None: Returns: int: The minimum key. """ - smallest = self.least - if smallest is not None: + if (smallest := self.least) is not None: for child in smallest.children: if child is not None: self.trees.append(child) @@ -129,9 +128,10 @@ def consolidate(self) -> None: for k in aux: if k is not None: self.trees.append(k) - if (self.least is None or k.key < self.least.key): + if self.least is None or k.key < self.least.key: self.least = k - + + def floor_log2(x: int) -> int: """ Computes the floor of the base-2 logarithm of 'x'. @@ -144,11 +144,14 @@ def floor_log2(x: int) -> int: """ return math.floor(math.log2(x)) if x > 0 else 0 + # Doctest for floor_log2 if __name__ == "__main__": import doctest + doctest.testmod() if __name__ == "__main__": import doctest + doctest.testmod() From 5076ab436796966c534eaaf0f284094291b935df Mon Sep 17 00:00:00 2001 From: Dhruv Agarwal <92450489+Dhruv127@users.noreply.github.com> Date: Sun, 1 Oct 2023 20:10:24 +0530 Subject: [PATCH 29/32] Update fibonacci_heap.py --- data_structures/heap/fibonacci_heap.py | 33 ++++++++++++-------------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index 4145ab467755..ecb3ce6398a0 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -15,10 +15,10 @@ class FibonacciTree: def __init__(self, key: int) -> None: self.key = key - self.children: list["FibonacciTree"] = [] + self.children: list['FibonacciTree'] = [] self.order = 0 - def add_at_end(self, child_node: "FibonacciTree") -> None: + def add_at_end(self, child_node: 'FibonacciTree') -> None: """ Adds a child node 'child_node' to the end of the children list. @@ -53,8 +53,8 @@ class FibonacciHeap: """ def __init__(self) -> None: - self.trees: list["FibonacciTree"] = [] - self.least: "FibonacciTree" | None = None + self.trees: list['FibonacciTree'] = [] + self.least: 'FibonacciTree' | None = None self.count = 0 def insert(self, key: int) -> None: @@ -66,7 +66,7 @@ def insert(self, key: int) -> None: """ new_tree = FibonacciTree(key) self.trees.append(new_tree) - if self.least is None or key < self.least.key: + if (self.least is None or key < self.least.key): self.least = new_tree self.count = self.count + 1 @@ -88,7 +88,8 @@ def extract_min(self) -> int | None: Returns: int: The minimum key. """ - if (smallest := self.least) is not None: + smallest = self.least + if smallest is not None: for child in smallest.children: if child is not None: self.trees.append(child) @@ -108,13 +109,13 @@ def consolidate(self) -> None: """ aux = (floor_log2(self.count) + 1) * [None] - while self.trees: - x = self.trees[0] - if x is None: - self.trees.pop(0) # Remove the None value - continue # Skip processing None values + # Filter out None values from self.trees + valid_trees = [tree for tree in self.trees if tree is not None] + + while valid_trees: + x = valid_trees[0] order = x.order - self.trees.remove(x) + valid_trees.remove(x) while aux[order] is not None: y = aux[order] if x.key > y.key: @@ -128,10 +129,9 @@ def consolidate(self) -> None: for k in aux: if k is not None: self.trees.append(k) - if self.least is None or k.key < self.least.key: + if (self.least is None or k.key < self.least.key): self.least = k - - + def floor_log2(x: int) -> int: """ Computes the floor of the base-2 logarithm of 'x'. @@ -144,14 +144,11 @@ def floor_log2(x: int) -> int: """ return math.floor(math.log2(x)) if x > 0 else 0 - # Doctest for floor_log2 if __name__ == "__main__": import doctest - doctest.testmod() if __name__ == "__main__": import doctest - doctest.testmod() From 757daaf30cd823c185d1055be80e78fb20286942 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 14:40:57 +0000 Subject: [PATCH 30/32] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/heap/fibonacci_heap.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index ecb3ce6398a0..44c1c94c5a68 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -15,10 +15,10 @@ class FibonacciTree: def __init__(self, key: int) -> None: self.key = key - self.children: list['FibonacciTree'] = [] + self.children: list["FibonacciTree"] = [] self.order = 0 - def add_at_end(self, child_node: 'FibonacciTree') -> None: + def add_at_end(self, child_node: "FibonacciTree") -> None: """ Adds a child node 'child_node' to the end of the children list. @@ -53,8 +53,8 @@ class FibonacciHeap: """ def __init__(self) -> None: - self.trees: list['FibonacciTree'] = [] - self.least: 'FibonacciTree' | None = None + self.trees: list["FibonacciTree"] = [] + self.least: "FibonacciTree" | None = None self.count = 0 def insert(self, key: int) -> None: @@ -66,7 +66,7 @@ def insert(self, key: int) -> None: """ new_tree = FibonacciTree(key) self.trees.append(new_tree) - if (self.least is None or key < self.least.key): + if self.least is None or key < self.least.key: self.least = new_tree self.count = self.count + 1 @@ -88,8 +88,7 @@ def extract_min(self) -> int | None: Returns: int: The minimum key. """ - smallest = self.least - if smallest is not None: + if (smallest := self.least) is not None: for child in smallest.children: if child is not None: self.trees.append(child) @@ -129,9 +128,10 @@ def consolidate(self) -> None: for k in aux: if k is not None: self.trees.append(k) - if (self.least is None or k.key < self.least.key): + if self.least is None or k.key < self.least.key: self.least = k - + + def floor_log2(x: int) -> int: """ Computes the floor of the base-2 logarithm of 'x'. @@ -144,11 +144,14 @@ def floor_log2(x: int) -> int: """ return math.floor(math.log2(x)) if x > 0 else 0 + # Doctest for floor_log2 if __name__ == "__main__": import doctest + doctest.testmod() if __name__ == "__main__": import doctest + doctest.testmod() From bb257cb5d277999ec75eaa017beded5729b55cf8 Mon Sep 17 00:00:00 2001 From: Dhruv Agarwal <92450489+Dhruv127@users.noreply.github.com> Date: Sun, 1 Oct 2023 20:30:29 +0530 Subject: [PATCH 31/32] Update fibonacci_heap.py --- data_structures/heap/fibonacci_heap.py | 28 ++++++++++++++------------ 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index 44c1c94c5a68..bcb9f2d79e8a 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -15,10 +15,10 @@ class FibonacciTree: def __init__(self, key: int) -> None: self.key = key - self.children: list["FibonacciTree"] = [] + self.children: list['FibonacciTree'] = [] self.order = 0 - def add_at_end(self, child_node: "FibonacciTree") -> None: + def add_at_end(self, child_node: 'FibonacciTree') -> None: """ Adds a child node 'child_node' to the end of the children list. @@ -53,8 +53,8 @@ class FibonacciHeap: """ def __init__(self) -> None: - self.trees: list["FibonacciTree"] = [] - self.least: "FibonacciTree" | None = None + self.trees: list['FibonacciTree'] = [] + self.least = None self.count = 0 def insert(self, key: int) -> None: @@ -66,7 +66,7 @@ def insert(self, key: int) -> None: """ new_tree = FibonacciTree(key) self.trees.append(new_tree) - if self.least is None or key < self.least.key: + if (self.least is None or key < self.least.key): self.least = new_tree self.count = self.count + 1 @@ -88,7 +88,8 @@ def extract_min(self) -> int | None: Returns: int: The minimum key. """ - if (smallest := self.least) is not None: + smallest = self.least + if smallest is not None: for child in smallest.children: if child is not None: self.trees.append(child) @@ -106,7 +107,8 @@ def consolidate(self) -> None: """ Consolidates trees in the Fibonacci heap to maintain the heap's structure. """ - aux = (floor_log2(self.count) + 1) * [None] + max_degree = floor_log2(self.count) + 1 # Maximum possible degree + aux = [None] * max_degree # Filter out None values from self.trees valid_trees = [tree for tree in self.trees if tree is not None] @@ -117,7 +119,7 @@ def consolidate(self) -> None: valid_trees.remove(x) while aux[order] is not None: y = aux[order] - if x.key > y.key: + if x.key > y.key : x, y = y, x x.add_at_end(y) aux[order] = None @@ -128,9 +130,12 @@ def consolidate(self) -> None: for k in aux: if k is not None: self.trees.append(k) - if self.least is None or k.key < self.least.key: + if (self.least is None): self.least = k - + continue + if(self.least.key > k.key): + self.least=k + continue def floor_log2(x: int) -> int: """ @@ -144,14 +149,11 @@ def floor_log2(x: int) -> int: """ return math.floor(math.log2(x)) if x > 0 else 0 - # Doctest for floor_log2 if __name__ == "__main__": import doctest - doctest.testmod() if __name__ == "__main__": import doctest - doctest.testmod() From 160f525f4638d228b55b18f78d5ccb1212899aa6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 15:01:38 +0000 Subject: [PATCH 32/32] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/heap/fibonacci_heap.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index bcb9f2d79e8a..1cecf3b88b68 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -15,10 +15,10 @@ class FibonacciTree: def __init__(self, key: int) -> None: self.key = key - self.children: list['FibonacciTree'] = [] + self.children: list["FibonacciTree"] = [] self.order = 0 - def add_at_end(self, child_node: 'FibonacciTree') -> None: + def add_at_end(self, child_node: "FibonacciTree") -> None: """ Adds a child node 'child_node' to the end of the children list. @@ -53,7 +53,7 @@ class FibonacciHeap: """ def __init__(self) -> None: - self.trees: list['FibonacciTree'] = [] + self.trees: list["FibonacciTree"] = [] self.least = None self.count = 0 @@ -66,7 +66,7 @@ def insert(self, key: int) -> None: """ new_tree = FibonacciTree(key) self.trees.append(new_tree) - if (self.least is None or key < self.least.key): + if self.least is None or key < self.least.key: self.least = new_tree self.count = self.count + 1 @@ -88,8 +88,7 @@ def extract_min(self) -> int | None: Returns: int: The minimum key. """ - smallest = self.least - if smallest is not None: + if (smallest := self.least) is not None: for child in smallest.children: if child is not None: self.trees.append(child) @@ -119,7 +118,7 @@ def consolidate(self) -> None: valid_trees.remove(x) while aux[order] is not None: y = aux[order] - if x.key > y.key : + if x.key > y.key: x, y = y, x x.add_at_end(y) aux[order] = None @@ -130,13 +129,14 @@ def consolidate(self) -> None: for k in aux: if k is not None: self.trees.append(k) - if (self.least is None): + if self.least is None: self.least = k continue - if(self.least.key > k.key): - self.least=k + if self.least.key > k.key: + self.least = k continue + def floor_log2(x: int) -> int: """ Computes the floor of the base-2 logarithm of 'x'. @@ -149,11 +149,14 @@ def floor_log2(x: int) -> int: """ return math.floor(math.log2(x)) if x > 0 else 0 + # Doctest for floor_log2 if __name__ == "__main__": import doctest + doctest.testmod() if __name__ == "__main__": import doctest + doctest.testmod()