Skip to content

Commit

Permalink
Merge pull request #8 from m4tveevm/dev
Browse files Browse the repository at this point in the history
Completing last part of DataStructure task with RB-Tree model
  • Loading branch information
m4tveevm authored Dec 3, 2024
2 parents a3f74d2 + 8eea896 commit b1242a7
Show file tree
Hide file tree
Showing 28 changed files with 863 additions and 37 deletions.
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

0 comments on commit b1242a7

Please sign in to comment.