forked from UNN/2026-rff_mp
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bc6ece83d0 | |||
| b9c4421127 | |||
| 4a214a2843 | |||
| 1b21f97e28 | |||
| 7e045c71e0 | |||
| 9b92dcc206 | |||
| d616bfe1fb | |||
| 14e6c71416 | |||
| 0e7a03e784 | |||
| b638d6c169 | |||
| 62e1b34fd0 | |||
| 10f35b3ac3 | |||
| d9d935c0bf | |||
| c9947a713f | |||
| 10445d4940 | |||
| 5e85fa060b | |||
| 7fec6872a1 |
94
.gitignore → stepushovgs/.gitignore
vendored
94
.gitignore → stepushovgs/.gitignore
vendored
|
|
@ -160,3 +160,97 @@ cython_debug/
|
||||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
#.idea/
|
#.idea/
|
||||||
|
|
||||||
|
# Prerequisites
|
||||||
|
*.d
|
||||||
|
|
||||||
|
# Object files
|
||||||
|
*.o
|
||||||
|
*.ko
|
||||||
|
*.obj
|
||||||
|
*.elf
|
||||||
|
|
||||||
|
# Linker output
|
||||||
|
*.ilk
|
||||||
|
*.map
|
||||||
|
*.exp
|
||||||
|
|
||||||
|
# Precompiled Headers
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
|
||||||
|
# Libraries
|
||||||
|
*.lib
|
||||||
|
*.a
|
||||||
|
*.la
|
||||||
|
*.lo
|
||||||
|
|
||||||
|
# Shared objects (inc. Windows DLLs)
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.so.*
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
*.exe
|
||||||
|
*.out
|
||||||
|
*.app
|
||||||
|
*.i*86
|
||||||
|
*.x86_64
|
||||||
|
*.hex
|
||||||
|
|
||||||
|
# Debug files
|
||||||
|
*.dSYM/
|
||||||
|
*.su
|
||||||
|
*.idb
|
||||||
|
*.pdb
|
||||||
|
|
||||||
|
# Kernel Module Compile Results
|
||||||
|
*.mod*
|
||||||
|
*.cmd
|
||||||
|
.tmp_versions/
|
||||||
|
modules.order
|
||||||
|
Module.symvers
|
||||||
|
Mkfile.old
|
||||||
|
dkms.conf
|
||||||
|
|
||||||
|
# debug information files
|
||||||
|
*.dwo
|
||||||
|
|
||||||
|
#################################
|
||||||
|
############## Go ###############
|
||||||
|
#################################
|
||||||
|
|
||||||
|
# If you prefer the allow list template instead of the deny list, see community template:
|
||||||
|
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
|
||||||
|
#
|
||||||
|
# Binaries for programs and plugins
|
||||||
|
*.exe
|
||||||
|
*.exe~
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Test binary, built with `go test -c`
|
||||||
|
*.test
|
||||||
|
|
||||||
|
# Code coverage profiles and other test artifacts
|
||||||
|
*.out
|
||||||
|
coverage.*
|
||||||
|
*.coverprofile
|
||||||
|
profile.cov
|
||||||
|
|
||||||
|
# Dependency directories (remove the comment below to include it)
|
||||||
|
# vendor/
|
||||||
|
|
||||||
|
# Go workspace file
|
||||||
|
go.work
|
||||||
|
go.work.sum
|
||||||
|
|
||||||
|
# env file
|
||||||
|
.env
|
||||||
|
|
||||||
|
# Editor/IDE
|
||||||
|
# .idea/
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
!go.mod
|
||||||
1
stepushovgs/427
Normal file
1
stepushovgs/427
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
427
|
||||||
208
stepushovgs/data-structures/source/bin_search_tree_C/bst.c
Normal file
208
stepushovgs/data-structures/source/bin_search_tree_C/bst.c
Normal file
|
|
@ -0,0 +1,208 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "bst.h"
|
||||||
|
#include "queue.h"
|
||||||
|
/*
|
||||||
|
3. Двоичное дерево поиска
|
||||||
|
Узел — словарь: `{'val': '123', 'left': None, 'right': None}.`
|
||||||
|
|
||||||
|
Функции:
|
||||||
|
|
||||||
|
def bst_insert(root, name, phone) — рекурсивно или итеративно вставляет, возвращает новый корень (если корень меняется).
|
||||||
|
|
||||||
|
def bst_find(root, name) — поиск.
|
||||||
|
|
||||||
|
def bst_delete(root, name) — удаление, возвращает новый корень.
|
||||||
|
|
||||||
|
def bst_list_all(root) — центрированный обход (рекурсивно собирает записи в отсортированном порядке).
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bst_node* create_bst_node(char name[NAME_LEN], char phone[PHONE_LEN])
|
||||||
|
{
|
||||||
|
bst_node* node = (bst_node*)malloc(sizeof(bst_node));
|
||||||
|
|
||||||
|
strcpy(node->name, name);
|
||||||
|
strcpy(node->phone, phone);
|
||||||
|
|
||||||
|
node->left = NULL;
|
||||||
|
node->right = NULL;
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
bst_node* bst_minimum(bst_node* node)
|
||||||
|
{
|
||||||
|
if (node->left == NULL)
|
||||||
|
return node;
|
||||||
|
return bst_minimum(node->left);
|
||||||
|
}
|
||||||
|
|
||||||
|
bst_node* bst_maximum(bst_node* node)
|
||||||
|
{
|
||||||
|
if (node->right == NULL)
|
||||||
|
return node;
|
||||||
|
return bst_maximum(node->right);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_bst(bst_node node)
|
||||||
|
{
|
||||||
|
//printf("value: %d\n", node.value);
|
||||||
|
|
||||||
|
printf("name: %s, phone: %s\n", node.name, node.phone);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bst_inorder_traversal(bst_node* HEAD)
|
||||||
|
{
|
||||||
|
if (HEAD != NULL)
|
||||||
|
{
|
||||||
|
bst_inorder_traversal(HEAD->left);
|
||||||
|
print_bst(*HEAD);
|
||||||
|
bst_inorder_traversal(HEAD->right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bst_preorder_traversal(bst_node* HEAD)
|
||||||
|
{
|
||||||
|
if (HEAD != NULL)
|
||||||
|
{
|
||||||
|
print_bst(*HEAD);
|
||||||
|
bst_preorder_traversal(HEAD->left);
|
||||||
|
bst_preorder_traversal(HEAD->right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bst_node* bst_search(bst_node* HEAD, char target_name[NAME_LEN])
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Node search(x : Node, k : T):
|
||||||
|
if x == null or k == x.key
|
||||||
|
return x
|
||||||
|
if k < x.key
|
||||||
|
return search(x.left, k)
|
||||||
|
else
|
||||||
|
return search(x.right, k)
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((HEAD == NULL) || strcmp(HEAD->name, target_name) == 0)
|
||||||
|
{
|
||||||
|
return HEAD;
|
||||||
|
}
|
||||||
|
if (strcmp(target_name, HEAD->name) < 0)
|
||||||
|
{
|
||||||
|
return bst_search(HEAD->left, target_name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return bst_search(HEAD->right, target_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bst_node* bst_insert(bst_node* HEAD, char name[NAME_LEN], char phone[PHONE_LEN])
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Node insert(x : Node, z : T): // x — корень поддерева, z — вставляемый ключ
|
||||||
|
if x == null
|
||||||
|
return Node(z) // подвесим Node с key = z
|
||||||
|
else if z < x.key
|
||||||
|
x.left = insert(x.left, z)
|
||||||
|
else if z > x.key
|
||||||
|
x.right = insert(x.right, z)
|
||||||
|
return x
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (HEAD == NULL)
|
||||||
|
{
|
||||||
|
return create_bst_node(name, phone);
|
||||||
|
}
|
||||||
|
else if (strcmp(name, HEAD->name) < 0)
|
||||||
|
{
|
||||||
|
HEAD->left = bst_insert(HEAD->left, name, phone);
|
||||||
|
}
|
||||||
|
else if (strcmp(name, HEAD->name) > 0)
|
||||||
|
{
|
||||||
|
HEAD->right = bst_insert(HEAD->right, name, phone);
|
||||||
|
}
|
||||||
|
return HEAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
bst_node* bst_delete(bst_node* root, char target_name[NAME_LEN])
|
||||||
|
{ // корень поддерева, удаляемый ключ
|
||||||
|
if (root == NULL)
|
||||||
|
return root;
|
||||||
|
|
||||||
|
if (strcmp(target_name, root->name) < 0)
|
||||||
|
root->left = bst_delete(root->left, target_name);
|
||||||
|
else if (strcmp(target_name, root->name) > 0)
|
||||||
|
root->right = bst_delete(root->right, target_name);
|
||||||
|
else {
|
||||||
|
if (root->left != NULL && root->right != NULL)
|
||||||
|
{
|
||||||
|
strcpy(root->name, bst_minimum(root->right)->name);
|
||||||
|
strcpy(root->phone, bst_minimum(root->right)->phone);
|
||||||
|
|
||||||
|
root->right = bst_delete(root->right, root->name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bst_node* temp = root;
|
||||||
|
if (root->left != NULL)
|
||||||
|
root = root->left;
|
||||||
|
else
|
||||||
|
root = root->right;
|
||||||
|
free(temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
void delete_bst(bst_node* root)
|
||||||
|
{
|
||||||
|
if (root == NULL)
|
||||||
|
return;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delete_bst(root->left);
|
||||||
|
delete_bst(root->right);
|
||||||
|
free(root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printTree(bst_node* node, int depth) {
|
||||||
|
|
||||||
|
if (node == NULL) return;
|
||||||
|
|
||||||
|
printTree(node->right, depth + 1);
|
||||||
|
|
||||||
|
for (int i = 0; i < depth; i++)
|
||||||
|
printf("\t");
|
||||||
|
//printf("%d\n", node->value);
|
||||||
|
print_bst(*node);
|
||||||
|
|
||||||
|
printTree(node->left, depth + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void treeLevelTraversal(bst_node* node) {
|
||||||
|
if (!node) return;
|
||||||
|
|
||||||
|
Queue q;
|
||||||
|
Queue* hq = &q;
|
||||||
|
queueInit(hq);
|
||||||
|
|
||||||
|
queuePush(hq, node);
|
||||||
|
while(!queueEmpty(hq))
|
||||||
|
{
|
||||||
|
bst_node* hn = queuePop(hq);
|
||||||
|
//printf("%d\n", hn->value);
|
||||||
|
print_bst(*hn);
|
||||||
|
|
||||||
|
if(hn->left)
|
||||||
|
queuePush(hq, hn->left);
|
||||||
|
if(hn->right)
|
||||||
|
queuePush(hq, hn->right);
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
37
stepushovgs/data-structures/source/bin_search_tree_C/bst.h
Normal file
37
stepushovgs/data-structures/source/bin_search_tree_C/bst.h
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
#define NAME_LEN 20
|
||||||
|
#define PHONE_LEN 20
|
||||||
|
|
||||||
|
typedef struct bst_node
|
||||||
|
{
|
||||||
|
//int value;
|
||||||
|
|
||||||
|
char name[NAME_LEN];
|
||||||
|
char phone[PHONE_LEN];
|
||||||
|
|
||||||
|
struct bst_node* right;
|
||||||
|
struct bst_node* left;
|
||||||
|
}bst_node;
|
||||||
|
|
||||||
|
bst_node* create_bst_node(char name[NAME_LEN], char phone[PHONE_LEN]);
|
||||||
|
|
||||||
|
bst_node* bst_minimum(bst_node* node);
|
||||||
|
|
||||||
|
bst_node* bst_maximum(bst_node* node);
|
||||||
|
|
||||||
|
void print_bst(bst_node node);
|
||||||
|
|
||||||
|
void bst_inorder_traversal(bst_node* HEAD);
|
||||||
|
|
||||||
|
void bst_preorder_traversal(bst_node* HEAD);
|
||||||
|
|
||||||
|
bst_node* bst_search(bst_node* HEAD, char target_name[NAME_LEN]);
|
||||||
|
|
||||||
|
bst_node* bst_insert(bst_node* HEAD, char name[NAME_LEN], char phone[PHONE_LEN]);
|
||||||
|
|
||||||
|
bst_node* bst_delete(bst_node* root, char target_name[NAME_LEN]);
|
||||||
|
|
||||||
|
void treeLevelTraversal(bst_node* node);
|
||||||
|
|
||||||
|
void printTree(bst_node* node, int depth);
|
||||||
|
|
||||||
|
void delete_bst(bst_node* root);
|
||||||
42
stepushovgs/data-structures/source/bin_search_tree_C/queue.c
Normal file
42
stepushovgs/data-structures/source/bin_search_tree_C/queue.c
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "queue.h"
|
||||||
|
|
||||||
|
int queueEmpty(Queue* q)
|
||||||
|
{
|
||||||
|
return (q->head == q->tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
int size(Queue* q)
|
||||||
|
{
|
||||||
|
if (q->head > q->tail)
|
||||||
|
return QUEUE_MAX_LENGTH - q->head + q->tail;
|
||||||
|
else
|
||||||
|
return q->tail - q->head;
|
||||||
|
}
|
||||||
|
|
||||||
|
void queuePush(Queue* q, void* ptr)
|
||||||
|
{
|
||||||
|
if (size(q) != QUEUE_MAX_LENGTH)
|
||||||
|
{
|
||||||
|
q->p[q->tail] = ptr;
|
||||||
|
q->tail = (q->tail + 1) % QUEUE_MAX_LENGTH;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void queueInit(Queue* q)
|
||||||
|
{
|
||||||
|
q->head = 0;
|
||||||
|
q->tail = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* queuePop(Queue* q)
|
||||||
|
{
|
||||||
|
if (queueEmpty(q))
|
||||||
|
return NULL;
|
||||||
|
void* x = q->p[q->head];
|
||||||
|
q->head = (q->head + 1) % QUEUE_MAX_LENGTH;
|
||||||
|
|
||||||
|
return x;
|
||||||
|
};
|
||||||
|
|
||||||
17
stepushovgs/data-structures/source/bin_search_tree_C/queue.h
Normal file
17
stepushovgs/data-structures/source/bin_search_tree_C/queue.h
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#define QUEUE_MAX_LENGTH 100
|
||||||
|
|
||||||
|
typedef struct Queue {
|
||||||
|
void* p[QUEUE_MAX_LENGTH];
|
||||||
|
unsigned int head;
|
||||||
|
unsigned int tail;
|
||||||
|
} Queue;
|
||||||
|
|
||||||
|
int queueEmpty(Queue* q);
|
||||||
|
|
||||||
|
void queuePush(Queue* q, void* p);
|
||||||
|
|
||||||
|
void* queuePop(Queue* q);
|
||||||
|
|
||||||
|
void queueInit(Queue* q);
|
||||||
|
|
||||||
|
int size(Queue* q);
|
||||||
3
stepushovgs/data-structures/source/go.mod
Normal file
3
stepushovgs/data-structures/source/go.mod
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
module source
|
||||||
|
|
||||||
|
go 1.26.3
|
||||||
166
stepushovgs/data-structures/source/linked_list_c/linked_list.c
Normal file
166
stepushovgs/data-structures/source/linked_list_c/linked_list.c
Normal file
|
|
@ -0,0 +1,166 @@
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "linked_list.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
Связный список (LinkedListPhoneBook)
|
||||||
|
|
||||||
|
Узел представляется словарём: `{'name': 'Имя', 'phone': '123', 'next': None}.`
|
||||||
|
|
||||||
|
Функции:
|
||||||
|
|
||||||
|
def ll_insert(head, name, phone) — проходит до конца (или сразу добавляет в конец) и возвращает новую голову (если вставка в начало) или изменяет список по ссылке. Удобнее возвращать новую голову, если вставка может быть в начало.
|
||||||
|
|
||||||
|
def ll_find(head, name) — ищет узел, возвращает телефон или None.
|
||||||
|
|
||||||
|
def ll_delete(head, name) — удаляет узел, возвращает новую голову.
|
||||||
|
|
||||||
|
def ll_list_all(head) — собирает все записи в список и сортирует (сортировка вынесена отдельно).
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
int getListNodeLength(Node* HEAD)
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
Node* current = HEAD;
|
||||||
|
while (current != NULL)
|
||||||
|
{
|
||||||
|
len++;
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Добавление в конец
|
||||||
|
Node* insert(Node* head, char name[NAME_BUFF_SIZE], char phone[PHONE_BUFF_SIZE], int show)
|
||||||
|
{
|
||||||
|
Node* newNode = (Node*)malloc(sizeof(Node));
|
||||||
|
|
||||||
|
strcpy_s(newNode->name_, NAME_BUFF_SIZE, name);
|
||||||
|
strcpy_s(newNode->phone_, PHONE_BUFF_SIZE, phone);
|
||||||
|
newNode->next = NULL;
|
||||||
|
|
||||||
|
printf("Data: %s %s\n", name, phone);
|
||||||
|
printf("New Data: %s %s\n", newNode->name_, newNode->phone_);
|
||||||
|
|
||||||
|
if (head == NULL)
|
||||||
|
{
|
||||||
|
printf("\nNew list\n");
|
||||||
|
head = newNode;
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* last = head;
|
||||||
|
int ind = 0;
|
||||||
|
while (last->next != NULL)
|
||||||
|
{
|
||||||
|
if (show == 1)
|
||||||
|
printf("%d \n", ind++);
|
||||||
|
last = last->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
last->next = newNode;
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* find(Node* HEAD, char target_name[NAME_BUFF_SIZE])
|
||||||
|
{
|
||||||
|
Node* current = HEAD;
|
||||||
|
|
||||||
|
while (current != NULL)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (strcmp(target_name, current->name_) == 0)
|
||||||
|
{
|
||||||
|
return current->phone_;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Вывод всех элементов
|
||||||
|
void printAllNodes(Node* head)
|
||||||
|
{
|
||||||
|
Node* current = head;
|
||||||
|
int ind = 0;
|
||||||
|
|
||||||
|
while (current != NULL)
|
||||||
|
{
|
||||||
|
printf("Ind: %d\nName: %s\nPhone: %s\n", ind++, current->name_, current->phone_);
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* deleteNode(Node* HEAD, char target_name[NAME_BUFF_SIZE])
|
||||||
|
{
|
||||||
|
Node* previous = NULL;
|
||||||
|
Node* current = HEAD;
|
||||||
|
|
||||||
|
if (current != NULL && strcmp(target_name, current->name_) == 0)
|
||||||
|
{
|
||||||
|
HEAD = current->next;
|
||||||
|
free(current);
|
||||||
|
|
||||||
|
return HEAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (current != NULL && strcmp(target_name, current->name_) == 0)
|
||||||
|
{
|
||||||
|
previous = current;
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current == NULL) return HEAD;
|
||||||
|
|
||||||
|
previous->next = current->next;
|
||||||
|
free(current);
|
||||||
|
|
||||||
|
return HEAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* listAll(Node* HEAD)
|
||||||
|
{
|
||||||
|
if (HEAD == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int len = getListNodeLength(HEAD);
|
||||||
|
Node* current = HEAD;
|
||||||
|
|
||||||
|
Node* list = (Node*)malloc(len * sizeof(Node));
|
||||||
|
|
||||||
|
int ind = 0;
|
||||||
|
while (current != NULL)
|
||||||
|
{
|
||||||
|
list[ind++] = *current;
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
void printNode(Node node)
|
||||||
|
{
|
||||||
|
printf("%s ", node.name_);
|
||||||
|
printf("%s\n", node.phone_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void printListNode(Node* list, int length)
|
||||||
|
{
|
||||||
|
printf("\n\n%d\n", length);
|
||||||
|
for (int i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
printNode(list[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
#define NAME_BUFF_SIZE 50
|
||||||
|
#define PHONE_BUFF_SIZE 12+1 // +1 for end symbol
|
||||||
|
|
||||||
|
typedef struct Node
|
||||||
|
{
|
||||||
|
char name_[NAME_BUFF_SIZE];
|
||||||
|
char phone_[PHONE_BUFF_SIZE];
|
||||||
|
struct Node* next;
|
||||||
|
} Node;
|
||||||
|
|
||||||
|
typedef struct LinkedListPhoneNumbers {
|
||||||
|
Node* HEAD;
|
||||||
|
} LinkedListPhoneNumbers;
|
||||||
|
|
||||||
|
Node* insert(Node* head, char name[NAME_BUFF_SIZE], char phone[PHONE_BUFF_SIZE], int show);
|
||||||
|
void printAllNodes(Node* head);
|
||||||
|
void printNode(Node node);
|
||||||
|
|
||||||
|
char* find(Node* HEAD, char target_name[NAME_BUFF_SIZE]);
|
||||||
|
|
||||||
|
|
||||||
|
Node* deleteNode(Node* HEAD, char target_name[NAME_BUFF_SIZE]);
|
||||||
|
|
||||||
|
|
||||||
|
Node* listAll(Node* HEAD);
|
||||||
|
|
||||||
|
void printListNode(Node list[], int length);
|
||||||
|
|
||||||
|
int getListNodeLength(Node* HEAD);
|
||||||
44
stepushovgs/data-structures/source/old_c/main.c
Normal file
44
stepushovgs/data-structures/source/old_c/main.c
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "linked_list/linked_list.h"
|
||||||
|
|
||||||
|
#define NAME_BUFF_SIZE 50
|
||||||
|
#define PHONE_BUFF_SIZE 12+1 // +1 for end symbol
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Node* list = NULL;
|
||||||
|
char phone[] = "1234";
|
||||||
|
for (int i = 0; i < 12; i++)
|
||||||
|
{
|
||||||
|
char num[3];
|
||||||
|
sprintf_s(num, 3, "%d", i);
|
||||||
|
|
||||||
|
char name[] = "name ";
|
||||||
|
strcat_s(name, 9, num);
|
||||||
|
printf("%d %s %s\n", i, name, phone);
|
||||||
|
list = insert(list, name, phone, 0);
|
||||||
|
}
|
||||||
|
char test_name[] = "name 20";
|
||||||
|
char test_phone[] = "phone 343";
|
||||||
|
|
||||||
|
list = insert(list, test_name, test_phone, 1);
|
||||||
|
|
||||||
|
printAllNodes(list);
|
||||||
|
|
||||||
|
printf("\n%s\n", find(list, test_name));
|
||||||
|
|
||||||
|
strcpy_s(test_name, NAME_BUFF_SIZE, "name 10");
|
||||||
|
list = deleteNode(list, test_name);
|
||||||
|
|
||||||
|
printAllNodes(list);
|
||||||
|
|
||||||
|
Node* listNodes = listAll(list);
|
||||||
|
printListNode(listNodes, getListNodeLength(list));
|
||||||
|
|
||||||
|
free(listNodes);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
86
stepushovgs/data-structures/source/old_c/main_tree.c
Normal file
86
stepushovgs/data-structures/source/old_c/main_tree.c
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "bin_search_tree/bst.h"
|
||||||
|
|
||||||
|
#define COUNT_NUMBERS 64
|
||||||
|
|
||||||
|
int isInArr(int arr[], int len, int target)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
if (arr[i] == target) return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char get_dozen(int number)
|
||||||
|
{
|
||||||
|
return (char)'0' + number % 10;
|
||||||
|
}
|
||||||
|
char get_units(int number)
|
||||||
|
{
|
||||||
|
return (char)'0' + number / 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
printf("hello world!\n");
|
||||||
|
|
||||||
|
//bst_node* head = create_bst_node("name", "phone");
|
||||||
|
bst_node* head = NULL;
|
||||||
|
|
||||||
|
int arr[COUNT_NUMBERS] = {0};
|
||||||
|
char name[NAME_LEN] = "name_xx";
|
||||||
|
char phone[PHONE_LEN] = "phone_xx";
|
||||||
|
int temp = 0;
|
||||||
|
for (int i = 0; i < COUNT_NUMBERS; i++)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
temp = rand() % 100;
|
||||||
|
}
|
||||||
|
while (isInArr(arr, i - 1, temp));
|
||||||
|
|
||||||
|
arr[i] = temp;
|
||||||
|
|
||||||
|
name[5] = get_dozen(temp);
|
||||||
|
name[6] = get_units(temp);
|
||||||
|
|
||||||
|
phone[6] = get_dozen(temp);
|
||||||
|
phone[7] = get_units(temp);
|
||||||
|
|
||||||
|
|
||||||
|
head = bst_insert(head, name, phone);
|
||||||
|
printf("%d ", arr[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n\ninorder traversal: \n");
|
||||||
|
bst_inorder_traversal(head);
|
||||||
|
|
||||||
|
printf("\n\npreorder traversal: \n");
|
||||||
|
bst_preorder_traversal(head);
|
||||||
|
|
||||||
|
char tar_name[NAME_LEN] = "name_44";
|
||||||
|
|
||||||
|
printf("\n\nУдаляем элемент с значением %s:\n", tar_name);
|
||||||
|
|
||||||
|
head = bst_delete(head, tar_name);
|
||||||
|
|
||||||
|
bst_inorder_traversal(head);
|
||||||
|
|
||||||
|
|
||||||
|
printf("\n\nВывод дерева:\n");
|
||||||
|
|
||||||
|
printTree(head, 0);
|
||||||
|
|
||||||
|
printf("\n\nОбход в ширину:\n");
|
||||||
|
treeLevelTraversal(head);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
delete_bst(head);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
40
stepushovgs/data-structures/source/old_c/swap.c
Normal file
40
stepushovgs/data-structures/source/old_c/swap.c
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int Partition_Hoa(int arr[], int l, int r)
|
||||||
|
{
|
||||||
|
int p = arr[(l + r) / 2];
|
||||||
|
int i = l;
|
||||||
|
int j = r;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
// #print(p)
|
||||||
|
while (arr[i] <= p) i++;
|
||||||
|
while (arr[j] > p) j--;
|
||||||
|
|
||||||
|
if (i >= j) return j;
|
||||||
|
|
||||||
|
swap(arr[i], arr[j]);
|
||||||
|
i++;
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void QuickSort(int arr[], int l, int r)
|
||||||
|
{
|
||||||
|
if (l < r):
|
||||||
|
{
|
||||||
|
int s = Partition_Hoa(arr, l, r);
|
||||||
|
QuickSort(arr, l, s-1);
|
||||||
|
QuickSort(arr, s+1, r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int arr[] = {2, 56, 10, 5, 2, 6, 9, 6, 3, 923, 3, 2, 1};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
package csvwriter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/csv"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BenchmarkResult struct {
|
||||||
|
Structure string
|
||||||
|
Mode string
|
||||||
|
Operation string
|
||||||
|
Time float64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BenchmarkResult) ToString() string {
|
||||||
|
return fmt.Sprintf("%s %s %s %f", b.Structure, b.Mode, b.Operation, b.Time)
|
||||||
|
}
|
||||||
|
func (b *BenchmarkResult) ToStrings() []string {
|
||||||
|
return []string{b.Structure, b.Mode, b.Operation, fmt.Sprintf("%d", b.Time)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppendRaw дописывает произвольные строки в CSV
|
||||||
|
func AppendRaw(results []BenchmarkResult) error {
|
||||||
|
|
||||||
|
filename := filepath.Join("results", "benchmarks.csv")
|
||||||
|
|
||||||
|
file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
writer := csv.NewWriter(file)
|
||||||
|
defer writer.Flush()
|
||||||
|
|
||||||
|
rows := make([][]string, len(results))
|
||||||
|
|
||||||
|
for i, res := range results {
|
||||||
|
rows[i] = res.ToStrings()
|
||||||
|
}
|
||||||
|
|
||||||
|
return writer.WriteAll(rows) // WriteAll пишет всё сразу
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
package data_struct
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type MyData struct {
|
||||||
|
Name string
|
||||||
|
Phone string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewData(name, phone string) *MyData {
|
||||||
|
return &MyData{
|
||||||
|
Name: name,
|
||||||
|
Phone: phone,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *MyData) ToString() string {
|
||||||
|
return fmt.Sprintf("Имя: %s, Телефон: %s", d.Name, d.Phone)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PrintList(list []MyData) {
|
||||||
|
for _, el := range list {
|
||||||
|
fmt.Printf("%s\n", el.ToString())
|
||||||
|
}
|
||||||
|
}
|
||||||
37
stepushovgs/data-structures/source/pkg/data_struct/qsort.go
Normal file
37
stepushovgs/data-structures/source/pkg/data_struct/qsort.go
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
package data_struct
|
||||||
|
|
||||||
|
func QSort(arr []MyData, l, r int) []MyData {
|
||||||
|
if l < r {
|
||||||
|
s := Partition_Hoa(arr, l, r)
|
||||||
|
arr = QSort(arr, l, s)
|
||||||
|
arr = QSort(arr, s+1, r)
|
||||||
|
}
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
|
||||||
|
func Partition_Hoa(arr []MyData, l, r int) int {
|
||||||
|
p := arr[(l+r)/2].Name
|
||||||
|
i := l - 1
|
||||||
|
j := r + 1
|
||||||
|
|
||||||
|
for {
|
||||||
|
for {
|
||||||
|
i++
|
||||||
|
if arr[i].Name >= p {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
j--
|
||||||
|
if arr[j].Name <= p {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if i >= j {
|
||||||
|
return j
|
||||||
|
}
|
||||||
|
|
||||||
|
arr[i], arr[j] = arr[j], arr[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
package gen_data
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
ds "source/pkg/data_struct"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
MAX_USER_IND = 10000
|
||||||
|
PHONE_LEN = 11
|
||||||
|
)
|
||||||
|
|
||||||
|
func genRandomPhone() string {
|
||||||
|
phone := ""
|
||||||
|
for i := 0; i < PHONE_LEN; i++ {
|
||||||
|
phone += fmt.Sprintf("%d", rand.Intn(10))
|
||||||
|
}
|
||||||
|
|
||||||
|
return phone
|
||||||
|
}
|
||||||
|
|
||||||
|
func RecordsShuffled(count int) []ds.MyData {
|
||||||
|
data := make([]ds.MyData, count)
|
||||||
|
number := 0
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
number = rand.Intn(MAX_USER_IND)
|
||||||
|
data[i].Name = fmt.Sprintf("User_%05d", number)
|
||||||
|
data[i].Phone = genRandomPhone()
|
||||||
|
}
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
func RecordsSorted(count int) []ds.MyData {
|
||||||
|
data := RecordsShuffled(count)
|
||||||
|
|
||||||
|
data = ds.QSort(data, 0, len(data)-1)
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,197 @@
|
||||||
|
package bin_search_tree
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
ds "source/pkg/data_struct"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BinSearchTree struct {
|
||||||
|
data ds.MyData
|
||||||
|
|
||||||
|
left *BinSearchTree
|
||||||
|
right *BinSearchTree
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBinSearchTree(data ds.MyData) *BinSearchTree {
|
||||||
|
return &BinSearchTree{
|
||||||
|
data: data,
|
||||||
|
left: nil,
|
||||||
|
right: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bst *BinSearchTree) Len() int {
|
||||||
|
if bst == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return 1 + bst.left.Len() + bst.right.Len()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bst *BinSearchTree) Minimum() *BinSearchTree {
|
||||||
|
if bst.left == nil {
|
||||||
|
return bst
|
||||||
|
}
|
||||||
|
return bst.left.Minimum()
|
||||||
|
}
|
||||||
|
func (bst *BinSearchTree) Maximum() *BinSearchTree {
|
||||||
|
if bst.right == nil {
|
||||||
|
return bst
|
||||||
|
}
|
||||||
|
return bst.right.Maximum()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (node *BinSearchTree) PrintNode() {
|
||||||
|
fmt.Print(node.data.ToString())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (node *BinSearchTree) ToString() string {
|
||||||
|
if node == nil {
|
||||||
|
return "nil"
|
||||||
|
}
|
||||||
|
return node.data.ToString()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bst *BinSearchTree) BstInorderTraversal() {
|
||||||
|
if bst != nil {
|
||||||
|
bst.left.BstInorderTraversal()
|
||||||
|
bst.PrintNode()
|
||||||
|
fmt.Println()
|
||||||
|
bst.right.BstInorderTraversal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bst *BinSearchTree) BstPreorderTraversal() {
|
||||||
|
if bst != nil {
|
||||||
|
bst.PrintNode()
|
||||||
|
bst.left.BstPreorderTraversal()
|
||||||
|
bst.right.BstPreorderTraversal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search
|
||||||
|
// Возвращает строковое представление узла
|
||||||
|
func (bst *BinSearchTree) Search(targetName string) (string, bool) {
|
||||||
|
node, ok := bst.search(targetName)
|
||||||
|
if ok {
|
||||||
|
return node.ToString(), true
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Node search(x : Node, k : T):
|
||||||
|
if x == null or k == x.key
|
||||||
|
return x
|
||||||
|
if k < x.key
|
||||||
|
return search(x.left, k)
|
||||||
|
else
|
||||||
|
return search(x.right, k)
|
||||||
|
*/
|
||||||
|
// Приватная вспомогательная функция поиска
|
||||||
|
func (node *BinSearchTree) search(targetName string) (*BinSearchTree, bool) {
|
||||||
|
if node == nil {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
if node.data.Name == targetName {
|
||||||
|
return node, true
|
||||||
|
}
|
||||||
|
if targetName < node.data.Name {
|
||||||
|
return node.left.search(targetName)
|
||||||
|
}
|
||||||
|
return node.right.search(targetName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (bst *BinSearchTree) Search(targetName string) (string, bool) {
|
||||||
|
/*
|
||||||
|
Node search(x : Node, k : T):
|
||||||
|
if x == null or k == x.key
|
||||||
|
return x
|
||||||
|
if k < x.key
|
||||||
|
return search(x.left, k)
|
||||||
|
else
|
||||||
|
return search(x.right, k)
|
||||||
|
*/
|
||||||
|
// targetNode, ok := bst.head.search(targetName)
|
||||||
|
|
||||||
|
// return targetNode.ToString(), ok
|
||||||
|
// }
|
||||||
|
|
||||||
|
func (node *BinSearchTree) Insert(data ds.MyData) *BinSearchTree {
|
||||||
|
if node == nil {
|
||||||
|
return NewBinSearchTree(data)
|
||||||
|
} else if data.Name < node.data.Name {
|
||||||
|
node.left = node.left.Insert(data)
|
||||||
|
} else if data.Name > node.data.Name {
|
||||||
|
node.right = node.right.Insert(data)
|
||||||
|
} else {
|
||||||
|
node.data.Phone = data.Phone // Заменяем существующее значение
|
||||||
|
}
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete удаляет узел по имени.
|
||||||
|
// Возвращает нового потомка для родительского узла.
|
||||||
|
|
||||||
|
/*
|
||||||
|
Node delete(root : Node, z : T): // корень поддерева, удаляемый ключ
|
||||||
|
if root == null
|
||||||
|
return root
|
||||||
|
if z < root.key
|
||||||
|
root.left = delete(root.left, z)
|
||||||
|
else if z > root.key
|
||||||
|
root.right = delete(root.right, z)
|
||||||
|
else if root.left != null and root.right != null
|
||||||
|
root.key = minimum(root.right).key
|
||||||
|
root.right = delete(root.right, root.key)
|
||||||
|
else
|
||||||
|
if root.left != null
|
||||||
|
root = root.left
|
||||||
|
else if root.right != null
|
||||||
|
root = root.right
|
||||||
|
else
|
||||||
|
root = null
|
||||||
|
return root
|
||||||
|
*/
|
||||||
|
|
||||||
|
func (root *BinSearchTree) Delete(targetName string) *BinSearchTree {
|
||||||
|
if root == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if targetName < root.data.Name {
|
||||||
|
root.left = root.left.Delete(targetName)
|
||||||
|
} else if targetName > root.data.Name {
|
||||||
|
root.right = root.right.Delete(targetName)
|
||||||
|
} else if root.left != nil && root.right != nil {
|
||||||
|
temp := root.right.Minimum()
|
||||||
|
root.data.Name = root.right.Minimum().data.Name
|
||||||
|
root.data.Phone = root.right.Minimum().data.Phone
|
||||||
|
|
||||||
|
// strcpy(root->name, bst_minimum(root->right)->name);
|
||||||
|
// strcpy(root->phone, bst_minimum(root->right)->phone);
|
||||||
|
root.right = root.right.Delete(temp.data.Name)
|
||||||
|
} else {
|
||||||
|
if root.left != nil {
|
||||||
|
return root.left
|
||||||
|
} else if root.right != nil {
|
||||||
|
return root.right
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bst *BinSearchTree) PrintAll(depth int) {
|
||||||
|
if bst == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
bst.right.PrintAll(depth + 1)
|
||||||
|
|
||||||
|
for i := 0; i < depth; i++ {
|
||||||
|
fmt.Printf("\t")
|
||||||
|
}
|
||||||
|
bst.PrintNode()
|
||||||
|
bst.left.PrintAll(depth + 1)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
package hash_table
|
||||||
|
|
||||||
|
func GetHashString(str string) int {
|
||||||
|
hash := 0
|
||||||
|
|
||||||
|
for _, ch := range str {
|
||||||
|
hash = (hash << 5) - hash + int(ch)
|
||||||
|
}
|
||||||
|
|
||||||
|
if hash < 0 {
|
||||||
|
hash = -hash
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,238 @@
|
||||||
|
package hash_table
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
ds "source/pkg/data_struct"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HashTable - хеш-таблица с цепочками
|
||||||
|
type HashTable struct {
|
||||||
|
buckets []*bucket
|
||||||
|
size int
|
||||||
|
capacity int
|
||||||
|
loadFactor float64
|
||||||
|
}
|
||||||
|
|
||||||
|
type bucket struct {
|
||||||
|
head *elementHT
|
||||||
|
}
|
||||||
|
|
||||||
|
type elementHT struct {
|
||||||
|
data ds.MyData
|
||||||
|
next *elementHT
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewHashTable - создает новую хеш-таблицу
|
||||||
|
func NewHashTable(capacity int, loadFactor float64) *HashTable {
|
||||||
|
|
||||||
|
buckets := make([]*bucket, capacity)
|
||||||
|
|
||||||
|
for i := 0; i < capacity; i++ {
|
||||||
|
buckets[i] = &bucket{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &HashTable{
|
||||||
|
buckets: buckets,
|
||||||
|
size: 0,
|
||||||
|
capacity: capacity,
|
||||||
|
loadFactor: loadFactor,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (h HashTable) getIndex(name string) int {
|
||||||
|
// return GetHashString(name) % h.size
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (h HashTable) Add(name string) {
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
func (ht *HashTable) GetIndex(name string) int {
|
||||||
|
hash := GetHashString(name)
|
||||||
|
return hash % ht.capacity
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (ht *HashTable) getIndex(hash int) int {
|
||||||
|
// return hash % ht.capacity
|
||||||
|
// }
|
||||||
|
|
||||||
|
func (h *HashTable) Insert(new ds.MyData) {
|
||||||
|
|
||||||
|
if h.size >= int(float64(h.capacity)*h.loadFactor) {
|
||||||
|
h.resize()
|
||||||
|
}
|
||||||
|
|
||||||
|
ind := h.GetIndex(new.Name)
|
||||||
|
|
||||||
|
buck := h.buckets[ind]
|
||||||
|
|
||||||
|
current := buck.head
|
||||||
|
|
||||||
|
for current != nil {
|
||||||
|
if current.data.Name == new.Name {
|
||||||
|
current.data.Phone = new.Phone
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
current = current.next
|
||||||
|
}
|
||||||
|
|
||||||
|
newHead := &elementHT{
|
||||||
|
data: new,
|
||||||
|
next: buck.head,
|
||||||
|
}
|
||||||
|
|
||||||
|
buck.head = newHead
|
||||||
|
h.size++
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HashTable) Get(name string) (phone string, status bool) {
|
||||||
|
ind := h.GetIndex(name)
|
||||||
|
|
||||||
|
buck := h.buckets[ind]
|
||||||
|
|
||||||
|
current := buck.head
|
||||||
|
|
||||||
|
for current != nil {
|
||||||
|
if current.data.Name == name {
|
||||||
|
return current.data.Phone, true
|
||||||
|
}
|
||||||
|
|
||||||
|
current = current.next
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
func pressEnterToContinue() {
|
||||||
|
fmt.Print("Нажмите Enter для продолжения...")
|
||||||
|
bufio.NewReader(os.Stdin).ReadBytes('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
// resize - увеличивает размер таблицы
|
||||||
|
func (ht *HashTable) resize() {
|
||||||
|
|
||||||
|
// fmt.Printf("Resize table!\n elements: %d(%.3f%%)\n old capacity: %d\n new capacity: %d\n", ht.size, float64(ht.size)/float64(ht.capacity), ht.capacity, 2*ht.capacity)
|
||||||
|
|
||||||
|
// ht.Print()
|
||||||
|
|
||||||
|
// pressEnterToContinue()
|
||||||
|
|
||||||
|
newCapacity := ht.capacity * 2
|
||||||
|
newHT := NewHashTable(newCapacity, ht.loadFactor)
|
||||||
|
|
||||||
|
for _, b := range ht.buckets {
|
||||||
|
current := b.head
|
||||||
|
for current != nil {
|
||||||
|
newHT.Insert(current.data)
|
||||||
|
current = current.next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ht.buckets = newHT.buckets
|
||||||
|
ht.capacity = newCapacity
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ht *HashTable) Remove(name string) bool {
|
||||||
|
ind := ht.GetIndex(name)
|
||||||
|
|
||||||
|
buck := ht.buckets[ind]
|
||||||
|
|
||||||
|
if buck.head == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if buck.head.data.Name == name {
|
||||||
|
buck.head = buck.head.next
|
||||||
|
ht.size--
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
prev := buck.head
|
||||||
|
current := buck.head.next
|
||||||
|
|
||||||
|
for current != nil {
|
||||||
|
if current.data.Name == name {
|
||||||
|
prev.next = current.next
|
||||||
|
ht.size--
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
prev = current
|
||||||
|
current = current.next
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ht *HashTable) Contains(name string) bool {
|
||||||
|
_, ok := ht.Get(name)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (elem *elementHT) ToString() string {
|
||||||
|
if elem == nil {
|
||||||
|
return "nil"
|
||||||
|
}
|
||||||
|
|
||||||
|
return elem.ToString()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ht *HashTable) Print() {
|
||||||
|
for ind := 0; ind < ht.capacity; ind++ {
|
||||||
|
buck := ht.buckets[ind]
|
||||||
|
current := buck.head
|
||||||
|
|
||||||
|
bucketsStr := ""
|
||||||
|
|
||||||
|
for current != nil {
|
||||||
|
bucketsStr += " --> " + current.ToString()
|
||||||
|
current = current.next
|
||||||
|
}
|
||||||
|
fmt.Printf("[%d]: %s\n", ind, bucketsStr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ht *HashTable) listAll() []ds.MyData {
|
||||||
|
data := make([]ds.MyData, ht.size)
|
||||||
|
|
||||||
|
index := 0
|
||||||
|
|
||||||
|
for ind := 0; ind < ht.capacity; ind++ {
|
||||||
|
buck := ht.buckets[ind]
|
||||||
|
current := buck.head
|
||||||
|
|
||||||
|
for current != nil {
|
||||||
|
data[index] = current.data
|
||||||
|
index++
|
||||||
|
// fmt.Println(current.name, current.phone)
|
||||||
|
current = current.next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ht *HashTable) ListAll() []ds.MyData {
|
||||||
|
// fmt.Printf("Size: %d, Capacity: %d\n", ht.size, ht.capacity)
|
||||||
|
data := ht.listAll()
|
||||||
|
|
||||||
|
data = ds.QSort(data, 0, len(data)-1)
|
||||||
|
|
||||||
|
// for i, el := range data {
|
||||||
|
// fmt.Printf("[%d]: \"%s\", %d\n", i, el.name, el.phone)
|
||||||
|
// }
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (ht *HashTable) PrintMostPopularnames(phone int) {
|
||||||
|
// // fmt.Printf("Size: %d, Capacity: %d\n", ht.size, ht.capacity)
|
||||||
|
// data := ht.listAll()
|
||||||
|
|
||||||
|
// data = QSortElementsHT(data, 0, len(data)-1)
|
||||||
|
|
||||||
|
// for i := 0; i < phone; i++ {
|
||||||
|
// fmt.Printf("[%d]: %3d : %s\n", i, ht.GetIndex(data[len(data)-i-1].name), data[len(data)-i-1].ToString())
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
@ -0,0 +1,152 @@
|
||||||
|
package linked_list
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
ds "source/pkg/data_struct"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Связный список (LinkedListPhoneBook)
|
||||||
|
|
||||||
|
Узел представляется словарём: `{'name': 'Имя', 'phone': '123', 'next': None}.`
|
||||||
|
|
||||||
|
Функции:
|
||||||
|
|
||||||
|
def ll_insert(head, name, phone) — проходит до конца (или сразу добавляет в конец) и возвращает новую голову (если вставка в начало) или изменяет список по ссылке. Удобнее возвращать новую голову, если вставка может быть в начало.
|
||||||
|
|
||||||
|
def ll_find(head, name) — ищет узел, возвращает телефон или None.
|
||||||
|
|
||||||
|
def ll_delete(head, name) — удаляет узел, возвращает новую голову.
|
||||||
|
|
||||||
|
def ll_list_all(head) — собирает все записи в список и сортирует (сортировка вынесена отдельно).
|
||||||
|
*/
|
||||||
|
|
||||||
|
type LinkedList struct {
|
||||||
|
data ds.MyData
|
||||||
|
|
||||||
|
next *LinkedList
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLinkedList(data ds.MyData) *LinkedList {
|
||||||
|
return &LinkedList{
|
||||||
|
data: data,
|
||||||
|
next: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ll *LinkedList) ToString() string {
|
||||||
|
return ll.data.ToString()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ll *LinkedList) Len() int {
|
||||||
|
|
||||||
|
if ll == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
len := 0
|
||||||
|
|
||||||
|
current := ll
|
||||||
|
for current != nil {
|
||||||
|
len++
|
||||||
|
current = current.next
|
||||||
|
}
|
||||||
|
|
||||||
|
return len
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ll *LinkedList) Insert(data ds.MyData) *LinkedList {
|
||||||
|
newNode := NewLinkedList(data)
|
||||||
|
|
||||||
|
if ll == nil {
|
||||||
|
return newNode
|
||||||
|
}
|
||||||
|
|
||||||
|
current := ll
|
||||||
|
for current.next != nil {
|
||||||
|
current = current.next
|
||||||
|
}
|
||||||
|
current.next = newNode
|
||||||
|
return ll
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ll *LinkedList) Search(targetName string) (string, bool) {
|
||||||
|
current := ll
|
||||||
|
|
||||||
|
for current != nil {
|
||||||
|
if current.data.Name == targetName {
|
||||||
|
return current.data.Phone, true
|
||||||
|
}
|
||||||
|
|
||||||
|
current = current.next
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ll *LinkedList) PrintAll() {
|
||||||
|
current := ll
|
||||||
|
index := 0
|
||||||
|
|
||||||
|
for current != nil {
|
||||||
|
fmt.Printf("[%d] %s\n", index, current.ToString())
|
||||||
|
index++
|
||||||
|
current = current.next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ll *LinkedList) Delete(targetName string) (*LinkedList, bool) {
|
||||||
|
|
||||||
|
if ll == nil {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
if ll.data.Name == targetName {
|
||||||
|
ll.data = ll.next.data
|
||||||
|
ll.next = ll.next.next
|
||||||
|
return ll, true
|
||||||
|
}
|
||||||
|
|
||||||
|
prev := ll
|
||||||
|
current := ll.next
|
||||||
|
|
||||||
|
for current != nil {
|
||||||
|
if current.data.Name == targetName {
|
||||||
|
prev.next = current.next
|
||||||
|
}
|
||||||
|
prev = current
|
||||||
|
current = current.next
|
||||||
|
}
|
||||||
|
|
||||||
|
return ll, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ll *LinkedList) listAll() []ds.MyData {
|
||||||
|
current := ll
|
||||||
|
|
||||||
|
listLL := make([]ds.MyData, ll.Len())
|
||||||
|
ind := 0
|
||||||
|
for current != nil {
|
||||||
|
listLL[ind] = current.data
|
||||||
|
ind++
|
||||||
|
current = current.next
|
||||||
|
}
|
||||||
|
|
||||||
|
listLL = ds.QSort(listLL, 0, len(listLL)-1)
|
||||||
|
return listLL
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ll *LinkedList) GetByInd(ind int) (ds.MyData, bool) {
|
||||||
|
if ind >= ll.Len() {
|
||||||
|
return ds.MyData{}, false
|
||||||
|
}
|
||||||
|
|
||||||
|
index := 0
|
||||||
|
current := ll
|
||||||
|
for current != nil {
|
||||||
|
if index == ind {
|
||||||
|
return current.data, true
|
||||||
|
}
|
||||||
|
current = current.next
|
||||||
|
index++
|
||||||
|
}
|
||||||
|
|
||||||
|
return ds.MyData{}, false
|
||||||
|
}
|
||||||
152
stepushovgs/data-structures/source/tests/benchmark/main.go
Normal file
152
stepushovgs/data-structures/source/tests/benchmark/main.go
Normal file
|
|
@ -0,0 +1,152 @@
|
||||||
|
package benchmark
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
csvwriter "source/pkg/csv_writer"
|
||||||
|
ds "source/pkg/data_struct"
|
||||||
|
dg "source/pkg/gen_data"
|
||||||
|
ll "source/pkg/structures/linked_list"
|
||||||
|
|
||||||
|
// csv "source/pkg/csv_ri"
|
||||||
|
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
countUsers = 10_000
|
||||||
|
countRepeat = 5
|
||||||
|
countRandomSearch = 100
|
||||||
|
countNotExitstSearch = 10
|
||||||
|
countDeletes = 50
|
||||||
|
)
|
||||||
|
|
||||||
|
type TestData struct {
|
||||||
|
Items []ds.MyData // все записи
|
||||||
|
ItemsSorted []ds.MyData // все записи отсортированные
|
||||||
|
Existing []ds.MyData // для поиска (существующие)
|
||||||
|
NonExisting []ds.MyData // для поиска (несуществующие)
|
||||||
|
ToDelete []ds.MyData // для удаления
|
||||||
|
}
|
||||||
|
|
||||||
|
type DataStructure interface {
|
||||||
|
Insert(data ds.MyData)
|
||||||
|
Search(name string) *ds.MyData
|
||||||
|
Delete(name string) bool
|
||||||
|
Size() int
|
||||||
|
}
|
||||||
|
|
||||||
|
func uniqueElements(data []ds.MyData) []ds.MyData {
|
||||||
|
res := make([]ds.MyData, 0, len(data))
|
||||||
|
isUnique := true
|
||||||
|
for _, el := range data {
|
||||||
|
for _, resEl := range res {
|
||||||
|
if el == resEl {
|
||||||
|
isUnique = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if isUnique {
|
||||||
|
res = append(res, el)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenerateTestData() TestData {
|
||||||
|
items := dg.RecordsShuffled(countUsers)
|
||||||
|
itemsSort := ds.QSort(items, 0, len(items)-1)
|
||||||
|
|
||||||
|
uniqueItems := uniqueElements(items)
|
||||||
|
existing := make([]ds.MyData, countRandomSearch)
|
||||||
|
// notExisting := [countNotExitstSearch]ds.MyData{}
|
||||||
|
notExisting := make([]ds.MyData, countNotExitstSearch)
|
||||||
|
toDelete := make([]ds.MyData, countDeletes)
|
||||||
|
|
||||||
|
countUniq := len(uniqueItems)
|
||||||
|
for i := 0; i < countUniq; i++ {
|
||||||
|
// randInd := rand.Intn(countUsers)
|
||||||
|
randInd := rand.Intn(countUniq)
|
||||||
|
existing[i] = uniqueItems[randInd]
|
||||||
|
// fmt.Println(randInd)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < countUniq; i++ {
|
||||||
|
// randInd := rand.Intn(countUsers)
|
||||||
|
randInd := rand.Intn(10)
|
||||||
|
name := fmt.Sprintf("User_%d", randInd)
|
||||||
|
notExisting[i] = *ds.NewData(name, "")
|
||||||
|
// fmt.Println(randInd)
|
||||||
|
}
|
||||||
|
|
||||||
|
return TestData{
|
||||||
|
Items: items,
|
||||||
|
ItemsSorted: itemsSort,
|
||||||
|
Existing: existing,
|
||||||
|
NonExisting: notExisting,
|
||||||
|
ToDelete: toDelete,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testOneInsert(structure DataStructure, data []ds.MyData) float64 {
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
|
for _, item := range data {
|
||||||
|
structure.Insert(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
return time.Since(start).Seconds()
|
||||||
|
}
|
||||||
|
|
||||||
|
func testRepInsert(structure DataStructure, data []ds.MyData, nameStruct, mode string) {
|
||||||
|
BenchRes := make([]csvwriter.BenchmarkResult, 0)
|
||||||
|
|
||||||
|
allTestTime := time.Now()
|
||||||
|
averageTime := 0.
|
||||||
|
|
||||||
|
// Тест Слчайной вставки
|
||||||
|
|
||||||
|
for i := 0; i < countRepeat; i++ {
|
||||||
|
|
||||||
|
head := structure
|
||||||
|
resTime := testOneInsert(head, data)
|
||||||
|
|
||||||
|
averageTime += resTime
|
||||||
|
BenchRes = append(BenchRes, csvwriter.BenchmarkResult{
|
||||||
|
Structure: nameStruct,
|
||||||
|
Mode: mode,
|
||||||
|
Operation: "Вставка",
|
||||||
|
Time: resTime,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
averageTime = time.Since(allTestTime).Seconds() / countRepeat
|
||||||
|
|
||||||
|
BenchRes = append(BenchRes, csvwriter.BenchmarkResult{
|
||||||
|
Structure: nameStruct,
|
||||||
|
Mode: mode,
|
||||||
|
Operation: "Вставка",
|
||||||
|
Time: averageTime,
|
||||||
|
})
|
||||||
|
|
||||||
|
csvwriter.AppendRaw(BenchRes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test(nameStruct string, structure DataStructure, data TestData) {
|
||||||
|
// BenchRes := make([]csvwriter.BenchmarkResult, 0)
|
||||||
|
|
||||||
|
// allTestTime := time.Now()
|
||||||
|
|
||||||
|
testRepInsert(structure, data.Items, nameStruct, "Случайный")
|
||||||
|
testRepInsert(structure, data.ItemsSorted, nameStruct, "Отсортированный")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
testData := GenerateTestData()
|
||||||
|
|
||||||
|
var head_ll *ll.LinkedList = nil
|
||||||
|
|
||||||
|
Test("Связный список", head_ll, testData)
|
||||||
|
}
|
||||||
90
stepushovgs/data-structures/source/tests/test_bst/main.go
Normal file
90
stepushovgs/data-structures/source/tests/test_bst/main.go
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"os"
|
||||||
|
ds "source/pkg/data_struct"
|
||||||
|
bst "source/pkg/structures/bin_search_tree"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
countNumbers = 64
|
||||||
|
)
|
||||||
|
|
||||||
|
func pressEnterToContinue() {
|
||||||
|
fmt.Print("Нажмите Enter для продолжения...")
|
||||||
|
bufio.NewReader(os.Stdin).ReadBytes('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
// isInArr проверяет, содержится ли target в срезе arr[:len]
|
||||||
|
func isInArr(arr []int, length int, target int) bool {
|
||||||
|
for i := 0; i < length; i++ {
|
||||||
|
if arr[i] == target {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("hello world!")
|
||||||
|
|
||||||
|
var head *bst.BinSearchTree = nil
|
||||||
|
|
||||||
|
arr := make([]int, countNumbers)
|
||||||
|
|
||||||
|
var temp int
|
||||||
|
for i := 0; i < countNumbers; i++ {
|
||||||
|
// Генерируем уникальное случайное число
|
||||||
|
for {
|
||||||
|
temp = rand.Intn(100) // 0 до 99
|
||||||
|
if !isInArr(arr, i, temp) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
arr[i] = temp
|
||||||
|
|
||||||
|
nameStr := fmt.Sprintf("name_%02d", temp)
|
||||||
|
phoneStr := fmt.Sprintf("phone_%02d", temp)
|
||||||
|
|
||||||
|
data := ds.NewData(nameStr, phoneStr)
|
||||||
|
|
||||||
|
head = head.Insert(*data)
|
||||||
|
fmt.Printf("%d ", arr[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("\n\nКоличество узлов: %d\n", head.Len())
|
||||||
|
|
||||||
|
pressEnterToContinue()
|
||||||
|
|
||||||
|
fmt.Println("\ninorder traversal:")
|
||||||
|
head.BstInorderTraversal()
|
||||||
|
|
||||||
|
tarName := "name_44"
|
||||||
|
|
||||||
|
fmt.Printf("\nПоиск '%s' перед удалением: ", tarName)
|
||||||
|
if found, ok := head.Search(tarName); ok {
|
||||||
|
fmt.Printf("Найден: %s\n", found)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("НЕ найден!\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("\nУдаляем элемент с значением %s:\n", tarName)
|
||||||
|
|
||||||
|
head = head.Delete(tarName)
|
||||||
|
|
||||||
|
fmt.Printf("\nКоличество узлов после удаления: %d\n", head.Len())
|
||||||
|
|
||||||
|
fmt.Printf("Поиск '%s' после удаления: ", tarName)
|
||||||
|
if found, ok := head.Search(tarName); ok {
|
||||||
|
fmt.Printf("ОШИБКА! Все еще существует: %s\n", found)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Успешно удален\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("\ninorder traversal after delete:")
|
||||||
|
head.BstInorderTraversal()
|
||||||
|
}
|
||||||
75
stepushovgs/data-structures/source/tests/test_ht/main.go
Normal file
75
stepushovgs/data-structures/source/tests/test_ht/main.go
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
// hash_table "hash-table-task/hash-table"
|
||||||
|
|
||||||
|
ds "source/pkg/data_struct"
|
||||||
|
ht "source/pkg/structures/hash_table"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
1. Сконструировать и реализовать свою хеш таблицу
|
||||||
|
|
||||||
|
- изначальный размер 8, коэф-т загрузки 0.75
|
||||||
|
|
||||||
|
- Преобразование подаваемого данного в индекс с помощью хеш функции(в ручну) пример: полиномиальный хеш
|
||||||
|
|
||||||
|
- Коллизии обрабатываются методом цепочек, каждая корзина таблицы - список в котором хранятся пары значений key-value
|
||||||
|
|
||||||
|
- При превышении коэф-та загрузки происходит перехеширование таблицы, размер увеличивается вдвое, все пары заново вставляются в таблицу.
|
||||||
|
|
||||||
|
2. Читаем текстовый файл, разбивает на слова, приводим к нижнему регистру, подсчитываем повторения каждого слова: key - слово, value - кол-во повторений
|
||||||
|
|
||||||
|
- На вывод 10 самых встречающихся слов, для каждого слова выводим: ind(hash), key, value
|
||||||
|
- Текст - первая глава, первые три стиха Евгений Онегин
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("hello world")
|
||||||
|
hashTable := ht.NewHashTable(8, 0.75)
|
||||||
|
hashTable.Insert(*ds.NewData("User_0", "Phone_0"))
|
||||||
|
// Чтение всего файла
|
||||||
|
|
||||||
|
// const filePath = "../data/onegin.txt"
|
||||||
|
// // const filePath = "../data/onegin_full.txt"
|
||||||
|
|
||||||
|
// data, err := os.ReadFile(filePath)
|
||||||
|
// text := string(data)
|
||||||
|
// if err != nil {
|
||||||
|
// fmt.Println("Ошибка чтения файла:", err)
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// fmt.Println(text)
|
||||||
|
|
||||||
|
// text = strings.ToLower(text)
|
||||||
|
|
||||||
|
// // Разбиение на слова (разделители: пробелы и переводы строк)
|
||||||
|
// re := regexp.MustCompile(`[\p{L}\p{N}-]+`)
|
||||||
|
// words := re.FindAllString(text, -1)
|
||||||
|
|
||||||
|
// fmt.Printf("Найдено слов: %d\n", len(words))
|
||||||
|
// for i, word := range words {
|
||||||
|
// fmt.Printf("Слово %d: %s\n", i+1, word)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// hashTable := ht.NewHashTable(8, 0.95)
|
||||||
|
|
||||||
|
// for i, word := range words {
|
||||||
|
// fmt.Printf("%d : %s\n", i, word)
|
||||||
|
// hashTable.Put(word, 1)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fmt.Println("\nХеш таблица текста: ")
|
||||||
|
// hashTable.Print()
|
||||||
|
|
||||||
|
// // fmt.Println("Отсортированные ячейки таблицы: ")
|
||||||
|
// // hashTable.PrintSort()
|
||||||
|
|
||||||
|
// fmt.Println("\nСамые часто встречающиеся слова: ")
|
||||||
|
|
||||||
|
// // hashTable.PrintMostPopularWords(10)
|
||||||
|
}
|
||||||
171
stepushovgs/data-structures/source/tests/test_ll/main.go
Normal file
171
stepushovgs/data-structures/source/tests/test_ll/main.go
Normal file
|
|
@ -0,0 +1,171 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"os"
|
||||||
|
dg "source/pkg/gen_data"
|
||||||
|
rs "source/pkg/resulter"
|
||||||
|
ll "source/pkg/structures/linked_list"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func isInArr(arr []int, length int, target int) bool {
|
||||||
|
for i := 0; i < length; i++ {
|
||||||
|
if arr[i] == target {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func Razdelitel() {
|
||||||
|
for i := 0; i < 20; i++ {
|
||||||
|
fmt.Print("-")
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
|
|
||||||
|
func pressEnterToContinue() {
|
||||||
|
fmt.Print("Нажмите Enter для продолжения...")
|
||||||
|
bufio.NewReader(os.Stdin).ReadBytes('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("hello world!")
|
||||||
|
|
||||||
|
results := make([]rs.BenchmarkResult, 0, countUsers)
|
||||||
|
averageInsertTime := 0.
|
||||||
|
|
||||||
|
Razdelitel()
|
||||||
|
fmt.Println("Тестирование вставки:")
|
||||||
|
var head *ll.LinkedList = nil
|
||||||
|
|
||||||
|
for testNum := 0; testNum < countRepeat; testNum++ {
|
||||||
|
head = nil
|
||||||
|
|
||||||
|
testData := dg.RecordsShuffled(countUsers)
|
||||||
|
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
|
for i := 0; i < countUsers; i++ {
|
||||||
|
head.Insert(testData[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
elapsed := time.Since(start).Seconds()
|
||||||
|
averageInsertTime += elapsed
|
||||||
|
|
||||||
|
results = append(results, rs.BenchmarkResult{
|
||||||
|
Structure: "Связный список", Mode: "Случайный", Operation: "Вставка", Time: elapsed,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
averageInsertTime /= countRepeat
|
||||||
|
results = append(results, rs.BenchmarkResult{
|
||||||
|
Structure: "Связный список", Mode: "Случайный", Operation: "Вставка", Time: averageInsertTime,
|
||||||
|
})
|
||||||
|
for i := 0; i < 6; i++ {
|
||||||
|
fmt.Println(results[i].ToString())
|
||||||
|
}
|
||||||
|
|
||||||
|
Razdelitel()
|
||||||
|
// fmt.Println("Тестирование Поиска:")
|
||||||
|
// // results = make([]rs.BenchmarkResult, 0, countUsers)
|
||||||
|
// averageSearchTime := 0.
|
||||||
|
|
||||||
|
// for testNum := 0; testNum < countRepeat; testNum++ {
|
||||||
|
// // var head *ll.LinkedList = nil
|
||||||
|
// // head = dg.RecordsShuffled(countUsers)
|
||||||
|
|
||||||
|
// testData := make([]ds.MyData, countRandomSearch)
|
||||||
|
|
||||||
|
// for i := 0; i < countRandomSearch; i++ {
|
||||||
|
// // randInd := rand.Intn(countUsers)
|
||||||
|
// randInd := rand.Intn(1000) + 9000
|
||||||
|
// testData[i], _ = head.GetByInd(randInd)
|
||||||
|
// // fmt.Println(randInd)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// start := time.Now()
|
||||||
|
|
||||||
|
// for i := 0; i < countRandomSearch; i++ {
|
||||||
|
// head.Search(testData[i].Name)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// elapsed := time.Since(start).Seconds()
|
||||||
|
// averageSearchTime += elapsed
|
||||||
|
|
||||||
|
// results = append(results, rs.BenchmarkResult{
|
||||||
|
// Structure: "Связный список", Mode: "Случайный", Operation: "Поиск", Time: elapsed,
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// averageSearchTime /= countRepeat
|
||||||
|
// results = append(results, rs.BenchmarkResult{
|
||||||
|
// Structure: "Связный список", Mode: "Случайный", Operation: "Поиск", Time: averageSearchTime,
|
||||||
|
// })
|
||||||
|
// for i := 0; i < len(results); i++ {
|
||||||
|
// fmt.Println(results[i].ToString())
|
||||||
|
// }
|
||||||
|
|
||||||
|
resultsS := runSearchBenchmark(head)
|
||||||
|
for i := 0; i < len(resultsS); i++ {
|
||||||
|
fmt.Println(resultsS[i].ToString())
|
||||||
|
}
|
||||||
|
// rs.AppendRaw(results)
|
||||||
|
}
|
||||||
|
|
||||||
|
func runSearchBenchmark(head *ll.LinkedList) []rs.BenchmarkResult {
|
||||||
|
fmt.Println("\n=== Тестирование Поиска ===")
|
||||||
|
|
||||||
|
const countRandomSearch = 1000 // уменьшим для поиска
|
||||||
|
|
||||||
|
var results []rs.BenchmarkResult
|
||||||
|
var totalTime float64
|
||||||
|
|
||||||
|
// Предварительно собираем имена для поиска
|
||||||
|
names := make([]string, countUsers)
|
||||||
|
for i := 0; i < countUsers; i++ {
|
||||||
|
data, found := head.GetByInd(i)
|
||||||
|
if found {
|
||||||
|
names[i] = data.Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for testNum := 0; testNum < countRepeat; testNum++ {
|
||||||
|
// Выбираем случайные имена
|
||||||
|
searchNames := make([]string, countRandomSearch)
|
||||||
|
for i := 0; i < countRandomSearch; i++ {
|
||||||
|
searchNames[i] = names[rand.Intn(countUsers)]
|
||||||
|
}
|
||||||
|
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
|
for _, name := range searchNames {
|
||||||
|
el, ok := head.Search(name)
|
||||||
|
if ok {
|
||||||
|
fmt.Println(el)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elapsed := time.Since(start).Seconds()
|
||||||
|
|
||||||
|
totalTime += elapsed
|
||||||
|
|
||||||
|
fmt.Printf(" Тест %d: %.6f сек (%.2f мкс/оп)\n",
|
||||||
|
testNum+1, elapsed,
|
||||||
|
elapsed/float64(countRandomSearch)*1_000_000)
|
||||||
|
}
|
||||||
|
|
||||||
|
avgTime := totalTime / float64(countRepeat)
|
||||||
|
fmt.Printf("Среднее: %.6f сек\n", avgTime)
|
||||||
|
|
||||||
|
results = append(results, rs.BenchmarkResult{
|
||||||
|
Structure: "Связный список",
|
||||||
|
Mode: "Случайный",
|
||||||
|
Operation: "Поиск",
|
||||||
|
Time: avgTime,
|
||||||
|
})
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user