Составьте программу polynom.c
, вычисляющую значение полинома
и его производной в заданной точке
Программа должна считывать из стандартного потока ввода степень полинома
Для вычисления значения полинома нужно использовать схему Горнера:
Например, согласно схеме Горнера
Для вычисления значения производной полинома необходимо очевидным образом модифицировать схему Горнера.
Составьте программу mulmod.c
, вычисляющую выражение
Программа должна считывать из стандартного потока ввода числа
Основная сложность этой задачи заключается в том, что произведение
Решение этой задачи сводится к вычислению значения полинома по схеме Горнера.
Представим число
Здесь
Тогда
Преобразовав это выражение по схеме Горнера, получим
Учитывая, что для любых
мы имеем право при вычислении правой части нашей формулы поступать следующим
образом: если есть возможность того, что сумма двух слагаемых превзойдёт
Числа Фибоначчи — это последовательность натуральных чисел {$f_{i}$}, в которой
По теореме Цекендорфа любое положительное целое число может быть единственным образом представлено в виде суммы различных чисел Фибоначчи, не включающей двух подряд идущих чисел Фибоначчи.
Например, для числа
Чтобы разложить целое положительное число
- находим максимальное число Фибоначчи
$f\leq x$ ; - добавляем
$f$ в сумму Цекендорфа; - вычитаем
$f$ из $x$.
Напомним, что в позиционной системе счисления вес каждой цифры зависит от её позиции в записи числа. Соответственно, базисом позиционной системы счисления называется последовательность чисел, задающих вес каждого разряда. Например, для десятичной системы базисом является последовательность 1, 10, 100, 1000, 10000, 100000, и т.д.
Фибоначчиева система счисления — это позиционная система счисления с двумя
цифрами —
Для того чтобы гарантировать единственность записи числа в фибоначчиевой системе счисления, запись числа не должна содержать две подряд идущие единицы (теорема Цекендорфа).
Составьте программу fibsys.c
, выполняющую перевод целого числа
Программа должна считывать из стандартного потока ввода число
Пусть intersect.c
, вычисляющую пересечение множеств
Программа должна считывать из стандартного потока ввода размер множества
Использовать массивы для хранения множеств запрещается: каждое множество должно
быть представлено 32-разрядным целым числом таким, что если его
Даны два целочисленных массива размером permut.c
, определяющую, можно ли получить один массив перестановкой элементов
другого массива.
Программа должна считывать из стандартного потока ввода элементы обоих массивов,
а затем выводить в стандартный поток вывода слово «yes
», если массивы
совпадают с точностью до перестановки элементов, и «no
» — в противном случае.
Сортировать массивы запрещается.
Дан целочисленный массив, размер которого не превышает maxk.c
,
определяющую, какие
Программа должна считывать из стандартного потока ввода размер массива, его
элементы и число
В программе запрещается обращаться к одному и тому же элементу массива более двух раз, а также объявлять какие бы то ни было вспомогательные массивы.
Составьте программу primediv.c
, вычисляющую наибольший простой делитель
некоторого числа
Программа должна использовать решето Эратосфена для построения массива простых чисел.
Элемент двумерного массива называется седловым, если он одновременно наибольший в своей строке и наименьший в своём столбце.
Дан целочисленный двумерный массив, размер которого не превышает saddlepoint.c
, определяющую седловую точку в этом массиве.
Программа должна считывать из стандартного потока ввода количество строк
и столбцов двумерного массива и его элементы. Программа должна вывести
в стандартный поток координаты найденной седловой точки или слово «none
»,
если седловой точки не существует.
В программе запрещается обращаться к одному и тому же элементу массива дважды.
Составьте функцию revarray
, переставляющую элементы любого массива в обратном
порядке. Функция должна быть объявлена как
void revarray(void *base, size_t nel, size_t width)
{
...
}
Здесь параметр base
означает указатель на начало массива, nel
— количество
элементов в массиве, а width
— размер каждого элемента массива в байтах.
Примечание. Тип size_t
определён в заголовочных файлах <stddef.h>
,
<stdio.h>
, <stdlib.h>
, <string.h>
, <time.h>
и <wchar.h>
.
Составьте функцию maxarray
, возвращающую индекс максимального элемента
произвольного массива. Функция должна быть объявлена как
int maxarray(void *base, size_t nel, size_t width,
int (*compare)(void *a, void *b))
{
...
}
Здесь параметр base
означает указатель на начало массива, nel
— количество
элементов в массиве, width
— размер каждого элемента массива в байтах,
а compare
— указатель на функцию сравнения двух элементов, работающую
аналогично функции сравнения для библиотечной функции qsort
.
Примечание. Тип size_t
определён в заголовочных файлах <stddef.h>
,
<stdio.h>
, <stdlib.h>
, <string.h>
, <time.h>
и <wchar.h>
.
Составьте функцию binsearch
, выполняющую поиск заданного числа
в последовательности чисел, отсортированной по возрастанию, методом деления
пополам. Функция должна быть объявлена как
unsigned long binsearch(unsigned long nel, int (*compare)(unsigned long i))
{
...
}
Здесь параметр nel
задаёт количество элементов в последовательности,
а параметр compare
— указатель на функцию сравнения, которая принимает
параметр i
и и возвращает:
-
$-1$ , еслиi
-тое число в последовательности меньше искомого числа; -
$0$ , если они равны; -
$1$ , еслиi
-тое число больше искомого числа.
Функция binsearch
должна возвращать индекс найденного элемента или значение
nel
, если такого элемента не существует.
Элемент последовательности чисел, значение которого — не меньше значений его
непосредственных соседей, называется пиком. Очевидно, что непустая
последовательность размера
Составьте функцию peak
, возвращающую индекс любого пика в последовательности.
Функция должна быть объявлена как
unsigned long peak(unsigned long nel,
int (*less)(unsigned long i, unsigned long j))
{
...
}
Здесь параметр nel
задаёт количество элементов в последовательности,
а параметр less
— указатель на функцию сравнения, которая принимает два
параметра — i
и j
— и возвращает i
-тое число
в последовательности меньше j
-того числа, и $0$ — в противном случае.
Составьте функцию concat
, выполняющую конкатенацию произвольного количества
строк:
char *concat(char **s, int n)
{
...
}
Здесь s
— указатель на массив соединяемых строк, n
— количество строк
в массиве. Функция должна создавать в динамической памяти новую строку, размер
которой равен суммарному размеру всех соединяемых строк, записывать в неё
соединяемые строки друг за другом в том порядке, в котором они перечислены
в массиве, и возвращать указатель на новую строку.
Программа concat.c
, демонстрирующая работоспособность функции concat
,
должна считывать со стандартного потока ввода количество строк и сами
соединяемые строки и выводить в стандартный поток вывода результирующую строку.
В автотестах длины строк, подаваемых на стандартный ввод, не превышают concat()
могут иметь произвольную длину.
Составьте функцию wcount
, вычисляющую количество слов в строке. Слово — это
подстрока, не содержащая пробелов. Слова разделяются произвольным количеством
пробелов. Кроме того, строка может начинаться и заканчиваться произвольным
количеством пробелов. Объявление функции должно выглядеть как
int wcount(char *s)
{
...
}
Итоговую программу, содержащую как функцию wcount
, так и функцию main
,
демонстрирующую работоспособность функции wcount
, нужно назвать wcount.c
.
Строка должна считываться из стандартного потока ввода с помощью функции gets
или fgets
, минимальный размер буфера —
Примечание. Функция fgets
, в отличие от gets
, добавляет \n
в конец
прочитанной строки.
Строки Фибоначчи — это последовательность строк
Чтобы было понятнее, приведём первые пять строк Фибоначчи:
Составьте функцию fibstr
, возвращающую fibstr
должна быть объявлена как
char *fibstr(int n)
{
...
}
Функция fibstr
должна выделять в динамической памяти массив такого размера,
чтобы в него как раз поместилась fibstr
.
Составьте программу fibstr.c
, демонстрирующую работоспособность составленной
функции.
Составьте функцию strdiff
, выполняющую побитовое сравнение двух строк.
Функция должна быть объявлена как
int strdiff(char *a, char *b)
{
...
}
Если строки равны, функция должна возвращать
Например, строки aa и ai представлены следующими последовательностями битов (последовательности записаны справа налево, то есть младший бит — самый правый):
Эти строки совпадают до $11$ бита (биты нумеруются, начиная с $0$).
Составьте программу frame.c
, выполняющую рисование рамки вокруг текстовой
строки. Программа должна принимать в качестве аргументов командной строки
размеры рамки и значение строки.
Например, пусть программа вызвана как
./frame 6 20 Abracadabra
Тогда в стандартный поток вывода должно быть выведено
********************
* *
* Abracadabra *
* *
* *
********************
Текстовая строка должна быть отцентрирована как по горизонтали, так
и по вертикали. В случае, если длина строки не позволяет вписать строку в рамку
заданного размера, программа должна вместо рамки выводить сообщение Error
.
Если программа вызвана с неправильным количеством аргументов командной строки, необходимо вывести подсказку
Usage: frame <height> <width> <text>
Из-за ограничений системы автоматического тестирования код возврата программы
всегда должен быть равен 0
, даже при ошибочных данных.
Пусть в гипотетическом интерпретаторе языка Lisp элемент списка представлен
в памяти структурой Elem
, которая объявлена в заголовочном файле
elem.h
следующим образом:
#ifndef ELEM_H_INCLUDED
#define ELEM_H_INCLUDED
struct Elem {
/* «Тег», описывающий тип значения в «головe» списка */
enum {
INTEGER,
FLOAT,
LIST
} tag;
/* Само значение в «голове» списка */
union {
int i;
float f;
struct Elem *list;
} value;
/* Указатель на «хвост» списка */
struct Elem *tail;
};
#endif
Таким образом, в качестве полезной нагрузки в элементе списка может храниться
целое число, число с плавающей точкой или указатель на список. Причём тип
хранимого значения определяется полем tag
.
Кроме того, в элементе списка хранится указатель tail
на «хвост» списка.
Если элемент является последним в списке, этот указатель принимает значение
NULL
.
Составьте функцию searchlist
, выполняющую поиск элемента списка, содержащего
указанное целое число:
struct Elem *searchlist(struct Elem *list, int k)
{
...
}
Здесь параметр list
означает указатель на первый элемент списка, k
— искомое
целое число.
Функция searchlist
должна возвращать указатель на найденный элемент списка
или NULL
, если элемент, содержащий число k
, не найден.
Указание. Добавьте в файл с решением #include "elem.h"
(он есть в среде
тестирования) или целиком определение структуры struct Elem
, скопировав её
из условия задачи. Скачать файл: elem.h
.
Пусть дано множество из $n$ строк, где superstr.c
, вычисляющую длину кратчайшей строки, содержащей все эти строки
в качестве подстрок.
Программа должна считывать из стандартного потока ввода число
Пусть дана последовательность из $n$ неповторяющихся целых чисел, где
Составьте программу power2.c
, вычисляющую, сколько существует непустых
сочетаний чисел из последовательности таких, что сумма чисел в сочетании равна
степени числа
Программа должна считывать из стандартного потока ввода число
В классической сортировке пузырьком проход по сортируемой последовательности осуществляется всегда в одном направлении. Модифицируйте алгоритм сортировки пузырьком, чтобы в нём чередовались проходы по последовательности слева направо и справа налево.
Составьте функцию bubblesort
, осуществляющую двунаправленную пузырьковую
сортировку произвольной последовательности. Функция должна быть объявлена как
void bubblesort(unsigned long nel,
int (*compare)(unsigned long i, unsigned long j),
void (*swap)(unsigned long i, unsigned long j))
{
...
}
Параметры функции bubblesort
:
-
nel
— количество элементов в последовательности; -
compare
— указатель на функцию сравнения, которая возвращает$-1$ , если$i$ -й элемент меньше$j$ -го,$0$ — в случае, если$i$ -й элемент равен$j$ -му, и $1$ — в случае, если$i$ -й элемент больше$j$ -го; -
swap
— указатель на функцию обмена$i$ -го и $j$-го элементов последовательности.
В классической сортировке втавками для вставки элемента в отсортированную часть
последовательности выполняется сравнение элемента со всеми членами
отсортированной части до тех пор, пока для него не будет найдено место, то есть
переменная
Метод Шелла является модификацией сортировки вставками, в которой переменная
Составьте функцию shellsort
, выполняющую сортировку произвольной
последовательности методом Шелла. Функция shellsort
должна быть объявлена как
void shellsort(unsigned long nel,
int (*compare)(unsigned long i, unsigned long j),
void (*swap)(unsigned long i, unsigned long j))
{
...
}
Параметры функции shellsort
:
-
nel
— количество элементов в последовательности; -
compare
— указатель на функцию сравнения, которая возвращает$-1$ , если$i$ -й элемент меньше$j$ -го,$0$ — в случае, если$i$ -й элемент равен$j$ -му, и $1$ — в случае, если$i$ -й элемент больше$j$ -го; -
swap
— указатель на функцию обмена$i$ -то и $j$-го элементов последовательности.
Значения расстояния nel
.
Составьте функцию сsort
, выполняющую сортировку слов в предложении методом
подсчёта сравнений. Слова в предложении разделяются произвольным количеством
пробелов. Функция csort
должна быть объявлена следующим образом:
void csort(char *src, char *dest)
{
...
}
В качестве параметров функция csort
принимает указатель на исходное
предложение src
и указатель на пустой буфер dest
подходящего размера.
В результате работы функции в буфер dest
записывается новое предложение,
состоящее из слов, взятых из исходного предложения и отсортированных в порядке
возрастания их длин. При этом слова в новом предложении разделяются одним
пробелом.
Рассмотрим пример работы функции csort
. Пусть исходное предложение выглядит
как
qqq www t aa rrr bb x y zz
Тогда в выходной буфер должно быть записано предложение
t x y aa bb zz qqq www rrr
Итоговую программу, содержащую как функцию csort
, так и функцию main
,
демонстрирующую работоспособность функции csort
, нужно назвать csort.c
.
Программа должна считывать исходное предложение со стандартного потока ввода.
Минимальный размер буфера для ввода с консоли должен быть равен
\0
в конце строки.
Составьте функцию hsort
, выполняющую пирамидальную сортировку произвольного
массива. Объявление функции hsort
должно быть выполнено по аналогии
с функцией qsort
:
void hsort(void *base, size_t nel, size_t width,
int (*compare)(const void *a, const void *b))
{
...
}
В качестве параметров функция hsort
принимает указатель на начало массива
base
, количество элементов массива nel
, размер одного элемента width
и указатель на функцию сравнения compare
.
Замечание. Функция hsort
должна иметь тот же интерфейс, что и функция
qsort
. А функция qsort
предполагает, что функция compare
возвращает
отрицательное значение, когда compare
не обязательно возвращает
только -1
, 0
или +1
. См., например, здесь:
- https://en.cppreference.com/w/c/algorithm/qsort
- http://cplusplus.com/reference/cstdlib/qsort/ (внимание на пример!)
Итоговая программа heapsort.c
должна сортировать массив строк в порядке
возрастания количества букв a
в строке. Программа должна считывать
из стандартного потока ввода размер и элементы массива, и выводить
в стандартный поток вывода результат сортировки.
Минимальный размер буфера для ввода с консоли должен быть равен
\0
в конце строки.
Составьте программу mergesort.c
, осуществляющую сортировку массива целых
чисел в порядке возрастания модуля числа.
В программе должен быть реализован алгоритм сортировки слиянием, рекурсивную
функцию которого нужно модифицировать таким образом, чтобы для
последовательностей длиной меньше
Размер и элементы массива должны считываться программой из стандартного потока ввода. Результат сортировки должен быть выведен в стандартный поток вывода.
Составьте программу quicksort.c
, осуществляющую сортировку массива целых
чисел в порядке возрастания.
В программе должен быть реализован алгоритм быстрой сортировки, рекурсивную
функцию которого нужно модифицировать таким образом, чтобы, во-первых, для
последовательностей длиной меньше
Программа должна считывать со стандартного потока ввода размер массива
Составьте программу dsort.c
, осуществляющую сортировку латинских букв в строке
в алфавитном порядке (размер строки — до миллиона букв). В программе должен быть
реализован алгоритм сортировки распределением.
Например, если введена строка
encyclopedia
то программа должна выводить в стандартный поток вывода
accdeeilnopy
Строка вводится со стандартного потока ввода, причём известно, что она содержит только маленькие латинские буквы.
Составьте программу datesort.c
, осуществляющую сортировку последовательности
дат по возрастанию. В программе должен быть реализован алгоритм поразрядной
сортировки, адаптированный для случая, когда ключи представляются в системе
счисления с основаниями, зависящими от разряда.
В программе сортируемая последовательность должна быть представлена в виде
массива структур Date
:
struct Date {
int Day, Month, Year;
};
Поле Day
может принимать значения от $1$ до $31$, поле Month
— от $1$
до $12$, а поле Year
— от $1970$ до $2030$.
Последовательность дат считывается из стандартного потока ввода. При этом
в самом начале считывается общее количество дат, а каждая дата представляется
тройкой чисел «yyyy mm dd
».
Например, если введена последовательность
5
2005 01 12
1977 02 01
1994 03 01
2004 02 29
1977 08 01
то программа должна выводить в стандартный поток вывода
1977 02 01
1977 08 01
1994 03 01
2004 02 29
2005 01 12
Указание. Формат вывода для printf()
: "%04d %02d %02d"
.
Составьте программу radixsort.c
, осуществляющую сортировку последовательности
Программа должна считывать из стандартного потока ввода размер и элементы последовательности, и записывать в стандартный поток вывода элементы отсортированной последовательности.
Например, если на вход программы подано
5
1000 700 -5000 2038 0
то программа должна выводить в стандартный поток вывода
-5000 0 700 1000 2038
В программе сортируемая последовательность должна быть представлена в виде
массива объединений Int32
:
union Int32 {
int x;
unsigned char bytes[4];
};
Тем самым подразумевается, что целые числа представлены в системе счисления
по основанию bytes
объединения.
Составьте программу prefixes.c
, выполняющую поиск всех периодических префиксов
заданной строки
где
Программа получает строку
Например, пусть программа вызвана как
./prefixes aabaabaabaab
Тогда программа должна выводить в стандартный поток вывода
2 2
6 2
9 3
12 4
Уточнение. Если один и тот же префикс можно разложить на одинаковые
подстроки разными способами, то величина
12 2
Составьте программу kmpall.c
, осуществляющую поиск всех вхождений подстроки
Строки
Составьте программу pword.c
, определяющую, составлена ли строка
Программа получает строки yes
», если no
» — в противном случае.
Например, пусть программа вызвана как
./pword abracadabra abrabracada
Тогда программа должна выводить в стандартный поток вывода «yes
».
Составьте программу bmall.c
, осуществляющую поиск всех вхождений подстроки
Строки
Строки
Существует модификация алгоритма Бойера–Мура, в которой эвристика стоп-символа расширена следующим образом:
Расширенная эвристика стоп-символа. Встретив в строке
Пример. (
Таблица
Составьте программу extstop.c
, осуществляющую поиск первого вхождения
подстроки
Строки
Строки
Составьте программу rangemax.c
, выполняющую поиск максимального элемента
на различных интервалах последовательности целых чисел, которая время
от времени изменяется.
Формат входных данных. Первая строка, считываемая со стандартного потока
ввода, содержит размер последовательности
Третья строка содержит общее количество выполняемых операций
Операция либо имеет форму MAX
UPD
Формат результата работы программы. Для каждой операции MAX
вывести
в стандартный поток вывода значение максимального элемента указанной
подпоследовательности.
Гипердром — это строка, из букв которой можно составить палиндром. Другими словами, любая буква имеет чётное количество вхождений (возможно, нулевое) в гипердром чётной длины. Если же гипердром имеет нечётную длину, то ровно одна буква имеет нечётное количество вхождений.
Составьте программу rangehd.c
, определяющую, является ли указанная подстрока
строки гипердромом. Строка время от времени может изменяться.
Формат входных данных. Первая строчка, считываемая со стандартного потока
ввода, содержит строку размера
Вторая строчка содержит общее количество выполняемых операций
Операция либо имеет форму HD
UPD
Формат результата работы программы. Для каждой операции HD
вывести
в стандартный поток вывода слово «YES
», если подстрока является гипердромом,
или слово «NO
» в противном случае.
Напомним, что элемент последовательности чисел, значение которого — не меньше значений его непосредственных соседей, называется пиком.
Составьте программу rangepeak.c
, выполняющую вычисление количества пиков
на различных интервалах последовательности целых чисел, которая время
от времени изменяется.
Формат входных данных. Первая строка, считываемая со стандартного потока
ввода, содержит размер последовательности
Третья строка содержит общее количество выполняемых операций
Операция либо имеет форму PEAK
UPD
Формат результата работы программы. Для каждой операции PEAK
вывести
в стандартный поток вывода количество пиков в указанной подпоследовательности.
Составьте программу rangegcd.c
, вычисляющую наибольший общий делитель
на различных интервалах последовательности целых чисел.
Формат входных данных. Первая строка, считываемая со стандартного потока
ввода, содержит размер последовательности
Третья строка содержит общее количество запросов
Формат результата работы программы. Для каждого запроса вывести в стандартный поток вывода наименьший общий делитель указанной подпоследовательности.
Составьте программу maxprod.c
, выполняющую поиск отрезка последовательности
простых дробей
Формат входных данных. Первая строка, считываемая со стандартного потока
ввода, содержит размер последовательности
Формат результата работы программы. Программа должна вывести в стандартный
поток вывода два числа
Необходимо составить программу qsstack.c
, осуществляющую сортировку массива
целых чисел в порядке возрастания.
В программе должен быть реализован нерекурсивный алгоритм быстрой сортировки, использующий в своей работе стек заданий. Каждое задание описывает координаты подмассива, который нужно отсортировать, и представляет собой структуру
struct Task {
int low, high;
};
Программа должна считывать со стандартного потока ввода размер массива
Пусть стековая машина — это устройство для выполнения арифметических операций, использующее для хранения промежуточных результатов вычислений стек целых чисел. Подразумевается, что каждая операция берёт операнды из стека и оставляет на стеке результат.
Составьте программу stackmachine.c
, моделирующую работу стековой машины.
Формат входных данных. Первая строка, считываемая со стандартного потока
ввода, содержит общее количество выполняемых операций
Стековая машина должна обеспечивать выполнение следующих операций:
-
CONST
$x$ — кладёт в стек число$x$ $(-1,000,000,000 < x < 1,000,000,000)$ ; -
ADD
— сложение (снимает со стека два операнда$a$ и $b$ и кладёт в стек их сумму); -
SUB
— вычитание (снимает со стека операнд$a$ , затем снимает со стека операнд$b$ , кладёт в стек$a - b$ ); -
MUL
— умножение (снимает со стека два операнда$a$ и $b$ и кладёт в стек их произведение); -
DIV
— деление (снимает со стека операнд$a$ , затем снимает со стека операнд$b$ , кладёт в стек результат целочисленного деления$a$ на $b$); -
MAX
— максимум двух чисел (снимает со стека два операнда$a$ и $b$ и кладёт в стек $\max(a,b)$); -
MIN
— минимум двух чисел (снимает со стека два операнда$a$ и $b$ и кладёт в стек $\min(a,b)$); -
NEG
— меняет знак числа, находящегося на вершине стека; -
DUP
— кладёт в стек копию числа, находящегося на вершине стека; -
SWAP
— меняет местами два числа, находящиеся на вершине стека.
Можно считать, что последовательность операций составлена правильно, то есть перед вызовом каждой операции стек содержит нужное ей количество операндов, деление на ноль и переполнение не возникают, и, кроме того, в результате выполнения всех операций на стеке остаётся единственное число.
Формат результата работы программы. В стандартный поток вывода необходимо вывести число, оставшееся на вершине стека в результате выполнения последовательности операций.
Реализуйте операции InitQueue
, QueueEmpty
, Enqueue
и Dequeue
для
очереди целых чисел, представленной в виде кольцевого буфера. Начальный
размер буфера –
Составьте программу circbuf.c
, демонстрирующую работоспособность реализованных
операций.
Формат входных данных. Первая строка, считываемая со стандартного потока
ввода, содержит общее количество выполняемых операций
Операция либо имеет форму ENQ
DEQ
(удалить головной
элемент из очереди), либо форму EMPTY
(проверить пустоту очереди).
Можно считать, что последовательность операций составлена правильно, то есть
перед каждой операцией DEQ
очередь не пуста.
Формат результата работы программы. Для каждой операции DEQ
вывести
в стандартный поток вывода значение удаляемого головного элемента очереди.
Для каждой операции EMPTY
вывести в стандартный поток вывода «true
» или
«false
» в зависимости от того, пуста очередь или нет.
Реализуйте через двойной стек набор операций InitQueue
, Enqueue
, Dequeue
,
QueueEmpty
и Maximum
для работы с очередью целых чисел. Операция Maximum
возвращает максимальное целое число, в данный момент времени находящееся
в очереди. Операции Enqueue
, QueueEmpty
и Maximum
должны работать
за константное время, а операция Dequeue
— за амортизированное константное
время.
Составьте программу qmax.c
, демонстрирующую работоспособность реализованных
операций.
Формат входных данных. Первая строка, считываемая со стандартного потока
ввода, содержит общее количество выполняемых операций
Операция либо имеет форму ENQ
DEQ
(удалить головной
элемент из очереди), либо форму MAX
(показать текущее максимальное число),
либо форму EMPTY
(проверить пустоту очереди).
Можно считать, что последовательность операций составлена правильно, то есть
перед каждой операцией DEQ
очередь не пуста.
Формат результата работы программы. Для каждой операции DEQ
вывести
в стандартный поток вывода значение удаляемого головного элемента очереди. Для
каждой операции MAX
вывести в стандартный поток вывода текущее максимальное
число. Для каждой операции EMPTY
вывести в стандартный поток вывода «true
»
или «false
» в зависимости от того, пуста очередь или нет.
Подсказка. Как реализовать стек с операциями Push
, Pop
и Maximum
за константное время?
Составьте программу merge.c
, объединяющую
Формат входных данных программы должен быть такой: первая строка, считываемая
со стандартного потока ввода, содержит количество
Программа должна выводить в стандартный поток вывода отсортированную по возрастанию последовательность целых чисел, полученную путём слияния массивов. Целые числа должны разделяться пробелами или символами перевода строки.
Например, рассмотрим следующие входные данные:
4
3 5 1 2
10 12 20
15 16 17 19 25
20
11 12
Для этих данных программа должна вывести
10 11 12 12 15 16 17 19 20 20 25
Имеется вычислительный кластер, состоящий из $N$ однопроцессорных узлов.
На кластере нужно выполнить
Для выполнения каждой задачи задействуется один узел кластера, то есть задачи
невозможно распараллеливать. Кроме того, нельзя менять порядок выполнения задач:
если данные для задачи
Необходимо составить программу cluster.c
, вычисляющую минимальное время
в микросекундах от начала работы кластера, когда все задачи будут выполнены.
В программе нужно использовать очередь с приоритетами для хранения времен
окончания задач, запущенных на кластере.
Формат входных данных программы должен быть такой: первая строка, считываемая
со стандартного потока ввода, содержит количество
Программа должна вывести в стандартный поток вывода целое число, выражающее время в микросекундах, прошедшее от включения кластера до момента, когда все задачи будут выполнены.
Составьте программу listisort.c
, выполняющую сортировку двунаправленного
кольцевого списка целых чисел по возрастанию. В программе должен быть
реализован алгоритм сортировки вставками.
Элементы списка должны быть представлены структурой
struct Elem {
struct Elem *prev, *next;
int v;
};
Алгоритм сортировки вставками, адаптированный для списков, должен выполнять
не более
Программа должна считывать со стандартного потока ввода размер списка
Составьте программу listbsort.c
, выполняющую сортировку слов в предложении
в порядке возрастания их длин. Слова в предложении разделены одним или
несколькими пробелами. Программа должна формировать однонаправленный список
слов, а затем сортировать этот список пузырьком.
Функция bsort
, реализующая алгоритм сортировки, должна быть объявлена как
struct Elem *bsort(struct Elem *list)
{
...
}
Структура Elem
, указатели на которую фигурируют в объявлении функции bsort
,
должна представлять элемент однонаправленного списка, содержащего одно слово
из предложения:
struct Elem {
struct Elem *next;
char *word;
};
Исходное предложение подаётся в стандартный поток ввода программы. Программа должна вывести в стандартный поток вывода отсортированную последовательность слов, разделённых пробелами.
Максимальная длина исходной строки —
Операция Rank
:
Модифицируйте представление и реализацию списка с пропусками, чтобы операция
Rank
для него работала в среднем за время
Составьте программу ranklist.c
, демонстрирующую работоспособность
реализованной операции.
Формат входных данных. Первая строка, считываемая со стандартного потока
ввода, содержит общее количество выполняемых операций
Операция либо имеет форму INSERT
LOOKUP
DELETE
RANK
Можно считать, что последовательность операций составлена правильно.
Формат результата работы программы. Для каждой операции LOOKUP
вывести
в стандартный поток вывода строку, связанную с ключом RANK
вывести в стандартный поток вывода порядковый номер словарной пары
с ключом
Указание. Представление списка с пропусками нужно модифицировать следующим
образом: каждый элемент списка должен включать в себя массив целых чисел span
размера span
должен содержать расстояние от данного элемента до следующего
элемента на $i$-том уровне.
Операция SearchByRank
:
Модифицируйте представление и реализацию бинарного дерева поиска, чтобы
операция SearchByRank
для него работала за время
Составьте программу ranktree.c
, демонстрирующую работоспособность
реализованной операции.
Формат входных данных. Первая строка, считываемая со стандартного потока
ввода, содержит общее количество выполняемых операций
Операция либо имеет форму INSERT
LOOKUP
DELETE
SEARCH
Можно считать, что последовательность операций составлена правильно.
Формат результата работы программы. Для каждой операции LOOKUP
вывести
в стандартный поток вывода строку, связанную с ключом SEARCH
вывести в стандартный поток вывода строку, связанную с ключом, имеющим
порядковый номер
Указание. Представление бинарного дерева поиска нужно модифицировать
следующим образом: в каждую вершину нужно добавить поле count
, содержащее
размер поддерева с корнем в данной вершине. Размер поддерева — это количество
вершин в нём.
Пусть константа — это непустая последовательность десятичных цифр.
Пусть специальный знак — это один из следующих символов: +
, -
, *
, /
,
(
, )
.
Пусть идентификатор — это непустая последовательность латинских букв и десятичных цифр, начинающаяся с буквы.
Пусть лексема — это либо константа, либо специальный знак, либо идентификатор.
Известно, что в некоторой строке записаны лексемы и пробелы. Лексемы не обязательно разделены пробелами за исключением случая, когда непосредственно после константы идёт идентификатор. Назовём такую строку предложением.
Лексический анализ предложения заключается в выделении из него
последовательности записанных в нём лексем. При этом для каждой лексемы
вычисляется пара CONST
для констант, SPEC
для специальных знаков и IDENT
для идентификаторов),
а $value$ — значение лексемы.
Значение лексемы — это неотрицательное целое число, смысл которого зависит от типа лексемы.
Константу мы будем считать десятичной записью её значения.
Значением специального знака пусть будет его порядковый номер в списке +
,
-
, *
, /
, (
, )
(нумерация осуществляется, начиная с нуля).
Значение идентификатора определяется следующим образом: если выписать все идентификаторы в том порядке, в каком они входят в предложение, и оставить только первые вхождения каждого идентификатора, то значением идентификатора будет являться его порядковый номер в получившейся последовательности (нумерация осуществляется, начиная с нуля).
Например, если дано предложение
alpha + x1 (beta alpha) x1 y
то значением идентификатора alpha
является число x1
— число beta
— число y
— число
Составьте программу lexavl.c
, выполняющую лексический анализ предложения.
Формат входных данных. Первая строка, считываемая со стандартного потока
ввода, содержит размер предложения
Формат результата. Для каждой лексемы, выделенной из предложения, программа должна выводить в стандартный поток вывода её тип и значение.
Указание. В процессе лексического анализа необходимо использовать АВЛ-дерево, хранящее отображение идентификаторов в их значения.
Вместо выделения памяти под всю исходную строку и использования gets()
или
fgets()
, можно строку считывать посимвольно при помощи getchar()
, getc()
или fgetc()
.
Разреженный массив — это массив большого размера, большинство элементов которого равны нулю. Хранение разреженного массива в памяти целиком нецелесообразно или даже вовсе невозможно из-за его большого размера, поэтому разумным решением является хранение только ненулевых элементов за счёт некоторого снижения скорости операций над массивом.
Разреженный целочисленный массив можно представить как ассоциативный массив,
в котором и ключи, и значения являются целыми числами. При этом наличие
в ассоциативном массиве словарной пары
Будем считать, что в ассоциативном массиве, представляющем разреженный массив,
вообще нет словарных пар со значением ноль. Это означает, что если
Пусть
-
At
:$A \times \mathbb{N} \to \mathbb{Z}$ — возвращает$k$ -тый элемент массива, -
Assign
:$A \times \mathbb{N} \times \mathbb{Z} \to A$ — присваивает новое значение$k$ -тому элементу массива.
Пусть разреженный целочисленный массив представлен в виде хеш-таблицы
размера At
и Assign
. Составьте программу
disparray.c
, демонстрирующую работоспособность реализованных операций.
Формат входных данных. Первая строка, считываемая со стандартного потока
ввода, содержит общее количество выполняемых операций
Операция либо имеет форму ASSIGN
AT
Формат результата работы программы. Для каждой операции AT
вывести
в стандартный поток вывода значение элемента разреженного массива
с индексом
Указание. Пусть хеш-функция вычисляется как
Пусть дана последовательность из $n$ целых чисел, где zeroxor.c
, вычисляющую, сколько в последовательности
существует подпоследовательностей таких, что побитовое ИСКЛЮЧАЮЩЕЕ ИЛИ их
элементов равно
Например, в последовательности
-
$a[0 : 0 ] = {0}$ , -
$a[0 : 2 ] = {0,14,14}$ , -
$a[0 : 4 ] = {0,14,14,2,2 }$ , -
$a[0 : 5 ] = {0,14,14,2,2, 0}$ , -
$a[1 : 2 ] = {14,14}$ , -
$a[1 : 4 ] = {14,14,2,2}$ , -
$a[1 : 5 ] = {14,14,2,2,0 }$ , -
$a[3 : 4 ] = {2,2}$ , -
$a[3 : 5 ] = {2,2,0}$ , -
$a[5 : 5 ] = {0}$ .
Программа должна считывать из стандартного потока ввода число
Указание. Пусть побитовое ИСКЛЮЧАЮЩЕЕ ИЛИ подпоследовательностей
Пусть также мы знаем количество подпоследовательностей с правой границей
Реализуйте структуру данных, представляющую множество строк с операциями
Insert
(добавление строки в множество), Delete
(удаление строки
из множества) и Prefix
(подсчёт количества строк множества, имеющих указанных
префикс). Операции Insert
и Delete
должны работать за время Prefix
— за время
Составьте программу ptrie.c
, демонстрирующую работоспособность реализованных
операций.
Формат входных данных. Первая строка, считываемая со стандартного потока
ввода, содержит общее количество выполняемых операций
Операция либо имеет форму INSERT
DELETE
PREFIX
Отметим, что аргументы операций — это строки, составленные из маленьких латинских букв.
Кроме того, допустим вызов операции INSERT
для строки, уже присутствующей
в множестве.
Формат результата работы программы. Для каждой операции PREFIX
вывести
в стандартный поток вывода количество строк в множестве, имеющих указанный
префикс.