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:
Yudong Jin
2026-03-28 04:24:07 +08:00
committed by GitHub
parent 2ca570cc33
commit 772183705e
1958 changed files with 108186 additions and 0 deletions
@@ -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();
}
+162
View File
@@ -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();
}