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,145 @@
/**
* File: array_deque.kt
* Created Time: 2024-01-25
* Author: curtishd (1023632660@qq.com)
*/
package chapter_stack_and_queue
/* Двусторонняя очередь на основе кольцевого массива */
/* Конструктор */
class ArrayDeque(capacity: Int) {
private var nums: IntArray = IntArray(capacity) // Массив для хранения элементов двусторонней очереди
private var front: Int = 0 // Указатель head, указывающий на первый элемент очереди
private var queSize: Int = 0 // Длина двусторонней очереди
/* Получить вместимость двусторонней очереди */
fun capacity(): Int {
return nums.size
}
/* Получение длины двусторонней очереди */
fun size(): Int {
return queSize
}
/* Проверка, пуста ли двусторонняя очередь */
fun isEmpty(): Boolean {
return queSize == 0
}
/* Вычислить индекс в кольцевом массиве */
private fun index(i: Int): Int {
// С помощью операции взятия по модулю соединить начало и конец массива
// Когда i выходит за конец массива, он возвращается в начало
// Когда i выходит за начало массива, он возвращается в конец
return (i + capacity()) % capacity()
}
/* Добавление в голову очереди */
fun pushFirst(num: Int) {
if (queSize == capacity()) {
println("Двусторонняя очередь заполнена")
return
}
// Указатель головы сдвигается на одну позицию влево
// С помощью операции взятия по модулю front после выхода за начало массива возвращается в хвост
front = index(front - 1)
// Добавить num в голову очереди
nums[front] = num
queSize++
}
/* Добавление в хвост очереди */
fun pushLast(num: Int) {
if (queSize == capacity()) {
println("Двусторонняя очередь заполнена")
return
}
// Вычислить указатель хвоста, указывающий на индекс хвоста + 1
val rear = index(front + queSize)
// Добавить num в хвост очереди
nums[rear] = num
queSize++
}
/* Извлечение из головы очереди */
fun popFirst(): Int {
val num = peekFirst()
// Указатель головы сдвигается на одну позицию назад
front = index(front + 1)
queSize--
return num
}
/* Извлечение из хвоста очереди */
fun popLast(): Int {
val num = peekLast()
queSize--
return num
}
/* Доступ к элементу в начале очереди */
fun peekFirst(): Int {
if (isEmpty()) throw IndexOutOfBoundsException()
return nums[front]
}
/* Доступ к элементу в конце очереди */
fun peekLast(): Int {
if (isEmpty()) throw IndexOutOfBoundsException()
// Вычислить индекс хвостового элемента
val last = index(front + queSize - 1)
return nums[last]
}
/* Вернуть массив для вывода */
fun toArray(): IntArray {
// Преобразовывать только элементы списка в пределах фактической длины
val res = IntArray(queSize)
var i = 0
var j = front
while (i < queSize) {
res[i] = nums[index(j)]
i++
j++
}
return res
}
}
/* Driver Code */
fun main() {
/* Инициализация двусторонней очереди */
val deque = ArrayDeque(10)
deque.pushLast(3)
deque.pushLast(2)
deque.pushLast(5)
println("Двусторонняя очередь deque = ${deque.toArray().contentToString()}")
/* Доступ к элементу */
val peekFirst = deque.peekFirst()
println("Первый элемент peekFirst = $peekFirst")
val peekLast = deque.peekLast()
println("Последний элемент peekLast = $peekLast")
/* Добавление элемента в очередь */
deque.pushLast(4)
println("После добавления элемента 4 в хвост deque = ${deque.toArray().contentToString()}")
deque.pushFirst(1)
println("После добавления элемента 1 в голову deque = ${deque.toArray().contentToString()}")
/* Извлечение элемента из очереди */
val popLast = deque.popLast()
println("Извлеченный из хвоста элемент = ${popLast}, deque после извлечения из хвоста = ${deque.toArray().contentToString()}")
val popFirst = deque.popFirst()
println("Извлеченный из головы элемент = ${popFirst}, deque после извлечения из головы = ${deque.toArray().contentToString()}")
/* Получение длины двусторонней очереди */
val size = deque.size()
println("Длина двусторонней очереди size = $size")
/* Проверка, пуста ли двусторонняя очередь */
val isEmpty = deque.isEmpty()
println("Пуста ли двусторонняя очередь = $isEmpty")
}
@@ -0,0 +1,110 @@
/**
* File: array_queue.kt
* Created Time: 2024-01-25
* Author: curtishd (1023632660@qq.com)
*/
package chapter_stack_and_queue
/* Очередь на основе кольцевого массива */
class ArrayQueue(capacity: Int) {
private val nums: IntArray = IntArray(capacity) // Массив для хранения элементов очереди
private var front: Int = 0 // Указатель head, указывающий на первый элемент очереди
private var queSize: Int = 0 // Длина очереди
/* Получить вместимость очереди */
fun capacity(): Int {
return nums.size
}
/* Получение длины очереди */
fun size(): Int {
return queSize
}
/* Проверка, пуста ли очередь */
fun isEmpty(): Boolean {
return queSize == 0
}
/* Поместить в очередь */
fun push(num: Int) {
if (queSize == capacity()) {
println("Очередь заполнена")
return
}
// Вычислить указатель хвоста, указывающий на индекс хвоста + 1
// С помощью операции взятия по модулю вернуть rear к началу после выхода за конец массива
val rear = (front + queSize) % capacity()
// Добавить num в хвост очереди
nums[rear] = num
queSize++
}
/* Извлечь из очереди */
fun pop(): Int {
val num = peek()
// Указатель head сдвигается на одну позицию назад; если он выходит за конец, то возвращается в начало массива
front = (front + 1) % capacity()
queSize--
return num
}
/* Доступ к элементу в начале очереди */
fun peek(): Int {
if (isEmpty()) throw IndexOutOfBoundsException()
return nums[front]
}
/* Вернуть массив */
fun toArray(): IntArray {
// Преобразовывать только элементы списка в пределах фактической длины
val res = IntArray(queSize)
var i = 0
var j = front
while (i < queSize) {
res[i] = nums[j % capacity()]
i++
j++
}
return res
}
}
/* Driver Code */
fun main() {
/* Инициализация очереди */
val capacity = 10
val queue = ArrayQueue(capacity)
/* Добавление элемента в очередь */
queue.push(1)
queue.push(3)
queue.push(2)
queue.push(5)
queue.push(4)
println("Очередь queue = ${queue.toArray().contentToString()}")
/* Доступ к элементу в начале очереди */
val peek = queue.peek()
println("Первый элемент peek = $peek")
/* Извлечение элемента из очереди */
val pop = queue.pop()
println("Извлеченный элемент pop = ${pop}, queue после извлечения = ${queue.toArray().contentToString()}")
/* Получение длины очереди */
val size = queue.size()
println("Длина очереди size = $size")
/* Проверка, пуста ли очередь */
val isEmpty = queue.isEmpty()
println("Пуста ли очередь = $isEmpty")
/* Проверка кольцевого массива */
for (i in 0..9) {
queue.push(i)
queue.pop()
println("После $i-го раунда операций enqueue и dequeue queue = ${queue.toArray().contentToString()}")
}
}
@@ -0,0 +1,75 @@
/**
* File: array_stack.kt
* Created Time: 2024-01-25
* Author: curtishd (1023632660@qq.com)
*/
package chapter_stack_and_queue
/* Стек на основе массива */
class ArrayStack {
// Инициализация списка (динамического массива)
private val stack = mutableListOf<Int>()
/* Получение длины стека */
fun size(): Int {
return stack.size
}
/* Проверка, пуст ли стек */
fun isEmpty(): Boolean {
return size() == 0
}
/* Поместить в стек */
fun push(num: Int) {
stack.add(num)
}
/* Извлечь из стека */
fun pop(): Int {
if (isEmpty()) throw IndexOutOfBoundsException()
return stack.removeAt(size() - 1)
}
/* Доступ к верхнему элементу стека */
fun peek(): Int {
if (isEmpty()) throw IndexOutOfBoundsException()
return stack[size() - 1]
}
/* Преобразовать List в Array и вернуть */
fun toArray(): Array<Any> {
return stack.toTypedArray()
}
}
/* Driver Code */
fun main() {
/* Инициализация стека */
val stack = ArrayStack()
/* Помещение элемента в стек */
stack.push(1)
stack.push(3)
stack.push(2)
stack.push(5)
stack.push(4)
println("Стек stack = ${stack.toArray().contentToString()}")
/* Доступ к верхнему элементу стека */
val peek = stack.peek()
println("Верхний элемент peek = $peek")
/* Извлечение элемента из стека */
val pop = stack.pop()
println("Извлеченный элемент pop = $pop, stack после извлечения = ${stack.toArray().contentToString()}")
/* Получение длины стека */
val size = stack.size()
println("Длина стека size = $size")
/* Проверка на пустоту */
val isEmpty = stack.isEmpty()
println("Пуст ли стек = $isEmpty")
}
@@ -0,0 +1,45 @@
/**
* File: deque.kt
* Created Time: 2024-01-25
* Author: curtishd (1023632660@qq.com)
*/
package chapter_stack_and_queue
import java.util.*
/* Driver Code */
fun main() {
/* Инициализация двусторонней очереди */
val deque = LinkedList<Int>()
deque.offerLast(3)
deque.offerLast(2)
deque.offerLast(5)
println("Двусторонняя очередь deque = $deque")
/* Доступ к элементу */
val peekFirst = deque.peekFirst()
println("Первый элемент peekFirst = $peekFirst")
val peekLast = deque.peekLast()
println("Последний элемент peekLast = $peekLast")
/* Добавление элемента в очередь */
deque.offerLast(4)
println("После добавления элемента 4 в хвост deque = $deque")
deque.offerFirst(1)
println("После добавления элемента 1 в голову deque = $deque")
/* Извлечение элемента из очереди */
val popLast = deque.pollLast()
println("Извлеченный из хвоста элемент = $popLast, deque после извлечения из хвоста = $deque")
val popFirst = deque.pollFirst()
println("Извлеченный из головы элемент = $popFirst, deque после извлечения из головы = $deque")
/* Получение длины двусторонней очереди */
val size = deque.size
println("Длина двусторонней очереди size = $size")
/* Проверка, пуста ли двусторонняя очередь */
val isEmpty = deque.isEmpty()
println("Пуста ли двусторонняя очередь = $isEmpty")
}
@@ -0,0 +1,163 @@
/**
* File: linkedlist_deque.kt
* Created Time: 2024-01-25
* Author: curtishd (1023632660@qq.com)
*/
package chapter_stack_and_queue
/* Узел двусвязного списка */
class ListNode(var _val: Int) {
// Значение узла
var next: ListNode? = null // Ссылка на узел-преемник
var prev: ListNode? = null // Ссылка на узел-предшественник
}
/* Двусторонняя очередь на основе двусвязного списка */
class LinkedListDeque {
private var front: ListNode? = null // Головной узел front
private var rear: ListNode? = null // Хвостовой узел rear
private var queSize: Int = 0 // Длина двусторонней очереди
/* Получение длины двусторонней очереди */
fun size(): Int {
return queSize
}
/* Проверка, пуста ли двусторонняя очередь */
fun isEmpty(): Boolean {
return size() == 0
}
/* Операция добавления в очередь */
fun push(num: Int, isFront: Boolean) {
val node = ListNode(num)
// Если связный список пуст, сделать так, чтобы и front, и rear указывали на node
if (isEmpty()) {
rear = node
front = rear
// Операция добавления в голову очереди
} else if (isFront) {
// Добавить node в голову списка
front?.prev = node
node.next = front
front = node // Обновить головной узел
// Операция добавления в хвост очереди
} else {
// Добавить node в хвост списка
rear?.next = node
node.prev = rear
rear = node // Обновить хвостовой узел
}
queSize++ // Обновить длину очереди
}
/* Добавление в голову очереди */
fun pushFirst(num: Int) {
push(num, true)
}
/* Добавление в хвост очереди */
fun pushLast(num: Int) {
push(num, false)
}
/* Операция извлечения из очереди */
fun pop(isFront: Boolean): Int {
if (isEmpty())
throw IndexOutOfBoundsException()
val _val: Int
// Операция извлечения из головы очереди
if (isFront) {
_val = front!!._val // Временно сохранить значение головного узла
// Удалить головной узел
val fNext = front!!.next
if (fNext != null) {
fNext.prev = null
front!!.next = null
}
front = fNext // Обновить головной узел
// Операция извлечения из хвоста очереди
} else {
_val = rear!!._val // Временно сохранить значение хвостового узла
// Удалить хвостовой узел
val rPrev = rear!!.prev
if (rPrev != null) {
rPrev.next = null
rear!!.prev = null
}
rear = rPrev // Обновить хвостовой узел
}
queSize-- // Обновить длину очереди
return _val
}
/* Извлечение из головы очереди */
fun popFirst(): Int {
return pop(true)
}
/* Извлечение из хвоста очереди */
fun popLast(): Int {
return pop(false)
}
/* Доступ к элементу в начале очереди */
fun peekFirst(): Int {
if (isEmpty()) throw IndexOutOfBoundsException()
return front!!._val
}
/* Доступ к элементу в конце очереди */
fun peekLast(): Int {
if (isEmpty()) throw IndexOutOfBoundsException()
return rear!!._val
}
/* Вернуть массив для вывода */
fun toArray(): IntArray {
var node = front
val res = IntArray(size())
for (i in res.indices) {
res[i] = node!!._val
node = node.next
}
return res
}
}
/* Driver Code */
fun main() {
/* Инициализация двусторонней очереди */
val deque = LinkedListDeque()
deque.pushLast(3)
deque.pushLast(2)
deque.pushLast(5)
println("Двусторонняя очередь deque = ${deque.toArray().contentToString()}")
/* Доступ к элементу */
val peekFirst = deque.peekFirst()
println("Первый элемент peekFirst = $peekFirst")
val peekLast = deque.peekLast()
println("Последний элемент peekLast = $peekLast")
/* Добавление элемента в очередь */
deque.pushLast(4)
println("После добавления элемента 4 в хвост deque = ${deque.toArray().contentToString()}")
deque.pushFirst(1)
println("После добавления элемента 1 в голову deque = ${deque.toArray().contentToString()}")
/* Извлечение элемента из очереди */
val popLast = deque.popLast()
println("Извлеченный из хвоста элемент = ${popLast}, deque после извлечения из хвоста = ${deque.toArray().contentToString()}")
val popFirst = deque.popFirst()
println("Извлеченный из головы элемент = ${popFirst}, deque после извлечения из головы = ${deque.toArray().contentToString()}")
/* Получение длины двусторонней очереди */
val size = deque.size()
println("Длина двусторонней очереди size = $size")
/* Проверка, пуста ли двусторонняя очередь */
val isEmpty = deque.isEmpty()
println("Пуста ли двусторонняя очередь = $isEmpty")
}
@@ -0,0 +1,98 @@
/**
* File: linkedlist_queue.kt
* Created Time: 2024-01-25
* Author: curtishd (1023632660@qq.com)
*/
package chapter_stack_and_queue
/* Очередь на основе связного списка */
class LinkedListQueue(
// Головной узел front, хвостовой узел rear
private var front: ListNode? = null,
private var rear: ListNode? = null,
private var queSize: Int = 0
) {
/* Получение длины очереди */
fun size(): Int {
return queSize
}
/* Проверка, пуста ли очередь */
fun isEmpty(): Boolean {
return size() == 0
}
/* Поместить в очередь */
fun push(num: Int) {
// Добавить num после хвостового узла
val node = ListNode(num)
// Если очередь пуста, сделать так, чтобы и head, и tail указывали на этот узел
if (front == null) {
front = node
rear = node
// Если очередь не пуста, добавить этот узел после хвостового узла
} else {
rear?.next = node
rear = node
}
queSize++
}
/* Извлечь из очереди */
fun pop(): Int {
val num = peek()
// Удалить головной узел
front = front?.next
queSize--
return num
}
/* Доступ к элементу в начале очереди */
fun peek(): Int {
if (isEmpty()) throw IndexOutOfBoundsException()
return front!!._val
}
/* Преобразовать связный список в Array и вернуть */
fun toArray(): IntArray {
var node = front
val res = IntArray(size())
for (i in res.indices) {
res[i] = node!!._val
node = node.next
}
return res
}
}
/* Driver Code */
fun main() {
/* Инициализация очереди */
val queue = LinkedListQueue()
/* Добавление элемента в очередь */
queue.push(1)
queue.push(3)
queue.push(2)
queue.push(5)
queue.push(4)
println("Очередь queue = ${queue.toArray().contentToString()}")
/* Доступ к элементу в начале очереди */
val peek = queue.peek()
println("Первый элемент peek = $peek")
/* Извлечение элемента из очереди */
val pop = queue.pop()
println("Извлеченный элемент pop = $pop, queue после извлечения = ${queue.toArray().contentToString()}")
/* Получение длины очереди */
val size = queue.size()
println("Длина очереди size = $size")
/* Проверка, пуста ли очередь */
val isEmpty = queue.isEmpty()
println("Пуста ли очередь = $isEmpty")
}
@@ -0,0 +1,87 @@
/**
* File: linkedlist_stack.kt
* Created Time: 2024-01-25
* Author: curtishd (1023632660@qq.com)
*/
package chapter_stack_and_queue
/* Стек на основе связного списка */
class LinkedListStack(
private var stackPeek: ListNode? = null, // Использовать головной узел как вершину стека
private var stkSize: Int = 0 // Длина стека
) {
/* Получение длины стека */
fun size(): Int {
return stkSize
}
/* Проверка, пуст ли стек */
fun isEmpty(): Boolean {
return size() == 0
}
/* Поместить в стек */
fun push(num: Int) {
val node = ListNode(num)
node.next = stackPeek
stackPeek = node
stkSize++
}
/* Извлечь из стека */
fun pop(): Int? {
val num = peek()
stackPeek = stackPeek?.next
stkSize--
return num
}
/* Доступ к верхнему элементу стека */
fun peek(): Int? {
if (isEmpty()) throw IndexOutOfBoundsException()
return stackPeek?._val
}
/* Преобразовать List в Array и вернуть */
fun toArray(): IntArray {
var node = stackPeek
val res = IntArray(size())
for (i in res.size - 1 downTo 0) {
res[i] = node?._val!!
node = node.next
}
return res
}
}
/* Driver Code */
fun main() {
/* Инициализация стека */
val stack = LinkedListStack()
/* Помещение элемента в стек */
stack.push(1)
stack.push(3)
stack.push(2)
stack.push(5)
stack.push(4)
println("Стек stack = ${stack.toArray().contentToString()}")
/* Доступ к верхнему элементу стека */
val peek = stack.peek()!!
println("Верхний элемент peek = $peek")
/* Извлечение элемента из стека */
val pop = stack.pop()!!
println("Извлеченный элемент pop = $pop, stack после извлечения = ${stack.toArray().contentToString()}")
/* Получение длины стека */
val size = stack.size()
println("Длина стека size = $size")
/* Проверка на пустоту */
val isEmpty = stack.isEmpty()
println("Пуст ли стек = $isEmpty")
}
@@ -0,0 +1,39 @@
/**
* File: queue.kt
* Created Time: 2024-01-25
* Author: curtishd (1023632660@qq.com)
*/
package chapter_stack_and_queue
import java.util.*
/* Driver Code */
fun main() {
/* Инициализация очереди */
val queue = LinkedList<Int>()
/* Добавление элемента в очередь */
queue.offer(1)
queue.offer(3)
queue.offer(2)
queue.offer(5)
queue.offer(4)
println("Очередь queue = $queue")
/* Доступ к элементу в начале очереди */
val peek = queue.peek()
println("Первый элемент peek = $peek")
/* Извлечение элемента из очереди */
val pop = queue.poll()
println("Извлеченный элемент pop = $pop, queue после извлечения = $queue")
/* Получение длины очереди */
val size = queue.size
println("Длина очереди size = $size")
/* Проверка, пуста ли очередь */
val isEmpty = queue.isEmpty()
println("Пуста ли очередь = $isEmpty")
}
@@ -0,0 +1,39 @@
/**
* File: stack.kt
* Created Time: 2024-01-25
* Author: curtishd (1023632660@qq.com)
*/
package chapter_stack_and_queue
import java.util.*
/* Driver Code */
fun main() {
/* Инициализация стека */
val stack = Stack<Int>()
/* Помещение элемента в стек */
stack.push(1)
stack.push(3)
stack.push(2)
stack.push(5)
stack.push(4)
println("Стек stack = $stack")
/* Доступ к верхнему элементу стека */
val peek = stack.peek()
println("Верхний элемент peek = $peek")
/* Извлечение элемента из стека */
val pop = stack.pop()
println("Извлеченный элемент pop = $pop, stack после извлечения = $stack")
/* Получение длины стека */
val size = stack.size
println("Длина стека size = $size")
/* Проверка на пустоту */
val isEmpty = stack.isEmpty()
println("Пуст ли стек = $isEmpty")
}