Дорога длинная и длинная, и я буду искать вдоль и поперек. —— Цюй Юань
Оглавление
1. Что такое структура данных?
3. Упражнения на временную сложность
1. Что такое структура данных?
Структура данных — это набор и обработка элементов данных, которые имеют одно или несколько конкретных отношений друг с другом.
Это относится к взаимосвязям между элементами данных, то есть к организации данных. Эта организационная форма является логической структурой данных.
Логика данных обычно имеет следующие четыре основные структуры:
1. Коллективные учреждения
2. Линейная структура
3. Древовидная структура
4. Структура графика
В процессе фактической обработки данных компьютером мы должны учитывать, как данные должны храниться, чтобы они могли отражать взаимосвязь между данными.
Способ хранения данных в компьютере является структурой хранения данных . Например, последовательный список, связанный список и т. д., которые будут изучены позже .
Кроме того, в процессе обработки данных также будут происходить такие операции , как удаление данных, вставка и поиск , поэтому следует рассмотреть и способ обработки данных, то есть алгоритм .
2. Что такое алгоритм?
Алгоритм (алгоритм) относится к точному и полному описанию схемы решения проблемы, которая представляет собой серию четких инструкций по решению проблемы.Алгоритм представляет собой механизм стратегии для систематического описания решения проблемы. То есть требуемый результат может быть получен в течение ограниченного времени для определенного стандартного ввода .
Подобно пузырьковой сортировке, поиску числа, проверке дубликатов и т. д. — все это алгоритмы.
Особенности алгоритма:
Конечность: алгоритм должен иметь возможность завершаться после выполнения конечного числа шагов.
Точность: каждый шаг алгоритма должен иметь точное определение.
Входы: Алгоритм имеет 0 или более входов для описания исходной ситуации операнда.
Выходной элемент: Алгоритм имеет один или несколько выходных данных для отражения результата обработки входных данных, а алгоритм без выходных данных не имеет смысла.
Выполнимость: любой вычислительный шаг, выполняемый в алгоритме, можно разбить на основные выполняемые рабочие шаги.
1. Сложность алгоритма
После того, как алгоритм скомпилирован в исполняемую программу, ему необходимо потреблять временные ресурсы и ресурсы пространства (памяти) при работе. Следовательно, чтобы измерить качество алгоритма, его обычно измеряют по двум измерениям времени и пространства, то есть по временной и пространственной сложности.
Временная сложность в основном измеряет скорость работы алгоритма, а пространственная сложность в основном измеряет дополнительное пространство, необходимое для работы алгоритма. В первые дни развития компьютеров у компьютеров было очень мало места для хранения данных . Поэтому меня очень беспокоит космическая сложность. Однако с быстрым развитием компьютерной индустрии емкость компьютеров достигла очень высокого уровня. Таким образом, нам больше не нужно уделять особое внимание пространственной сложности алгоритма.
2. Временная сложность
Определение временной сложности. В информатике временная сложность алгоритма — это функция (математическая функция) , которая количественно описывает время выполнения этого алгоритма. Теоретически время, необходимое для выполнения алгоритма, невозможно рассчитать, узнать его можно только в том случае, если вы поместите свою программу на машину и запустите ее. Но нужно ли тестировать каждый алгоритм на компьютере?Да, мы можем протестировать все алгоритмы на компьютере, но это очень хлопотно, поэтому у нас есть метод анализа временной сложности. Время, затрачиваемое алгоритмом, пропорционально количеству выполнений операторов в нем , а количество выполнений основных операций в алгоритме есть временная сложность алгоритма .
Резюме: Алгоритм — это не количество времени выполнения, потому что, когда вы запускаете код, скорость времени также связана с конфигурацией вашего компьютера и скоростью сети в это время. Так что просто найдите количество запусков алгоритма. То есть математическое выражение между некоторым базовым предложением и размером задачи N состоит в вычислении временной сложности алгоритма.
Пример: подсчитайте, сколько раз было выполнено выражение count++ в Fun1?
void Func1(int N)
{
int count = 0;
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
count++;
}
}
for (int k = 0; k < 2 * N; k++)
{
count++;
}
int M = 10;
while (M--)
{
count++;
}
printf("%dn", count);
}
Общее количество петель выше: выражение математической функции F(N)=N^2+2*N+10.
Временная сложность F(N)=N^2+2*N+10.
Когда N принимает разные значения:
- N = 10 F(N) = 130
- N = 1000 F(N) = 1002010
- N = 100000 F(N) = 10000200010
Здесь мы видим, что по мере постепенного увеличения N 2*N+10 в F(N)=N^2+ 2*N+10 оказывает все меньшее и меньшее влияние на значение всей функции. Временная сложность все ближе и ближе к N^2, можно сказать, что N^2 — это временная сложность этого алгоритма.
Для сложности времени мы используем асимптотическую нотацию большого 0:
нотация большого 0 (нотация Big 0) : это математический символ, используемый для описания асимптотического поведения функций.
Вывод метода Big 0:
1. Замените все аддитивные константы во время выполнения константой 1 . 2. В модифицированной функции времени работы сохраняется только член высшего порядка . 3. Если элемент наивысшего порядка существует и не равен 1 , удалите константу, умноженную на этот элемент . Полученный результат порядка 0.
После использования асимптотического представления большого 0 временная сложность Func1 составляет: O (N ^ 2).
Из вышеизложенного мы обнаружим, что прогрессивное представление большого 0 удаляет те элементы, которые мало влияют на результат, и кратко и ясно выражает количество выполнений. Кроме того, существуют лучшие, средние и худшие временные сложности некоторых алгоритмов :
Наихудший случай: максимальное количество запусков для любого размера входных данных (верхняя граница)
Средний случай: ожидаемое количество запусков для любого размера входных данных
Наилучший случай: минимальное количество запусков для любого размера входных данных (нижняя граница)
Например: Поиск данных x в массиве длины N
Лучший случай: 1 найти
Наихудший случай: N найти
Средний случай: N/2 найти
На практике общий случай фокусируется на наихудших условиях работы алгоритма , поэтому время сложность поиска данных в массиве равна 0(N) .
3. Упражнения на временную сложность
1. Какова временная сложность Func2?
void Fun2(int N)
{
int count = 0;
for (int k = 0; k < 2 * N; k++)
{
count++;
}
int M = 10;
while (M--)
{
count++;
}
printf("%d\n", count);
}
Точно F(N)=2*N+10.
Поскольку N продолжает увеличиваться, размер F(N) не имеет ничего общего с 10, поэтому при выражении временной сложности 10 нужно убрать, а согласно третьему пункту вывода метода большого 0-го порядка: 3. Если член высшего порядка существует и не равен 1 , константа, умноженная на этот член, удаляется . Полученный результат порядка 0. Так что 2 в 2*N тоже можно убрать.
Следовательно, временная сложность Func2 равна O(N).
2. Какова временная сложность вычисления Func3?
void Func3(int N, int M)
{
int count = 0;
for (int k = 0; k < M; k++)
{
count++;
}
for (int k = 0; k < N; k++)
{
count++;
}
printf("%d\n", count);
}
Очевидно, что между M и N нет очевидной связи, поэтому временная сложность равна O(N+M).
1. Если N намного больше, чем M, временная сложность равна O(N).
2. Если M намного больше, чем N, временная сложность равна O(M).
3. Если M и N примерно одного размера, временная сложность равна O(N) или O(M).
3. Рассчитать временную сложность strchr?
Функция функции strchr состоит в том, чтобы найти указанный символ в строке, и если символ найден, она возвращает адрес, по которому появляется первый символ. Если после поиска в строке символ не найден, возвращается нулевой указатель.
#include<string.h>//NULL空指针需要的头文件
#include<assert.h>//assert必须要的头文件
char* strchr(const char* str, int character)
{ //字符的ASCll值就是数子,所以这里字符的数据类型可以用int
assert(str);
while (*str)
{
if (*str == character)
return str;
else
str++;
}
return NULL;
}
При вычислении временной сложности мы все рассчитываем в худшем случае , поэтому временная сложность алгоритма strchr составляет O(N).
3. Рассчитать временную сложность пузырьковой сортировки?
void Bulllesort(int *arr,int N)
{
assert(arr);
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N - i; j++)
{
if (arr[j] > arr[j + 1]) {
int ret = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = ret;
}
}
}
Здесь видно, что при первом входе в пузырьковую сортировку массив нужно поменять местами 9 раз, при втором входе в пузырьковую сортировку массив нужно поменять местами 8 раз и так далее. По сути, это арифметическая прогрессия. F(N)=N(1+N)/2, поэтому временная сложность равна O(N^2).
4. Рассчитать временную сложность бинарного поиска?
int Binarysearch(int nums[], int size, int target)
{
int left = 0;
int right = size - 1;
while (left <= right) {
int middle = left + ((right - left) / 2);
if (nums[middle] > target)
{
right = middle - 1;
}
else if (nums[middle] < target)
{
left = middle + 1;
}
else {
return middle;
}
}
}
Мы вычисляем временную сложность в худшем случае, В бинарном поиске худший случай состоит в том, что искомое число находится ровно посередине. То есть 2 ^ x = N, x - количество поисков.В математике log - это логарифм с основанием 2, но его нелегко набирать на клавиатуре, поэтому он упрощается до log2, поэтому временная сложность двоичного поиска Это O (log2).
4. Пространственная сложность
Пространственная сложность также является выражением математической функции, которая является мерой временного объема памяти, занимаемого алгоритмом во время работы.
Пространственная сложность — это не то, сколько байт занимает программа , потому что это не очень значимо. Таким образом, пространственная сложность подсчитывает количество переменных . Правила расчета пространственной сложности в основном аналогичны практической сложности, также используется асимптотическое представление большого 0.
Примечание. Пространство стека (параметры хранения, локальные переменные, некоторая информация о регистрах и т. д.), необходимое функции во время выполнения, определяется во время компиляции, поэтому сложность пространства в основном определяется дополнительным пространством, явно запрашиваемым функцией во время выполнения.
void Bulllesort(int *arr,int N)
{
assert(arr);
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N - i; j++)
{
if (arr[j] > arr[j + 1]) {
int ret = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = ret;
}
}
}
Как и в случае с этой пузырьковой сортировкой, в дополнение к параметрам в функции определены две дополнительные переменные i и j , поэтому пространственная сложность равна O(1).
В настоящее время объем памяти компьютеров относительно велик, и объемная сложность не имеет большого значения.
Общие сравнения сложности:
Это не легко создать, я надеюсь, что каждый может поставить лайк, спасибо.