, Если алгоритм имеет О (g (n)), это означает, что время выполнения алгоритма как n (входной размер) становится больше, пропорционально g (n).
, Если алгоритм имеет O (g (n)), это означает, что время выполнения алгоритма как n становится больше, самое большее пропорциональны g (n).
Обычно, даже когда люди говорят о O (g (n)) они на самом деле имеют в виду О (g (n)), но технически, существует различие.
O (n) представляет верхнюю границу. О (n) означает трудный связанный. О© (n) представляет нижнюю границу.
f (x) = О (g (x)) эквивалентность f (x) = O (g (x)) и f (x) = О© (g (x))
В основном, когда мы говорим, что алгоритм имеет O (n), это также O (n 2 глоток>), O (n 1000000 глоток>), O (2 n глоток>)... но О (n) алгоритм не О (n 2 глоток>).
На самом деле, с тех пор f (n) = О (g (n)) средства для достаточно больших значений n, f (n) могут быть связаны в c1 г (n) и c2 г (n) для некоторых значений c1 и c2, т.е. темп роста f асимптотически равен g: g может быть нижней границей и и верхняя граница f. Это непосредственно подразумевает, что f может быть нижней границей и верхней границей g также. Следовательно,
f (x) = О (g (x)) эквивалентность g (x) = О (f (x))
Точно так же для показа f (n) = О (g (n)) достаточно показать, что g является верхней границей f (т.е. f (n) = O (g (n))), и f является нижней границей g (т.е. f (n) = О© (g (n)), который является той же самой вещью как g (n) = O (f (n))). Кратко,
f (x) = О (g (x)) эквивалентность f (x) = O (g (x)) и g (x) = O (f (x))
существует также, мало-о, и мало-омега (ω
) нотации, представляющие свободные верхние и свободные нижние границы функции.
Для суммирования:
f(x) = O(g(x))
(большой об) означает, что темп ростаf(x)
асимптотически меньше чем или равен [1 118] к темпу ростаg(x)
.
f(x) = Ω(g(x))
(большая омега) означает, что темп ростаf(x)
асимптотически больше, чем или равный [1 119] темп ростаg(x)
f(x) = o(g(x))
(мало-о), средства, что темп ростаf(x)
асимптотически меньше чем [1 120] темп ростаg(x)
.
f(x) = ω(g(x))
(мало-омега) означает, что темп роста [1 111] асимптотически больше, чем [1 121], темп роста [1 112]
f(x) = Θ(g(x))
(тета) означает, что темп роста [1 114] асимптотически равен [1 122] темп роста [1 115]
Для более детального обсуждения, Вы можете читать определение на Википедию или консультироваться с классическим учебником как Введение в Алгоритмы Cormen и др.
extern «C» делает имена неискаженными.
Используется, когда:
Нам нужно использовать некоторую библиотеку C в C ++
extern «C» int foo (int) ;
Нам нужно экспортировать некоторый код C ++ в C
extern «C» int foo (int) {something; }
Нам нужна возможность разрешать символы в разделяемой библиотеке - поэтому нам нужно избавиться от искажения
extern "C" int foo (int) {something; }
///
typedef int (* foo_type) (интервал);
foo_type f = (foo_type) dlsym (дескриптор, "foo")
Одно из мест, где extern "C" имеет смысл, - это когда вы связываетесь с библиотекой, которая была скомпилирована как код C.
extern "C" {
#include "c_only_header.h"
}
В противном случае вы можете получить ошибки компоновщика, потому что библиотека содержит функции с C-компоновкой (_myfunc), но компилятор C ++, который обработал заголовок библиотеки как код C ++, сгенерировал имена символов C ++ для функций (" _myfunc @ XAZZYE"- это называется искажением и отличается для каждого компилятора).
Другое место, где используется extern" C ", - это гарантия связывания C даже для функций, написанных на C ++, например.
extern "C" void __stdcall PrintHello() {
cout << "Hello World" << endl;
}
Такую функцию можно экспортировать в DLL и затем будет вызываться из другого языка программирования, потому что компиляция не будет искажать его имя. Если вы добавили еще одну перегрузку той же функции, например
extern "C" void __stdcall PrintHello() {
cout << "Hello World" << endl;
}
extern "C" void __stdcall PrintHello(const char *name) {
cout << "Hello, " << name << endl;
}
Большинство компиляторов перехватили бы это и, таким образом, предотвратили бы использование перегрузок функций в вашем DLL-общедоступные функции.