Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Completing last part of DataStructure task with RB-Tree model #8

Merged
merged 2 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.10' # Specify the version of Python you want to use
python-version: '3.10'

- name: Install dependencies
run: |
Expand Down
6 changes: 4 additions & 2 deletions .idea/etu_algo_labs.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ For a visual demonstration of the algorithm, check out the following video: [Shu
The core implementation is contained within the `Solution` class. Here’s a brief overview of the code:

```python
from algo.Queue import Queue
from algo.Stack import Stack
from src.algo import Queue
from src.algo import Stack


class Solution:
def __init__(self):
Expand All @@ -61,7 +62,7 @@ class Solution:
self.__stack.pop()
else:
while self.__stack and self.get_priority(
self.__stack.top.data
self.__stack.top.data
) >= self.get_priority(elem):
self.__queue.push(self.__stack.pop())
self.__stack.push(elem)
Expand Down
15 changes: 15 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[tool.black]
line-length = 79
target-version = ['py37']
include = '\.pyi?$'
exclude = '''
/(
.git
| __pycache__
| docs/source/conf.py
| old
| build
| dist
| .venv
)/
'''
8 changes: 8 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from setuptools import find_packages, setup

setup(
name="algo_labs",
version="0.1.0",
packages=find_packages(where="src"),
package_dir={"": "src"},
)
File renamed without changes.
8 changes: 4 additions & 4 deletions Shunting Yard/solution.py → src/ShuntingYard/solution.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from algo.LineCheck import is_valid
from algo.Queue import Queue
from algo.Stack import Stack
from src.algo.line_check import validate_brackets
from src.algo.queue import Queue
from src.algo.stack import Stack


class Solution:
Expand All @@ -13,7 +13,7 @@ def get_priority(elem):
return {"+": 0, "-": 0, "*": 1, "/": 1, "^": 2}.get(elem, -1)

def infix_to_postfix(self, line: str):
assert is_valid(line)
assert validate_brackets(line)
for elem in line.split():
if elem.isnumeric():
self.__queue.push(elem)
Expand Down
Empty file added src/algo/__init__.py
Empty file.
4 changes: 2 additions & 2 deletions algo/LineCheck.py → src/algo/line_check.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from .Stack import Stack
from src.algo.stack import Stack


def is_valid(bracket_sequence):
def validate_brackets(bracket_sequence):
stack = Stack()
brackets_dict = {
"[": "]",
Expand Down
File renamed without changes.
File renamed without changes.
Empty file added src/timsort/__init__.py
Empty file.
25 changes: 13 additions & 12 deletions timsort/solution.py → src/timsort/solution.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
from algo.Stack import Stack
from src.algo.stack import Stack


def calculate_minrun(n):
def calculate_min_run(n):
count = 0
while n >= 64:
count |= n & 1
n >>= 1
return n + count


def insertion_sort(arr, left, right):
def insertion_sort(arr, left: list, right):
for i in range(left + 1, right + 1):
key_item = arr[i]
j = i - 1
Expand Down Expand Up @@ -50,15 +50,16 @@ def merge(arr, start, mid, end):

if count >= gallop_trigger:
if left[i] <= right[j]:
idx = binary_search(right, left[i], j)
arr[start + k : start + k + idx - j] = right[j:idx]
k += idx - j
j = idx
index = binary_search(right, left[i], j)
arr[start + k : start + k + index - j] = right[j:index]
k += index - j
j = index
else:
idx = binary_search(left, right[j], i)
arr[start + k : start + k + idx - i] = left[i:idx]
k += idx - i
i = idx
index = binary_search(left, right[j], i)
arr[start + k : start + k + index - i] = left[i:index]
k += index - i
i = index

while i < len(left):
arr[start + k] = left[i]
i += 1
Expand Down Expand Up @@ -99,7 +100,7 @@ def find_runs(arr, minrun):

def timsort(arr):
n = len(arr)
minrun = calculate_minrun(n)
minrun = calculate_min_run(n)
runs = find_runs(arr, minrun)

stack = Stack()
Expand Down
Empty file added src/tree/__init__.py
Empty file.
38 changes: 38 additions & 0 deletions src/tree/binary_tree.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from .traversal import TraversalStrategy


class BinaryTree:
def __init__(self, root=None):
self.root = root

def traverse(self, strategy: TraversalStrategy):
return strategy.traverse(self.root)

def delete(self, value):
self.root = self._delete_rec(self.root, value)

def _delete_rec(self, node, value):
if node is None:
return None
if value < node.get_value():
node.set_left(self._delete_rec(node.get_left(), value))
elif value > node.get_value():
node.set_right(self._delete_rec(node.get_right(), value))
else:
if node.get_left() is None:
return node.get_right()
elif node.get_right() is None:
return node.get_left()
temp = self._min_value_node(node.get_right())
node.set_value(temp.get_value())
node.set_right(
self._delete_rec(node.get_right(), temp.get_value())
)
return node

@staticmethod
def _min_value_node(node):
current = node
while current.get_left() is not None:
current = current.get_left()
return current
63 changes: 63 additions & 0 deletions src/tree/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from src.tree.binary_tree import BinaryTree
from src.tree.parser import TreeParser
from src.tree.red_black_tree import RedBlackTree
from src.tree.traversal import (
BreadthFirstTraversal,
InOrderTraversal,
PostOrderTraversal,
PreOrderTraversal,
)


def read_tree_from_file(file_name):
with open(file_name, "r") as file:
tree_string = file.read().strip()
parser = TreeParser(tree_string)
root = parser.parse()
return root


def build_red_black_tree(bin_root):
tree = RedBlackTree()

def insert_node(node):
if node:
try:
value = int(node.get_value())
except ValueError:
value = node.get_value()
tree.insert(value)
insert_node(node.get_left())
insert_node(node.get_right())

insert_node(bin_root)
return tree


def demonstrate_traversals(tree):
strategies = {
"Обход в ширину": BreadthFirstTraversal(),
"Обход в глубину (прямой)": PreOrderTraversal(),
"Обход в глубину (симметричный)": InOrderTraversal(),
"Обход в глубину (обратный)": PostOrderTraversal(),
}

for name, strategy in strategies.items():
result = tree.traverse(strategy)
print(f"{name}: {' '.join(map(str, result))}")


if __name__ == "__main__":
filename = "tree.txt"
binary_root = read_tree_from_file(filename)
if not binary_root:
print("Не удалось построить дерево.")
exit(1)
binary_tree = BinaryTree(binary_root)
print("Построено двоичное дерево.")
demonstrate_traversals(binary_tree)

print("\nПостроение красно-черного дерева из двоичного дерева...")
rb_tree = build_red_black_tree(binary_root)
print("Вывод узлов красно-черного дерева:")
demonstrate_traversals(rb_tree)
52 changes: 52 additions & 0 deletions src/tree/nodes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from abc import ABC, abstractmethod


class TreeNode(ABC):
@abstractmethod
def get_value(self):
pass

@abstractmethod
def set_value(self, value):
pass

@abstractmethod
def get_left(self):
pass

@abstractmethod
def get_right(self):
pass

@abstractmethod
def set_left(self, node):
pass

@abstractmethod
def set_right(self, node):
pass


class BinaryTreeNode(TreeNode):
def __init__(self, value):
self._value = value
self._left = None
self._right = None

def get_value(self):
return self._value

def set_value(self, value):
self._value = value

def get_left(self):
return self._left

def get_right(self):
return self._right

def set_left(self, node):
self._left = node

def set_right(self, node):
self._right = node
34 changes: 34 additions & 0 deletions src/tree/parser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from .nodes import BinaryTreeNode


class TreeParser:
def __init__(self, line):
self.tokens = line.replace("(", " ( ").replace(")", " ) ").split()
self.index = 0

def parse(self):
if self.index >= len(self.tokens):
return None

token = self.tokens[self.index]
if token == "(":
self.index += 1
if self.index >= len(self.tokens):
raise Exception("Ожидалось значение после '('")
value = self.tokens[self.index]
self.index += 1
node = BinaryTreeNode(value)
node.set_left(self.parse())
node.set_right(self.parse())
if (
self.index >= len(self.tokens)
or self.tokens[self.index] != ")"
):
raise Exception("Ожидалась ')'")
self.index += 1
return node
elif token == ")":
return None
else:
self.index += 1
return BinaryTreeNode(token)
Loading
Loading