MO417 - Atas das Aulas (Conceitos Básicos)

Ata de Aula: 21/02/2003
Redator: Patrick Henrique da Silva Brito

 

Tópicos:

  1. Problema de ordenação;
  2. Ordenação por inserção;
  3. Loops invariantes;
  4. Modelo RAM;
  5. Análise (Custo e nº de vezes que cada linha é executada);
  6. Pior caso e caso médio;
  7. Razão de crescimento;
  8. Divisão e conquista: Merge sort;
  9. Recorrência do Merge sort;

Problema de ordenação

Consiste em um problema que possui:
Entrada: um array de n elementos (a1, a2, ..., an);
Saída: um array (b1, b2, ..., bn) com os mesmos elementos da entrada, mas numa ordem tal que b1 <= b2 <= ... <=  bn.

Ordenação por inserção

É um algoritmo de ordenação onde você percorre o array, sempre a partir do primeiro índice desordenado (inicialmente o 2º elemento), e em seguida procura inseri-lo na posição correta, comparando-o com o seu anterior e trocando-os de lugar enquanto ele for menor que seu precedente.
 

Loops invariantes

São as afirmações / propriedades que se mantém válidas no início de cada iteração do loop.
Ex.: No algoritmo de Insertion sort (veja abaixo), há uma invariante do loop externo, poisno início de cada iteração, a sub-array A[1]..A[j-1] consiste dos mesmos elementos que tinham antes e está ordenada.
Foi discutido sobre a questão 2.1-3, que propõe um problema de busca seqüencial, que possua:
Entrada:um array de vetores (A) e um valor (v) a ser encontrado em A.
Saída: o índice (i) onde se encontra o item v no array A (em caso de repetição de v, pode-se fornecer qualquer índice i tal que A[i]) = v.
 

Modelo RAM

É um modelo de computação, isto é, é uma descrição de onde o algoritmo vai ser executado (máquina). Possui as seguintes características:
oAritméticas (soma, subtração, multiplicação, divisão, resto, piso e teto);
oDe movimentação de dados (carregar, armazenar, copiar);
oDe controle (desvio condicional e incondicional, chamada e retorno de sub-rotina);
oEssas instruções são executadas em uma unidade de tempo, uma aos a outra (sem concorrência);
oSuporta os tipos de dados: Inteiro e de ponto flutuante;
oPossui uma memória, que é representada por um vetor infinito que provê acesso aleatório em uma unidade de tempo. Esse acesso aleatório em uma unidade de tempo é a principal característica desse modelo computacional.
RAM (Random Access Machine) é uma máquina teórica, assim como a máquina de Turing, porém o modelo RAM é mais real, uma vez que provê o acesso aleatório à memória, se assemelhando a um computador real.
 

Análise (Custo e nº de vezes que cada linha é executada)

Analisar um algoritmo significa prever os recursos de que o algoritmo necessita. Mas com freqüência é o tempo de computação que desejamos medir.
 
Análise do algoritmo Insert sort:
Custo
Nº de vezes
Pseudocódigo
3
n
for j <-- 2 to length[A]
2
n-1
     key <-- A[j]
2
n-1
     i <-- j-1
4
     while i>0 and A[i]>key
4
           A[i+1] <-- A[i]
2
           i <-- i-1
3
n-1
     A[i+1] <-- key

* Como o tamanho do vetor de entrada (n) interfere diretamente no tempo de execução, o nº de ciclos do algoritmo foi estimado em função dele (n).

Resolução dos somatórios (Soma dos termos de uma PA):

O tempo de execução T(n)= soma de todos os custos, multiplicados pelo respectivo nº de vezes que foi executado.

T(n)= 5n2 + 7n – 11, assim, o tempo de execução do algoritmo Insertion sort é uma função quadrática de n, isto é, o tempo de execução, no pior caso é ordem de n2, representado por O(n2).
 

Pior caso e caso médio

Em geral, nos concentramos apenas na descoberta do tempo de execução no pior caso; ou seja, o tempo de execução mais longo para qualquer entrada de tamanho n. Alguns comentários sobre essa escolha:
 
Porém há algumas situações em que o caso médio é bastante relevante, como por exemplo, o algoritmo Quick sort que possui um pior caso O(n2), porém, na prática se mostra o melhor algoritmo de ordenação conhecido, pois seu caso médio é O(n lg n).
 

Razão de crescimento

Para saber a razão de crescimento de um algoritmo, as constantes e os termos de menor ordem devem ser ignorados, uma vez que o objetivo é ter uma idéia geral da taxa de crescimento em função da variação da entrada, o que é representado pelo termo mais significativo, isto é, o de maior ordem.
A razão de crescimento é o principal fator levado em consideração ao analisar a adequação ou não de um algoritmo a um problema que exija um determinado tamanho de entrada.
Ex.: Se um problema exigisse a ordenação de um vetor de até 100 unidades, o algoritmo de Insertion sort se adequaria, porém, para outro problema que exija a ordenação de vetores com mais de 1.000.000 de de unidades, o Insertion sort seria inviável.
 

Divisão e conquista: Merge sort

Divisão e conquista é uma técnica de resolução de problemas que visa reduzir o esforço de resolução dividindo o problema inicial em sub-problemas, que podem ser resolvidos recursivamente, até encontrar um caso base resolvido de maneira trivial. Essa técnica possui basicamente três passos:
  1. Dividir o problema em sub-problemas;
  2. Conquistar os sub-problemas;
  3. Combinar as soluções dos sub-problemas, apresentando a resolução do problema inicial.
 
O algoritmo Merge Sort utiliza essa técnica para resolver o problema da ordenação:
  1. Divide o array em dois sub-arrays;
  2. Ordena cada sub-array de forma recursiva;
  3. Combina os sub-arrays ordenados, conservando a ordenação.
O Merge Sort é recursivo e divide o vetor até que o sub-array tenha apenas um elemento, o que caracteriza o caso base uma vez que um vetor unitário sempre está ordenado.
 

Recorrência do Merge sort

A introdução desse conceito foi apresentado através da análise do algoritmo recursivo de Merge Sort:
Custo
Nº de vezes
Pseudocódigo
   
Merge-Sort(A,p,r)
1
1
   if p < r then
3
1
      q <-- arredondaParaMenos[(p+r)/2]
T(m/2)
1
      Merge-Sort(A,p,q)
T(m/2)
1
      Merge-Sort(A,q+1,r)
cm
1
      Merge(A,p,q,r)
m= tamanho da entrada = (r-p+1)
O procedimento Merge(A,p,q,r) tem a função de combinar os dois sub-arrays (A[p..q] e A[q+1..r]) e seu tempo de execução é proporcional ao tamanho desses dois sub-arrays, isto é O(m), para m=(r-p+1). Como os valores do custo serão empregados numa equação, a ordem do valor não deve ser empregada simplesmente, portanto, multiplicamos m por uma constante apropriada c.
A complexidade do algoritmo de ordenação de um vetor com m elementos é representada por T(m):
T(m)=2T(m/2) + cm + 4
Essa equação chama-se recorrência, pois ela estipula todos os valores da função dependendo de valores menores da mesma função (recursividade). Deve haver também o caso base: neste caso, quando m=1 (p=r), T(1)=1.
 

… “não foi continuada a resolução dessa equação em sala, uma vez que o conhecimento necessário para esse fim (resolução de recorrência) será tratado em outra aula”.

 
A solução é T(m) = O(m lg m). Para ordenar um vetor de n elementos, temos T(n) = O(n lg n).
Conclusão: O algoritmo de ordenação Merge Sort é mais rápido que o algoritmo Insertion Sort, que tem razão de crescimento O(n2).