mirror of
https://github.com/krahets/hello-algo.git
synced 2026-07-16 08:56:05 +00:00
Add ru version (#1865)
* Add Russian docs site baseline * Add Russian localized codebase * Polish Russian code wording * Update ru code translation. * Update code translation and chapter covers. * Fix pythontutor extraction. * Add README and landing page. * placeholder of profiles * Use figures of English version * Remove chapter paperbook
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
// File: bubble_sort.zig
|
||||
// Created Time: 2023-01-08
|
||||
// Author: codingonion (coderonion@gmail.com)
|
||||
|
||||
const std = @import("std");
|
||||
const inc = @import("include");
|
||||
|
||||
// Пузырьковая сортировка
|
||||
fn bubbleSort(nums: []i32) void {
|
||||
// Внешний цикл: неотсортированный диапазон [0, i]
|
||||
var i: usize = nums.len - 1;
|
||||
while (i > 0) : (i -= 1) {
|
||||
var j: usize = 0;
|
||||
// Внутренний цикл: переместить максимальный элемент неотсортированного диапазона [0, i] в его правый конец
|
||||
while (j < i) : (j += 1) {
|
||||
if (nums[j] > nums[j + 1]) {
|
||||
// Поменять местами nums[j] и nums[j + 1]
|
||||
var tmp = nums[j];
|
||||
nums[j] = nums[j + 1];
|
||||
nums[j + 1] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Пузырьковая сортировка (оптимизация флагом)
|
||||
fn bubbleSortWithFlag(nums: []i32) void {
|
||||
// Внешний цикл: неотсортированный диапазон [0, i]
|
||||
var i: usize = nums.len - 1;
|
||||
while (i > 0) : (i -= 1) {
|
||||
var flag = false; // Инициализировать флаг
|
||||
var j: usize = 0;
|
||||
// Внутренний цикл: переместить максимальный элемент неотсортированного диапазона [0, i] в его правый конец
|
||||
while (j < i) : (j += 1) {
|
||||
if (nums[j] > nums[j + 1]) {
|
||||
// Поменять местами nums[j] и nums[j + 1]
|
||||
var tmp = nums[j];
|
||||
nums[j] = nums[j + 1];
|
||||
nums[j + 1] = tmp;
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
if (!flag) break; // На этой итерации «всплытия» не было ни одного обмена, сразу выйти
|
||||
}
|
||||
}
|
||||
|
||||
// Driver Code
|
||||
pub fn main() !void {
|
||||
var nums = [_]i32{ 4, 1, 3, 1, 5, 2 };
|
||||
bubbleSort(&nums);
|
||||
std.debug.print("После завершения пузырьковой сортировки nums = ", .{});
|
||||
inc.PrintUtil.printArray(i32, &nums);
|
||||
|
||||
var nums1 = [_]i32{ 4, 1, 3, 1, 5, 2 };
|
||||
bubbleSortWithFlag(&nums1);
|
||||
std.debug.print("\nПосле завершения пузырьковой сортировки nums1 = ", .{});
|
||||
inc.PrintUtil.printArray(i32, &nums1);
|
||||
|
||||
_ = try std.io.getStdIn().reader().readByte();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
// File: insertion_sort.zig
|
||||
// Created Time: 2023-01-08
|
||||
// Author: codingonion (coderonion@gmail.com)
|
||||
|
||||
const std = @import("std");
|
||||
const inc = @import("include");
|
||||
|
||||
// Сортировка вставками
|
||||
fn insertionSort(nums: []i32) void {
|
||||
// Внешний цикл: отсортированный диапазон [0, i-1]
|
||||
var i: usize = 1;
|
||||
while (i < nums.len) : (i += 1) {
|
||||
var base = nums[i];
|
||||
var j: usize = i;
|
||||
// Внутренний цикл: вставить base в правильную позицию отсортированного диапазона [0, i-1]
|
||||
while (j >= 1 and nums[j - 1] > base) : (j -= 1) {
|
||||
nums[j] = nums[j - 1]; // Сдвинуть nums[j] на одну позицию вправо
|
||||
}
|
||||
nums[j] = base; // Поместить base в правильную позицию
|
||||
}
|
||||
}
|
||||
|
||||
// Driver Code
|
||||
pub fn main() !void {
|
||||
var nums = [_]i32{ 4, 1, 3, 1, 5, 2 };
|
||||
insertionSort(&nums);
|
||||
std.debug.print("После завершения сортировки вставками nums = ", .{});
|
||||
inc.PrintUtil.printArray(i32, &nums);
|
||||
|
||||
_ = try std.io.getStdIn().reader().readByte();
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// File: merge_sort.zig
|
||||
// Created Time: 2023-01-15
|
||||
// Author: codingonion (coderonion@gmail.com)
|
||||
|
||||
const std = @import("std");
|
||||
const inc = @import("include");
|
||||
|
||||
// Объединить левый и правый подмассивы
|
||||
// Диапазон левого подмассива [left, mid]
|
||||
// Диапазон правого подмассива [mid + 1, right]
|
||||
fn merge(nums: []i32, left: usize, mid: usize, right: usize) !void {
|
||||
// Инициализация вспомогательного массива
|
||||
var mem_arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||
defer mem_arena.deinit();
|
||||
const mem_allocator = mem_arena.allocator();
|
||||
var tmp = try mem_allocator.alloc(i32, right + 1 - left);
|
||||
std.mem.copy(i32, tmp, nums[left..right+1]);
|
||||
// Начальный и конечный индексы левого подмассива
|
||||
var leftStart = left - left;
|
||||
var leftEnd = mid - left;
|
||||
// Начальный и конечный индексы правого подмассива
|
||||
var rightStart = mid + 1 - left;
|
||||
var rightEnd = right - left;
|
||||
// i и j указывают соответственно на первые элементы левого и правого подмассивов
|
||||
var i = leftStart;
|
||||
var j = rightStart;
|
||||
// Объединить левый и правый подмассивы, перезаписывая исходный массив nums
|
||||
var k = left;
|
||||
while (k <= right) : (k += 1) {
|
||||
// Если «левый подмассив уже полностью слит», выбрать элемент правого подмассива и выполнить j++
|
||||
if (i > leftEnd) {
|
||||
nums[k] = tmp[j];
|
||||
j += 1;
|
||||
// Иначе, если «правый подмассив уже полностью слит» или «элемент левого подмассива <= элементу правого подмассива», выбрать элемент левого подмассива и выполнить i++
|
||||
} else if (j > rightEnd or tmp[i] <= tmp[j]) {
|
||||
nums[k] = tmp[i];
|
||||
i += 1;
|
||||
// Иначе, если «оба подмассива еще не полностью слиты» и «элемент левого подмассива > элемента правого подмассива», выбрать элемент правого подмассива и выполнить j++
|
||||
} else {
|
||||
nums[k] = tmp[j];
|
||||
j += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Сортировка слиянием
|
||||
fn mergeSort(nums: []i32, left: usize, right: usize) !void {
|
||||
// Условие завершения
|
||||
if (left >= right) return; // Завершить рекурсию, когда длина подмассива равна 1
|
||||
// Этап разбиения
|
||||
var mid = left + (right - left) / 2; // Вычислить середину
|
||||
try mergeSort(nums, left, mid); // Рекурсивно обработать левый подмассив
|
||||
try mergeSort(nums, mid + 1, right); // Рекурсивно обработать правый подмассив
|
||||
// Этап слияния
|
||||
try merge(nums, left, mid, right);
|
||||
}
|
||||
|
||||
// Driver Code
|
||||
pub fn main() !void {
|
||||
// Сортировка слиянием
|
||||
var nums = [_]i32{ 7, 3, 2, 6, 0, 1, 5, 4 };
|
||||
try mergeSort(&nums, 0, nums.len - 1);
|
||||
std.debug.print("После завершения сортировки слиянием nums = ", .{});
|
||||
inc.PrintUtil.printArray(i32, &nums);
|
||||
|
||||
_ = try std.io.getStdIn().reader().readByte();
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
// File: quick_sort.zig
|
||||
// Created Time: 2023-01-15
|
||||
// Author: codingonion (coderonion@gmail.com)
|
||||
|
||||
const std = @import("std");
|
||||
const inc = @import("include");
|
||||
|
||||
// Класс быстрой сортировки
|
||||
const QuickSort = struct {
|
||||
|
||||
// Обмен элементов
|
||||
pub fn swap(nums: []i32, i: usize, j: usize) void {
|
||||
var tmp = nums[i];
|
||||
nums[i] = nums[j];
|
||||
nums[j] = tmp;
|
||||
}
|
||||
|
||||
// Разбиение с опорными указателями
|
||||
pub fn partition(nums: []i32, left: usize, right: usize) usize {
|
||||
// Взять nums[left] в качестве опорного элемента
|
||||
var i = left;
|
||||
var j = right;
|
||||
while (i < j) {
|
||||
while (i < j and nums[j] >= nums[left]) j -= 1; // Идти справа налево в поисках первого элемента меньше опорного
|
||||
while (i < j and nums[i] <= nums[left]) i += 1; // Идти слева направо в поисках первого элемента больше опорного
|
||||
swap(nums, i, j); // Поменять эти два элемента местами
|
||||
}
|
||||
swap(nums, i, left); // Переместить опорный элемент на границу двух подмассивов
|
||||
return i; // Вернуть индекс опорного элемента
|
||||
}
|
||||
|
||||
// Быстрая сортировка
|
||||
pub fn quickSort(nums: []i32, left: usize, right: usize) void {
|
||||
// Завершить рекурсию, когда длина подмассива равна 1
|
||||
if (left >= right) return;
|
||||
// Разбиение с опорными указателями
|
||||
var pivot = partition(nums, left, right);
|
||||
// Рекурсивно обработать левый и правый подмассивы
|
||||
quickSort(nums, left, pivot - 1);
|
||||
quickSort(nums, pivot + 1, right);
|
||||
}
|
||||
};
|
||||
|
||||
// Класс быстрой сортировки (оптимизация медианным опорным элементом)
|
||||
const QuickSortMedian = struct {
|
||||
|
||||
// Обмен элементов
|
||||
pub fn swap(nums: []i32, i: usize, j: usize) void {
|
||||
var tmp = nums[i];
|
||||
nums[i] = nums[j];
|
||||
nums[j] = tmp;
|
||||
}
|
||||
|
||||
// Выбрать медиану из трех кандидатов
|
||||
pub fn medianThree(nums: []i32, left: usize, mid: usize, right: usize) usize {
|
||||
var l = nums[left];
|
||||
var m = nums[mid];
|
||||
var r = nums[right];
|
||||
if ((l <= m && m <= r) || (r <= m && m <= l))
|
||||
return mid; // m находится между l и r
|
||||
if ((m <= l && l <= r) || (r <= l && l <= m))
|
||||
return left; // l находится между m и r
|
||||
return right;
|
||||
}
|
||||
|
||||
// Разбиение с опорными указателями (медиана трех)
|
||||
pub fn partition(nums: []i32, left: usize, right: usize) usize {
|
||||
// Выбрать медиану из трех кандидатов
|
||||
var med = medianThree(nums, left, (left + right) / 2, right);
|
||||
// Переместить медиану в крайний левый элемент массива
|
||||
swap(nums, left, med);
|
||||
// Взять nums[left] в качестве опорного элемента
|
||||
var i = left;
|
||||
var j = right;
|
||||
while (i < j) {
|
||||
while (i < j and nums[j] >= nums[left]) j -= 1; // Идти справа налево в поисках первого элемента меньше опорного
|
||||
while (i < j and nums[i] <= nums[left]) i += 1; // Идти слева направо в поисках первого элемента больше опорного
|
||||
swap(nums, i, j); // Поменять эти два элемента местами
|
||||
}
|
||||
swap(nums, i, left); // Переместить опорный элемент на границу двух подмассивов
|
||||
return i; // Вернуть индекс опорного элемента
|
||||
}
|
||||
|
||||
// Быстрая сортировка
|
||||
pub fn quickSort(nums: []i32, left: usize, right: usize) void {
|
||||
// Завершить рекурсию, когда длина подмассива равна 1
|
||||
if (left >= right) return;
|
||||
// Разбиение с опорными указателями
|
||||
var pivot = partition(nums, left, right);
|
||||
if (pivot == 0) return;
|
||||
// Рекурсивно обработать левый и правый подмассивы
|
||||
quickSort(nums, left, pivot - 1);
|
||||
quickSort(nums, pivot + 1, right);
|
||||
}
|
||||
};
|
||||
|
||||
// Класс быстрой сортировки (оптимизация глубины рекурсии)
|
||||
const QuickSortTailCall = struct {
|
||||
|
||||
// Обмен элементов
|
||||
pub fn swap(nums: []i32, i: usize, j: usize) void {
|
||||
var tmp = nums[i];
|
||||
nums[i] = nums[j];
|
||||
nums[j] = tmp;
|
||||
}
|
||||
|
||||
// Разбиение с опорными указателями
|
||||
pub fn partition(nums: []i32, left: usize, right: usize) usize {
|
||||
// Взять nums[left] в качестве опорного элемента
|
||||
var i = left;
|
||||
var j = right;
|
||||
while (i < j) {
|
||||
while (i < j and nums[j] >= nums[left]) j -= 1; // Идти справа налево в поисках первого элемента меньше опорного
|
||||
while (i < j and nums[i] <= nums[left]) i += 1; // Идти слева направо в поисках первого элемента больше опорного
|
||||
swap(nums, i, j); // Поменять эти два элемента местами
|
||||
}
|
||||
swap(nums, i, left); // Переместить опорный элемент на границу двух подмассивов
|
||||
return i; // Вернуть индекс опорного элемента
|
||||
}
|
||||
|
||||
// Быстрая сортировка (оптимизация глубины рекурсии)
|
||||
pub fn quickSort(nums: []i32, left_: usize, right_: usize) void {
|
||||
var left = left_;
|
||||
var right = right_;
|
||||
// Завершить рекурсию, когда длина подмассива равна 1
|
||||
while (left < right) {
|
||||
// Операция разбиения с опорными указателями
|
||||
var pivot = partition(nums, left, right);
|
||||
// Выполнить быструю сортировку для более короткого из двух подмассивов
|
||||
if (pivot - left < right - pivot) {
|
||||
quickSort(nums, left, pivot - 1); // Рекурсивно отсортировать левый подмассив
|
||||
left = pivot + 1; // Оставшийся неотсортированный диапазон: [pivot + 1, right]
|
||||
} else {
|
||||
quickSort(nums, pivot + 1, right); // Рекурсивно отсортировать правый подмассив
|
||||
right = pivot - 1; // Оставшийся неотсортированный диапазон: [left, pivot - 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Driver Code
|
||||
pub fn main() !void {
|
||||
// Быстрая сортировка
|
||||
var nums = [_]i32{ 2, 4, 1, 0, 3, 5 };
|
||||
QuickSort.quickSort(&nums, 0, nums.len - 1);
|
||||
std.debug.print("После завершения быстрой сортировки nums = ", .{});
|
||||
inc.PrintUtil.printArray(i32, &nums);
|
||||
|
||||
// Быстрая сортировка (оптимизация медианным опорным элементом)
|
||||
var nums1 = [_]i32{ 2, 4, 1, 0, 3, 5 };
|
||||
QuickSortMedian.quickSort(&nums1, 0, nums1.len - 1);
|
||||
std.debug.print("\nПосле завершения быстрой сортировки (оптимизация медианным опорным элементом) nums = ", .{});
|
||||
inc.PrintUtil.printArray(i32, &nums1);
|
||||
|
||||
// Быстрая сортировка (оптимизация глубины рекурсии)
|
||||
var nums2 = [_]i32{ 2, 4, 1, 0, 3, 5 };
|
||||
QuickSortTailCall.quickSort(&nums2, 0, nums2.len - 1);
|
||||
std.debug.print("\nПосле завершения быстрой сортировки (оптимизация глубины рекурсии) nums = ", .{});
|
||||
inc.PrintUtil.printArray(i32, &nums2);
|
||||
|
||||
_ = try std.io.getStdIn().reader().readByte();
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
// File: radix_sort.zig
|
||||
// Created Time: 2023-01-15
|
||||
// Author: codingonion (coderonion@gmail.com)
|
||||
|
||||
const std = @import("std");
|
||||
const inc = @import("include");
|
||||
|
||||
// Получить k-й разряд элемента num, где exp = 10^(k-1)
|
||||
fn digit(num: i32, exp: i32) i32 {
|
||||
// Передача exp вместо k позволяет избежать повторного дорогостоящего вычисления степени
|
||||
return @mod(@divFloor(num, exp), 10);
|
||||
}
|
||||
|
||||
// Сортировка подсчетом (сортировка по k-му разряду nums)
|
||||
fn countingSortDigit(nums: []i32, exp: i32) !void {
|
||||
// Разряды десятичной системы лежат в диапазоне 0~9, поэтому нужен массив корзин длины 10
|
||||
var mem_arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||
// defer mem_arena.deinit();
|
||||
const mem_allocator = mem_arena.allocator();
|
||||
var counter = try mem_allocator.alloc(usize, 10);
|
||||
@memset(counter, 0);
|
||||
var n = nums.len;
|
||||
// Подсчитать число появлений каждой цифры от 0 до 9
|
||||
for (nums) |num| {
|
||||
var d: u32 = @bitCast(digit(num, exp)); // Получить k-й разряд nums[i], обозначив его как d
|
||||
counter[d] += 1; // Подсчитать число появлений цифры d
|
||||
}
|
||||
// Вычислить префиксные суммы и преобразовать «число появлений» в «индекс массива»
|
||||
var i: usize = 1;
|
||||
while (i < 10) : (i += 1) {
|
||||
counter[i] += counter[i - 1];
|
||||
}
|
||||
// Выполняя обратный проход, заполнить res элементами по статистике в корзинах
|
||||
var res = try mem_allocator.alloc(i32, n);
|
||||
i = n - 1;
|
||||
while (i >= 0) : (i -= 1) {
|
||||
var d: u32 = @bitCast(digit(nums[i], exp));
|
||||
var j = counter[d] - 1; // Получить индекс j цифры d в массиве
|
||||
res[j] = nums[i]; // Поместить текущий элемент по индексу j
|
||||
counter[d] -= 1; // Уменьшить количество d на 1
|
||||
if (i == 0) break;
|
||||
}
|
||||
// Перезаписать исходный массив nums результатом
|
||||
i = 0;
|
||||
while (i < n) : (i += 1) {
|
||||
nums[i] = res[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Поразрядная сортировка
|
||||
fn radixSort(nums: []i32) !void {
|
||||
// Получить максимальный элемент массива, чтобы определить максимальное число разрядов
|
||||
var m: i32 = std.math.minInt(i32);
|
||||
for (nums) |num| {
|
||||
if (num > m) m = num;
|
||||
}
|
||||
// Проходить разряды от младшего к старшему
|
||||
var exp: i32 = 1;
|
||||
while (exp <= m) : (exp *= 10) {
|
||||
// Выполнить сортировку подсчетом по k-му разряду элементов массива
|
||||
// k = 1 -> exp = 1
|
||||
// k = 2 -> exp = 10
|
||||
// то есть exp = 10^(k-1)
|
||||
try countingSortDigit(nums, exp);
|
||||
}
|
||||
}
|
||||
|
||||
// Driver Code
|
||||
pub fn main() !void {
|
||||
// Поразрядная сортировка
|
||||
var nums = [_]i32{ 23, 12, 3, 4, 788, 192 };
|
||||
try radixSort(&nums);
|
||||
std.debug.print("После завершения поразрядной сортировки nums = ", .{});
|
||||
inc.PrintUtil.printArray(i32, &nums);
|
||||
|
||||
_ = try std.io.getStdIn().reader().readByte();
|
||||
}
|
||||
Reference in New Issue
Block a user