
- •Какие типы данных Вы знаете?
- •Как узнать размер типа?
- •Что такое модель памяти? Какие модели памяти Вы знаете?
- •Назовите размеры стандартных типов в используемой Вами модели памяти.
- •Что такое оператор typedef?
- •Для чего предназначена директива препроцессора #define?
- •Что такое сигнатура функции?
- •Что означает директива #include?
- •Что такое #if, #ifdef, #endif? Приведите пример применения.
- •Как можно выделить память?
- •Как устроен односвязный список?
- •Что такое стек? Как он устроен, какие операции в нем есть?
- •Что такое очередь? Как она устроена? Какие операции в ней есть?
- •Что такое куча (пирамида, Heap)?
- •Какова стоимость операций с кучей?
- •Как устроена очередь с приоритетами?
Как можно выделить память?
Статическое выделение памяти: пространство для объектов создаётся в области хранения данных кода программы в момент компиляции; время жизни таких объектов совпадает со временем жизни этого кода. static int arr[5];
Автоматическое выделение памяти: объекты можно временно хранить в стеке; эта память затем автоматически освобождается и может быть использована снова, после того, как программа выходит из блока, использующего её. int arr[5]; //в теле функции/метода
Динамическое выделение памяти: блоки памяти нужного размера могут запрашиваться во время выполнения программы с помощью библиотечных функций malloc, realloc и free из области памяти, называемой кучей. Эти блоки освобождаются и могут быть использованы снова после вызова для них функции free. int *arr = new int[5];
_______________________________________________________________________________
Как можно освободить память?
С помощью free(delete).
Как проверить, что память выделилась?
Пример: … int *buf;
buf = NULL;
buf = (int*)malloc(n*sizeof(int));
if (buf == NULL)
…
malloc возвращает пустой указатель на выделенное пространство или NULL, если недостаточно доступной памяти.
_______________________________________________________________________________
Как создать массив на стеке? Любой ли массив можно создать на стеке?
Int arr[10];
Создали массив из 10 целочисленных элементов.
Размер массива ограничивается размером стека.
________________________________________________________________________________
Что такое "выделение памяти в куче"?
Ку́ча — структура данных, с помощью которой реализована динамически распределяемая память приложения. Память в куче используется для размещения объектов, динамически созданных программой.
В любой момент времени существования кучи вся память, на которой работает куча, разделена на занятую и свободную. Занятая память использована под размещение объектов, уже созданных и ещё не освобождённых к этому моменту времени. Из объёма свободной памяти можно выделять память под новые объекты.
Int* p = new int[s]; - выделение памяти в куче Delete[] p; - удаление данных из кучи
______________________________________________________________________________
Как получить значение, на которое указывает указатель? Как называется эта операция?
Получить само значение переменной, на который указывает указатель, можно только выполнив операцию разыменовывания *.
int n = 1;
int *pn = 0;
pn = &n;
cout << *pn;
______________________________________________________________________________
Какой тип получается при взятии адреса переменной?
&a - получение указателя (взятие адреса) тип - *тип_переменной_а (указатель на тип переменной а)
_______________________________________________________________________________
Напишите функцию swap, меняющую значения двух переменных.
Void swap (int &a, int &b) { int t=a; a=b; b=t; }
Что такое передача аргументов по ссылке и по значению?
Если мы передаем переменную по значению, то в функции используется копия этой самой переменной. Для передачи по значению пишем просто void f (int a)
Если мы передаем переменную по ссылке, то в функции мы работаем с самой переменной. Для передачи по ссылке пишем void g (int& a)
______________________________________________________________________________
Ввод-вывод¶
Какие функции для форматированного ввода из файла Вы знаете?
FILE *f; f=fopen(f"file.txt", "r"); fscanf(f, “%d”, &i); fclose(f);
_______________________________________________________________________________
Какие функции для форматированного вывода в файл Вы знаете?
FILE *f; f=fopen("file.txt", "w"); fprintf(f, “%d”, i); fclose(f);
_______________________________________________________________________________
Какие функции для форматированного чтения из стандартного потока ввода Вы знаете?
Считать из стандартного потока ввода целочисленную переменную i: C: scanf("%d", &i); C++: cin>>i;
_______________________________________________________________________________
Какие функции для форматированного вывода в стандартный поток вывода Вы знаете?
Вывести в стандартный поток вывода целочисленную переменную i: C: printf("%d", i); C++: cout<<i;
_______________________________________________________________________________
Как прочитать один символ из стандартного потока ввода?
char a=getchar(); char b=cin.get();
_______________________________________________________________________________
Как открыть файл для записи?
f=fopen("file.txt", "w");
_______________________________________________________________________________
Как закрыть файл после завершения записи?
fclose(f);
Как считать строку?
Сhar sym = getchar(); char str[1000]; int len = 0; for (int i=0; sym!= ‘ ‘; i++, len++) {str[i]=sym; sym=getchar();}
Как вывести строку?
for (int i = 0; i<len; i++) printf(“%c”, str[i]); или str[len] = 0; printf(“%s”, str);
_______________________________________________________________________________
Общее по алгоритмам¶
Какие нотации используют для обозначения сложности алгоритмов?
T(n) – время работы алгоритма, тогда
f(n)=Θ(g(n)) означает, что найдутся такие константы c1>0 и с2>0 и n0, что 0<=c1g(n)<=f(n)<=c2g(n) для всех n>=n0
f(n)=O(g(n)) означает, что найдется такая константа с>0 и n0, что 0<=f(n)<=cg(n) для всех n>=n0
f(n)=Ω(g(n)) означает, что найдется такая константа с>0 и n0, что 0<=cg(n)<=f(n) для всех n>=n0
Если
к тому же
при
n
,
тогда
f(n)=о(g(n)) означает, что для всякого ε>0 найдется такое n0, что 0<=f(n)<=εg(n) при всех n>=n0
f(n)=ω(g(n)) означает, что для всякого с>0 найдется такое n0, что 0<=cg(n)<=f(n) при всех n>=n0
_______________________________________________________________________________
Затраты каких ресурсов обычно меряют при оценке сложности?
Алгоритмы оцениваются по скорости выполнения и эффективности использования памяти
_______________________________________________________________________________
Может ли алгоритм со сложностью O(n2) работать в практической задаче быстрее, чем алгоритм со сложностью O(n lоgn)?
Может. Пример: быстрая сортировка (nlogn) и сортировка пузырьком (n2) при отсортированном массиве
_______________________________________________________________________________
Что такое рекурсия?
В программировании рекурсия — вызов функции (процедуры) из неё же самой.
_______________________________________________________________________________
Какую опасность несет рекурсия?
Наиболее очевидная опасность рекурсии заключается в бесконечной рекурсии.
Другая опасность рекурсии заключается в потерях памяти. При каждом вызове подпрограммы, система выделяет память для локальных переменных новой процедуры.
_______________________________________________________________________________
Покажите на примере, как можно избавиться от рекурсии.
n-ое число Фиббоначи можно вычислять как рекурсивным методом (с помощью рекурсии подсчитывая предыдщее число), а можно обычным циклом, считая числа Фиббоначи, начиная с первого.
_______________________________________________________________________________
Оцените сложность алгоритма поиска простых чисел.
При простом переборе делителей O(n sqrt(n) )
Примените основную теорему об оценках для оценки сложности сортировки слиянием.
T(n) = 2*T(n/2) + θ(n) Данная формула означает, что чтобы отсортировать массив из n элементов, нужно согласно алгоритму отсортировать две его половины(2*Т(n/2)) и слить в один массив за (θ(n)). Из основной теоремы об оценках получаем, что a=2, b=2, n^(log(b)a)=n^(log(2)2)=n=θ(n) и f(n)=θ(n). Подходит случай 2 теоремы об оценках, значит T(n)=θ(n*logn).
Примените основную теорему об оценках для оценки сложности быстрой сортировки .
Для лучшего случая, когда каждый раз массив делится на две равные части, доказательство аналогично пункту 8, худший и средний случай смотри в Кормене с.154.
Сортировки¶
В чем заключается задача сортировки?
Задача сортировки - упорядочивание элементов массива по неубыванию (или какому-то иному признаку)
_______________________________________________________________________________
Какова наименьшая сложность алгоритма сортировки?
Сортировка сравнениями не может работать быстрее чем O (n log n)
_______________________________________________________________________________
Какова сложность алгоритма сортировки пузырьком?
O(n2)
_______________________________________________________________________________
Какова сложность алгоритма сортировки пузырьком в лучшем случае?
O (n) В том случае, когда массив уже отсортирован
_______________________________________________________________________________
Какова сложность алгоритма сортировки Шелла?
Зависит от последовательности, которая используется в сортировке. В среднем O(n3/2) Последовательности и их сложность: Шелла: d1=N/2 di=di-1/2 dk=1 O(c n2) Хиббард: все (2i-1)/2 <= n/2 O(n3/2) Пратт: все 2i*3j<=n/2 O(n (log n)2 )
_______________________________________________________________________________
Какова сложность алгоритма сортировки вставками?
Худший и средний случаи O(n2), лучший O(n)
_______________________________________________________________________________
Какова сложность алгоритма быстрой сортировки?
O(n log n) в среднем и лучшем, O(n2) в худшем случае
Какие оптимизации быстрой сортировки Вы знаете?
При выборе опорного элемента из данного диапазона случайным образом худший случай становится очень маловероятным и ожидаемое время выполнения алгоритма сортировки — O(n log n).
Выбирать опорным элементом средний из трех (первого, среднего и последнего элементов). Такой выбор также направлен против худшего случая.
Во избежание достижения опасной глубины рекурсии в худшем случае (или при приближении к нему) возможна модификация алгоритма, устраняющая одну ветвь рекурсии: вместо того, чтобы после разделения массива вызывать рекурсивно процедуру разделения для обоих найденных подмассивов, рекурсивный вызов делается только для меньшего подмассива, а больший обрабатывается в цикле в пределах этого же вызова процедуры. С точки зрения эффективности в среднем случае разницы практически нет: накладные расходы на дополнительный рекурсивный вызов и на организацию сравнения длин подмассивов и цикла — примерно одного порядка. Зато глубина рекурсии ни при каких обстоятельствах не превысит log2n, а в худшем случае вырожденного разделения она вообще будет не более 2 — вся обработка пройдёт в цикле первого уровня рекурсии.
Разбивать массив не на две, а на три части(меньше опорного элемента, равные опорному элементу, больше опорного элемента)
Из-за рекурсии и других "накладных расходов" Quicksort может оказаться не столь уж быстрой для коротких массивов. Поэтому, если в массиве меньше CUTOFF элементов (константа зависит от реализации, обычно равна от 3 до 40), вызывается сортировка вставками. Увеличение скорости может составлять до 15%.
_______________________________________________________________________________
Какова сложность пирамидальной сортировки?
Во всех случаях O(n log n)
_______________________________________________________________________________
Какова сложность сортировки слиянием?
Во всех случаях θ(n log n)
_______________________________________________________________________________
Какова сложность поразрядной сортировки?
Во всех случаях O(dn+dk), где d – количество разрядов, k – основание системы счисления.
_______________________________________________________________________________
Что такое задача выбора (k-я порядковая статистика)? Какова ее сложность?
k-ой порядковой статистикой набора элементов линейно упорядоченного множества называется такой его элемент, который является k-ым элементом набора в порядке сортировки.
В среднем случае работает за O(n), в худшем O(n n), в лучшем случае O(1).
Какова сложность алгоритма бинарного поиска?
В среднем и худшем O(log n), в лучшем O(1)
_______________________________________________________________________________
Можно ли применить алгоритм бинарного поиска к списку?
Нельзя, т.к. в списке каждый элемент ссылки только на последующий элемент или на соседние элементы.
_______________________________________________________________________________
Структуры данных¶
Что такое структура?
Структура — конструкция программирования, позволяющая содержать в себе набор переменных различных типов, совокупность нескольких переменных, часто различных типов, сгруппированных под единым именем для удобства обращения.
_______________________________________________________________________________
Как выделить массив структур?
struct key
{
char sym;
int num_in_alphabet;
};
key mass[1000];
или
key* m = NULL;
m = (key*)malloc(26*sizeof(key));
Что такое список?
динамический список представляет из себя некоторое количество компонентов (узлов), содержащих непосредственно информационную часть (число, строка или более сложные типы данных), а также ссылку на следующий компонент (возможно, что узел содержит 2 ссылки: на следующий и на предыдущий, в таком случае, список называется двусвязным).
_______________________________________________________________________________