|
1 | 1 | import random |
2 | | -import math |
3 | 2 | from collections import deque as Queue |
4 | 3 | from pydatastructs.utils import TreeNode, CartesianTreeNode, RedBlackTreeNode |
5 | 4 | from pydatastructs.miscellaneous_data_structures import Stack |
|
19 | 18 | 'Treap', |
20 | 19 | 'SplayTree', |
21 | 20 | 'RedBlackTree', |
22 | | - 'FusionTree', |
23 | 21 | ] |
24 | 22 |
|
25 | 23 | class BinaryTree(object): |
@@ -1889,160 +1887,3 @@ def get_sum(self, left_index, right_index): |
1889 | 1887 | self.get_prefix_sum(left_index - 1) |
1890 | 1888 | else: |
1891 | 1889 | return self.get_prefix_sum(right_index) |
1892 | | - |
1893 | | -class FusionTree(object): |
1894 | | - """ |
1895 | | - Implements a Fusion Tree, a multi-way search tree optimized for integer keys. |
1896 | | -
|
1897 | | - Parameters |
1898 | | - ========== |
1899 | | -
|
1900 | | - key: int |
1901 | | - The integer key to insert. |
1902 | | - root_data: Any |
1903 | | - Optional data to store with the key. |
1904 | | - backend: pydatastructs.Backend |
1905 | | - The backend to be used. Available backends: Python and C++ |
1906 | | - Optional, by default, the Python backend is used. For faster execution, use the C++ backend. |
1907 | | - word_size: int |
1908 | | - The size of the integer keys in bits. |
1909 | | - Optional, by default, set to 64. |
1910 | | -
|
1911 | | - Examples |
1912 | | - ======== |
1913 | | -
|
1914 | | - >>> from pydatastructs import FusionTree |
1915 | | - >>> ft = FusionTree() |
1916 | | - >>> ft.insert(1, 1) |
1917 | | - >>> ft.insert(2, 2) |
1918 | | - >>> ft.search(1) |
1919 | | - 0 |
1920 | | - >>> ft.delete(1) |
1921 | | - True |
1922 | | - >>> ft.search(1) |
1923 | | -
|
1924 | | -
|
1925 | | - References: |
1926 | | - - https://en.wikipedia.org/wiki/Fusion_tree |
1927 | | - - Fredman & Willard (1990): "Fusion Trees" |
1928 | | - """ |
1929 | | - |
1930 | | - __slots__ = ['root_idx', 'tree', 'size', 'B', |
1931 | | - 'sketch_mask', 'fingerprint_multiplier'] |
1932 | | - |
1933 | | - def __new__(cls, key=None, root_data=None, **kwargs): |
1934 | | - backend = kwargs.get('backend', Backend.PYTHON) |
1935 | | - raise_if_backend_is_not_python(cls, backend) |
1936 | | - |
1937 | | - obj = object.__new__(cls) |
1938 | | - key = None if root_data is None else key |
1939 | | - root = TreeNode(key, root_data) |
1940 | | - root.is_root = True |
1941 | | - obj.root_idx = 0 |
1942 | | - obj.tree, obj.size = ArrayForTrees(TreeNode, [root]), 1 |
1943 | | - obj.B = int(math.log2(kwargs.get('word_size', 64)) |
1944 | | - ** (1/5)) # Multi-way branching factor |
1945 | | - obj.sketch_mask = 0 # Computed dynamically |
1946 | | - obj.fingerprint_multiplier = 2654435761 # Prime multiplier for fingerprinting |
1947 | | - return obj |
1948 | | - |
1949 | | - def _compute_sketch_mask(self): |
1950 | | - """ |
1951 | | - Computes a sketch mask for efficient parallel comparisons. |
1952 | | - """ |
1953 | | - keys = [node.key for node in self.tree if node is not None] |
1954 | | - if len(keys) > 1: |
1955 | | - significant_bits = [max(k.bit_length() for k in keys)] |
1956 | | - self.sketch_mask = sum(1 << b for b in significant_bits) |
1957 | | - |
1958 | | - def insert(self, key, data=None): |
1959 | | - """ |
1960 | | - Inserts a key into the Fusion Tree. |
1961 | | -
|
1962 | | - Parameters |
1963 | | - ========== |
1964 | | -
|
1965 | | - key: int |
1966 | | - The integer key to insert. |
1967 | | - data: Any |
1968 | | - Optional data to store with the key. |
1969 | | - """ |
1970 | | - # Edge case for root node if not intially inserted |
1971 | | - if self.size == 1 and self.tree[0].key is None: |
1972 | | - self.tree[0] = TreeNode(key, data) |
1973 | | - self.tree[0].is_root = True |
1974 | | - return |
1975 | | - |
1976 | | - node = TreeNode(key, data) |
1977 | | - self.tree.append(node) |
1978 | | - self.size += 1 |
1979 | | - if self.size > 1: |
1980 | | - self._compute_sketch_mask() |
1981 | | - |
1982 | | - def _sketch_key(self, key): |
1983 | | - """ |
1984 | | - Applies the sketch mask to compress the key for fast comparison. |
1985 | | - """ |
1986 | | - return key & self.sketch_mask |
1987 | | - |
1988 | | - def _fingerprint(self, key): |
1989 | | - """ |
1990 | | - Uses multiplication-based fingerprinting to create a unique identifier |
1991 | | - for the key, allowing fast parallel searches. |
1992 | | - """ |
1993 | | - return (key * self.fingerprint_multiplier) & ((1 << 64) - 1) |
1994 | | - |
1995 | | - def search(self, key): |
1996 | | - """ |
1997 | | - Searches for a key in the Fusion Tree using bitwise sketching and fingerprinting. |
1998 | | -
|
1999 | | - Parameters |
2000 | | - ========== |
2001 | | -
|
2002 | | - key: int |
2003 | | - The integer key to search. |
2004 | | -
|
2005 | | - Returns |
2006 | | - ======= |
2007 | | -
|
2008 | | - int: The index of the key in the tree, or None if not found. |
2009 | | - """ |
2010 | | - sketch = self._sketch_key(key) |
2011 | | - fingerprint = self._fingerprint(key) |
2012 | | - for i in range(self.size): |
2013 | | - if self._sketch_key(self.tree[i].key) == sketch and self._fingerprint(self.tree[i].key) == fingerprint: |
2014 | | - return i |
2015 | | - return None |
2016 | | - |
2017 | | - def delete(self, key): |
2018 | | - """ |
2019 | | - Deletes a key from the Fusion Tree. |
2020 | | -
|
2021 | | - Parameters |
2022 | | - ========== |
2023 | | -
|
2024 | | - key: int |
2025 | | - The integer key to delete. |
2026 | | -
|
2027 | | - Returns |
2028 | | - ======= |
2029 | | -
|
2030 | | - bool: True if the key was successfully deleted, False otherwise. |
2031 | | -
|
2032 | | - """ |
2033 | | - index = self.search(key) |
2034 | | - if index is not None: |
2035 | | - self.tree[index] = None # Soft delete |
2036 | | - # Compact tree |
2037 | | - self.tree = [node for node in self.tree if node is not None] |
2038 | | - self.size -= 1 |
2039 | | - if self.size > 1: |
2040 | | - self._compute_sketch_mask() |
2041 | | - return True |
2042 | | - return False |
2043 | | - |
2044 | | - def __str__(self): |
2045 | | - """ |
2046 | | - Returns a string representation of the Fusion Tree. |
2047 | | - """ |
2048 | | - return str([(node.key, node.data) for node in self.tree if node is not None]) |
0 commit comments