c1 int x; c2 int i; c3 int n; c4 x = 5; c5 scanf("%d", &n); n*c6 for(i = 0; i < n; i++) n*c7 x++; C = c1 + c2 + c3 + c4 + c5 + n*c6 + n*c7 Suponha cj < c para todo j > 0 logo, C' = c + c + c + c + c + n*c + n*c C' = 5c +2nc Suponha que c = 1000 segundos logo, C' = 5000 + 2000n. Se n > 2, é fácil perceber que o custo maior é do termo 2000n. E quanto maior o n, maior será a parte que o termo 2000n representa no custo final do código. logo, o custo do código é fundamentalmente o custo do 2o termo. Para isso, foi criada uma notação: O. O O representa a complexidade de execução de um código. Logo, seria C' = O(2000n). Perceba, que pela mesma lógica, como 2000 é um número constante, quanto maior o n, de fato, o valor que representa o custo do programa é somente o termo n. Portanto, a complexidade de execução do código anterior pode ser escrita como C' = O(n). E perceba que, se uma máquina M1 o tempo C for 2000 segundos e em outra M2, muito mais rápida, for de 100 segundos, não importa para o resultado final, pois o tempo que, de fato importa, é o termo n. Obs.: perceba que quando n tende a infinito, fazer 2000 x infinito ou 100 x infinito, é a mesma coisa, ou seja, o custo de fato é o termo n, por isso O(n). Visto esse conceito sobre complexidade e notação O, vamos ver agora qual é a complexidade de um algoritmo eficiente e qual a complexidade de ordenar um conjunto de elementos. Algoritmo eficiente 1) O(1) - Eficiente 2) O(n) - -> Qualquer algoritmo deve ser considerado eficiente se ele tiver complexidade polinominal. f(x) = O(n^c) onde c = cte. c = 1, 2, 3... Não eficiente: -> f'(x) = O(2^n) n 2^n e n^2 1 2 1 2 4 4 3 8 9 4 16 16 5 32 25 6 64 36 7 128 49 f'(x) = 2^n e f(x) = n^2 Ou seja, f(x) = O(f'(x)) <-> n^2 = O(2^n) Ordenação eficiente = O(n * log n) -> Teta(n * log n)