Universidade Federal de Minas Gerais

Departamento de Ciência da Computação

Pós-Graduação em Ciência da Computação

  

 

 

 

PROJETO E ANÁLISE DE ALGORÍTMOS

Profº Nívio Ziviani

1º Trabalho

 

 

 

 

 

José Pinheiro de Queiroz Neto

 

 

Belo Horizonte - MG

2002

 

1ª Questão - Avaliar as somas:

  1. Seja =

    Utilizando o Método da Perturbação [Knuth et al 95]:

    +

    +

    +

    +

    +

    +

    -

    para

    =

    para

      

  2. Sendo a série harmônica acima uma função monotônicamente decrescente, podemos utilizar a técnica de aproximação por integrais para determinar seu limite inferior e superior, conforme demonstrado em [Cormen et al. 91], dada por:

    Aplicando esta aproximação, temos:

    Limite Inferior:

    Limite Superior:

    Logo,

    Podemos então afirmar que:

     

     

     

  3. Seja =

    Utilizando a Aproximação de Stirling [Cormen et al. 91], dada por:

    Podemos afirmar que: , para

    Portanto

     

Seja =

Utilizando o Método do Encurtamento (Telescoping Series) [Cormen et al. 91], e sabendo que :

Rearranjando o somatório, e eliminando os termos simétricos, obtemos:

  p/ n ³ 1

 

  

2ª Questão – Apresente a complexidade de tempo para os procedimentos abaixo:

a)

PROCEDURE FazAlgo ( n : integer);

VAR i, j, k, x : integer;

BEGIN

x := 0;

FOR i := 1 TO n - 1 DO

FOR j := i + 1 TO n DO

FOR k := 1 TO j DO x := x + 1;

END;

 

Seja uma função de complexidade de custo que representa o total de operações de incremento de x. Podemos observar que existem três anéis com intervalos interdependentes, sendo o mais interno com custo para cada evento, e os demais dados em função do mais interno, portanto a função de complexidade de custo para este procedimento é dada por:

sendo [Ziviani 93]

sendo [Knuth 95]

 

b)

PROCEDURE Pesquisa ( n : integer);

BEGIN

IF n > 1

THEN BEGIN

Inspecione n*n*n elementos;

Pesquisa (n/3);

END;

END;

 

Seja uma função de complexidade de custo que representa o número de inspeções nos elementos de um conjunto com elementos. Podemos observar que cada chamada recursiva da função Pesquisa( ) tem custo dado por , e a função Inspecione( ) tem custo do número de inspeções, portanto a equação de recorrência para este procedimento é dada por:

, ou seja, não faz inspeção.

Utilizando o método da Interação [Ziviani 93]

Adicionando ambos os lados e eliminado os termos comuns da equação:

Sendo: - uma potência de 3 ()

-

- [Knuth et al 95]

Temos:

sendo (),

 

c)

PROCEDURE Sort ( VAR A: ARRAY[1..n] OF integer; i, j: integer );

{ n uma potencia de 2 }

BEGIN

IF i < j

THEN BEGIN

m := (i + j - 1)/2;

Sort(A,i,m);

Sort(A,m+1,j);

Merge(A,i,m,j);

{ Merge intercala A[i..m] e A[m+1..j] em A[i..j] }

END;

END;

 

Seja uma função de complexidade de custo que representa o número de comparações nos elementos de um conjunto com elementos. Podemos observar que cada chamada recursiva da função Sort( ) tem custo dado por . A função Merge( ) tem custo do número de comparações para intercalar ordenado, portanto a equação de recorrência para este procedimento é dada por:

, ou seja, não faz comparação.

Utilizando o método da Interação [Ziviani 93]

Adicionando ambos os lados e eliminado os termos comuns da equação:

Sendo: - uma potência de 2 ()

-

- [Knuth et al 95]

Temos:

 

d)

PROCEDURE Proc( n : integer );

BEGIN

IF n = 0 THEN RETURN 1

ELSE RETURN Proc(n-1) + Proc(n-1)

END;

 

Seja uma função de complexidade de custo que representa o número de operações de soma em um conjunto com elementos. Podemos observar a função Proc( ) tem custo para , e cada chamada recursiva tem custo dado por , portanto a equação de recorrência para este procedimento é dada por:

, ou seja, não faz operação de soma.

Utilizando o método da Interação [Ziviani 93]

Adicionando ambos os lados e eliminado os termos comuns da equação:

Sendo: - o número de iterações ()

-

- [Knuth et al 95]

Temos:

 

3ª Questão

São dados 2n números distintos distribuídos em dois arranjos A e B, cada um com n elementos ordenados, tal que: e .O problema é achar o n-ésimo maior número dentre estes 2n elementos.

  1. Apresente um algoritmo ótimo para resolver esse problema. Implemente o seu algoritmo. A listagem da implementação deve ser entregue e o programa submetido.
  2. Prove que o seu algoritmo é ótimo, isto é, obtenha um limite inferior para o número de comparações para resolver esta classe de problemas.

3. Implementação do Algoritmo N-ésimo Maior (Nmax)

3.1 Introdução

Problemas envolvendo a busca de elementos em um arranjo são comuns e de grande utilidade na área de processamento de dados e recuperação de informação, principalmente quando faz-se necessário que esta busca ocorra em um menor tempo possível. Existem diversas instâncias deste problemas, e vários algoritmos que permitem sua solução. Nesta seção iremos apresentar um algoritmo para a solução de um problema em particular, objetivando desenvolver e implementar um algoritmo que se encontre dentro do limite inferior para esta classe de problemas, gerando resultados consistentes que comprovem sua eficácia.

3.2 Especificação do Problema

Dados 2n números distintos distribuídos em dois arranjos A e B, cada um com n elementos ordenados, tal que: e .O problema consiste em determinar o n-ésimo maior número dentre estes 2n elementos, utilizando um algoritmo ótimo.

3.3 Algoritmo Nmax

O algoritmo consiste em dividir os dois vetores ao meio, caso n seja potência de 2, ou ao meio menos um, caso contrário, descartando as duas metades onde, sabidamente, não se encontre o n-ésimo maior elemento desejado. Isto pode ser feito comparando os elementos médios dos dois vetores e analisando quais os elementos que não atingem os critérios do alvo procurado, como pode ser visto no exemplo abaixo:

Sejam A[4] e B[4] abaixo:

a1

a2

a3

a4

b1

b2

b3

b4

i j

O 4º maior elemento tem que ser no maior do que 4 e menor do que 3 elementos, e se a2 > b2 , teremos que:

Eliminando estes elementos temos:

a3

a4

b1

b2

i j

Possuímos agora 4 elementos, 2 que são os 3º e 4º maiores e dois que são os 3º e 4º menores, o elemento alvo é, portanto, menor do 1 e maior do 2 elementos, e se a3 > b1 , teremos que:

Eliminando estes elementos temos:

a4

b1

i j

E nesta situação, por comparação simples, o elemento procurado será o maior entre a4 > b1

No caso do número de elementos não ser potência de 2, uma pequena alteração deve ser adicionada, eliminando a mesma quantidade de elementos nos dois vetores. Abaixo o algoritmo na linguagem C:

int Nmax(int p1, int q1, int p2, int q2, int A[n], int B[n]){

int i,j;

if (p1==q1 && p2==q2){ // p e q índices de início e fim dos vetores

if(A[p1]>B[p2])

return A[p1];

else

return B[p2];

}

else {

i=(int)(q1-p1-1)/2 + p1; // Particiona A

j=(int)(q2-p2-1)/2 + p2; // Particiona B

if(A[i]>B[j]) // Mantém < A[i] e >= B[j]

if ((q1-p1+1)%2==0){

p1=i+1;

q2=j;

}else { // Mantém < A[i+1] e >= B[j]

p1=i+1;

q2=j+1; // Caso particular em que n != potência de 2

}

else // Mantém < B[j] e >= A[i]

if ((q2-p2+1)%2==0){

p2=j+1;

q1=i;

}else { // Mantém < B[j+1] e >= A[i]

p2=j+1;

q1=i+1; // Caso particular em que n != potência de 2

}

return Nmax(p1,q1,p2,q2,A,B); //Faz a recursão

}

}//fim de Nmax

 

3.4 Análise de Complexidade

Seja uma função de complexidade de custo que representa o número de comparações entre os elementos de dois conjuntos com 2 elementos. Podemos observar que a função Nmax( ) tem custo dado por , e a cada chamada recursiva a função Nmax( ) tem custo dado por , portanto a equação de recorrência para este procedimento é dada por:

, ou seja, não faz comparação.

Utilizando o método da Interação [Ziviani 93]

Adicionando ambos os lados e eliminado os termos comuns da equação:

Sendo: - uma potência de 2 ()

-

Temos:

 

3.5 Limite Inferior desta Classe de Problemas

Teorema 1: Qualquer árvore de decisão que busca o n-ésimo maior elemento entre 2n números distintos distribuídos em dois arranjos A e B, cada um com n elementos ordenados, tal que: e , possui altura no caso ótimo.

Prova: Considere uma árvore de decisão de altura h que busca o n-ésimo maior elemento entre 2n números distintos, distribuídos em dois arranjos A e B, cada um com n=4 elementos ordenados, tal que: e , utilizando o algoritmo proposto na seção 3.3.

 

Desde que existam respostas possíveis para encontrar o n-ésimo maior elemento, uma vez que cada um dos 2n elementos pode ser o elemento procurado, qualquer algoritmo utilizado para esta classe de problemas terá, no caso mínimo, a árvore acima que representa a quantidade de comparações entre elementos dos dois arranjos e , que deverá possuir, no mínimo, folhas. Desde que uma árvore binária de altura h não possui mais do folhas, temos então que, para qualquer algoritmo que busque implementar esta solução:

, isto implica que:

é o limite inferior para esta classe de problemas

Corolário: O algoritmo Nmax proposto na seção 3.3 é assintóticamente ótimo para esta classe de problemas.

Prova: O algoritmo Nmax possui complexidade de custo de , conforme demonstrado na seção 3.4, que está dentro do limite inferior para a solução desta classe de problemas, apresentado no Teorema 1.

 

3.6 Implementação do Algoritmo Nmax

O algoritmo foi implementado em linguagem C, no compilador gcc, utilizando uma plataforma Sun Ultra 5 em ambiente Solaris. Possui os seguintes arquivos: o principal, um módulo contendo as funções e um de cabeçalho. Como forma de tornar a análise da complexidade de custo mais transparente foi implementado utilizando recursão, o que aumenta a complexidade de espaço, que entretanto não é fator relevante neste estudo.

Para utilizá-lo basta digitar o comando executável, pois o mesmo irá gerar os dois arranjos de acordo com o problema que está sendo tratado, obtendo como saída os arranjos e sub-arranjos após cada divisão, e ao final o n-ésimo maior elemento. As principais funções do programa são:

Função GeraVetores: Gera dois vetores de tamanho n, em ordem decrescente, utilizando 2n números distintos. para garantir a distinção entre eles, um vetor será formado por números pares e outro por números ímpares, a partir de números aleatórios gerados pela função rand().

Função Nmax: Consiste em dividir os vetores ao meio (metade -1) e eliminar aqueles elementos que não possuem o n-ésimo maior elemento, comparando A[i] com B[j] e eliminando o maior entre as duas chaves e todos os maiores que ele (do mesmo vetor) e os menores que a menor chave (do mesmo vetor), sendo que em um caso particular (n ímpar), serão eliminados m-1 menores. A função é chamada recursivamente e a condição de parada é quando restar um único elemento em cada vetor, sendo que o maior entre eles será o n-ésimo maior elemento.

As demais funções podem ser encontradas no código do programa, conforme Anexo I.

 

3.7 Resultados Obtidos

Os testes foram efetuados considerando a geração aleatória de 2n elementos, para n=1, n=2, n=3, n=4, n=5, n=6, n=7, n=8, n=9 e n=10, sendo a busca alcançada com sucesso em todos os casos.. Segue abaixo um dos resultados obtidos, os demais poderão ser vistos no Anexo II.

Resultado impresso pelo programa para n = 8 :

 

Vetor A[8]: 136 108 96 66 62 58 50 34

Vetor B[8]: 159 149 145 123 93 61 33 29

Faz uma comparacão de A[3] com B[3] e obtém:

Vetor A[4]: 136 108 96 66

Vetor B[4]: 93 61 33 29

Faz uma comparacão de A[1] com B[5] e obtém:

Vetor A[2]: 96 66

Vetor B[2]: 93 61

Faz uma comparacão de A[2] com B[4] e obtém:

Vetor A[1]: 66

Vetor B[1]: 93

Faz a última comparacão de A[3] com B[3] e obtém:

O 8° maior é: 93

*****Fim do Programa*****

 

3.8 Conclusão

O problema apresentado possui mais de um tipo de algoritmo que implementa sua solução, entretanto nem todos estão na ordem de complexidade do limite inferior para esta classe de problemas.

O algoritmo Nmax apresenta uma solução que se encontra dentro do limite inferior, possuindo complexidade de O(log2(n)) , conforme demonstrado no item 3.4 . A versão recursiva do algoritmo facilita o seu entendimento em termos de complexidade de custo, entretanto, devido ao empilhamento em cada chamada recursiva, aumenta a complexidade de espaço, o que nos leva a concluir que a versão não recursiva de Nmax é uma opção mais vantajosa para a solução do problema apresentado.

Os experimentos realizados garantem a eficiência do algoritmo, uma vez que houve 100% de acerto em todos os experimentos realizados, conforme pode ser visto no Anexo II.

 

 4ª Questão - Árvore Binária de Pesquisa Sem Balanceamento (1 + 0,5 + 0,5 + 1 pontos)

Considere o algoritmo para pesquisar e inserir registros em uma árvore binária de pesquisa sem balanceamento. Devido à sua simplicidade e eficiência a árvore binária de pesquisa é considerada uma estrutura de dados muito útil. Considerando-se que a altura da árvore corresponde ao tamanho da pilha necessária para pesquisar na árvore é importante conhecer o seu valor. Assim sendo,

  1. Determine empiricamente a altura esperada da árvore;

Para a obtenção empírica da altura de uma árvore randômica não balanceada, foram executados os seguintes passos principais:

Após a execução dos experimentos, e considerando k como sendo uma constante que permite que h » klog2(n), foram obtidos os seguintes resultados:

n

21

22

23

24

25

26

27

28

29

210

211

212

213

214

215

216

217

218

219

220

h

1

3

5

7

9

11

14

16

19

22

24

27

30

32

36

39

41

44

47

51

k

1.00

1.50

1.67

1.75

1.80

1.83

2.00

2.00

2.11

2.20

2.18

2.25

2.31

2.29

2.40

2.44

2.41

2.44

2.47

2.55

É possível observar através do gráfico que o valor de k aumenta à medida que aumenta também o tamanho da entrada n . Sendo o desvio padrão obtido nos 10 primeiros valores de k igual a 0.25, e o desvio padrão obtido nos 10 últimos valores e de k igual a 0.13, é possível afirmar que k tende a um valor constante quando n tende a infinito, ou seja, para entradas com n muito grande, a altura da árvore pode ser dada por h º klog2(n), sendo k > 2.55. Estudos empíricos e matemáticos mais aprofundados são disponíveis na literatura, estabelecendo um valor de k com maior precisão. Iremos discutir sobre o valor de k encontrado neste experimento e o valor descrito na literatura no item c) desta questão.

 
  1. Mostre analiticamente o melhor caso e o pior caso para a altura da árvore;
  2. O melhor caso será aquele em que a árvore binária for balanceada, conforme abaixo:

    Nível 1 - 20 elementos
    Nível 2 - 21 elementos
    Nível 3 - 22 elementos
    Nível n - 2h elementos
     
    Sendo h a altura da árvore e n o número de elementos dado por:
     

    Sendo

    [Knuth et al 95]

     
    O pior caso será aquele em que a entrada n for uma seqüência de valores crescentes ou decrescentes, resultando em que todos os elementos sejam inseridos somente à esquerda ou somente à direita da árvore. Isto faz com que cada nó pai tenha um único nó filho, e que a árvore possua um único caminho entre o nó raiz e o nó folha, dado por n-1 elementos, que é exatamente a altura da árvore, portanto:
     
  3. Compare os resultados obtidos no item (a) com resultados analíticos publicados na literatura.
  4. A altura esperada de uma árvore binária não balanceada, construída a partir de permutações randômicas, como no caso da árvore implementada no item a), é dada por:

    sendo A = 4.311 [Knessl and Szpankowski 00]

    Calculando-se a altura da árvore utilizando-se a expressão acima, e apresentando a quantidade de elementos n e a altura empírica da árvore obtida no item a), obtemos o quadro e o gráfico abaixo:

    n

    21

    22

    23

    24

    25

    26

    27

    28

    29

    210

    211

    212

    213

    214

    215

    216

    217

    218

    219

    220

    h

    1

    3

    5

    7

    9

    11

    14

    16

    19

    22

    24

    27

    30

    32

    36

    39

    41

    44

    47

    51

    H

    4

    5

    8

    10

    13

    15

    18

    21

    24

    26

    29

    32

    35

    38

    41

    43

    46

    49

    52

    55

    Como pode ser visto, os resultados empíricos obtidos são consistentes, quando comparados com os resultados analíticos, ainda que para valores de n não muito grandes. Para valores de n muito grande, temos que:

    A constante k encontrada empiricamente no item a) foi de 2.55 para n = 220, e cuja tendência de crescimento, observada pelo declínio do desvio padrão entre as amostras, nos leva a considerar que este valor ficaria próximo do valor analítico citado na literatura [Knessl and Szpankowski 00].

     
  5. Mostre analiticamente o número esperado de comparações para encontrar um registro existente na árvore (busca com sucesso).
Seja:

o comprimento médio da trajetória de busca com sucesso;

o valor de uma chave com probabilidade de ser o nó raiz da árvore;

a subárvore à esquerda de com comprimento médio de ;

a subárvore à direita de com comprimento médio de .

O comprimento médio da trajetória em uma árvore com nós é a soma dos produtos dos níveis de cada um dos nós pela sua correspondente probabilidade de acesso [Wirth 76]. Admitindo-se que a probabilidade de busca para todos os nós é mesma:

(d.1) onde pi é o comprimento da trajetória de busca do nó

Sendo que:

Os nós à esquerda possuem comprimento médio de trajetória ;

O nó raiz possui trajetória de busca igual a zero;

O nós à direita possuem comprimento médio de trajetória +1.

A equação (d.1) pode ser expressa como a soma de dois termos:

(d.2)

 

 A equação (d.2) é uma relação de recorrência da forma an = f1(a1,a2,...an). A partir disto, deriva-se uma relação de recorrência da forma an = f2(an -1). Da equação (d.2) deriva-se a expressão (1), desmembrando-se o último termo, e a expressão (2), substituindo-se n por n-1:

  1. Multiplicando (2) por ((n-1)/2)2 obtemos

E substituindo (3) em (1)

an pode ser expressa em uma forma fechada não recursiva em termos da função harmônica [Wirth 76].

Aplicando-se a forma de Euler (usando a constante de Euler g » 0.577)

deriva-se, para valores grandes de n, a relação

Sendo o comprimento médio da trajetória em árvores banceadas aproximadamente igual a

E ignorando-se os termos constantes por serem desprezíveis quando n é muito grande:

Conforme valor citado em [Ziviani 93]

 

 

REFERÊNCIAS

 

 [Cormen et al 91] Cormen, T.H.; Leirson, C.E.; Rivest, R. L.; Introduction to Algorithms, McGraw-Hill,1991.

[Knessl and Szpankowski 00] Knessel, C; Szpankowski, W; The Height of a Binary Search Tree: The limit Distribution Perspective , 55pp. manuscrito em submissão.

[Knuth et al 95] Knuth, Donald E.; Graham, Ronald L.; Patashnik, Oren; Matematica Concreta , Livros Técnicos e Científicos, 1995.

[Wirth 76] Wirth, N; Algorithms + Data Structures = Programs , Prentice Hall, 1976

[Ziviani 93] Ziviani, Nívio; Projetos de Algoritmos Com Implementações em Pascal e C, Editora Pioneira, 1993.

 

 

BIBLIOGRAFIA

 

Knuth, D.E.; The Art of Computer Programming, volume 1. Addison-Wesley, Reading, MA, 1973.

Lueker, George S.; Some Techniques to Solve Recurrences, Computing Survey, Vol. 2, Nº4, December, 1980.

Manber,Udi; Introduction to Algorithms A Creative Approach, Addison-Wesley, 1989.

Miyazawa, Flavio Keidi; Notas de Aula de Complexidade de Algoritmos, Apostila do Instituto de Computação, UNICAMP.

 

 

 

ANEXO I – Código do Programa (Questão 3)

/* -----------------------------------------------------------------

Módulo .h p/ resolucao da questao 3 - Lista1 de PAA (2002/01)

Doutorado em Ciencia da Computacao - UFMG

Autor: José Pinheiro de Queiroz Neto - 2002201999

Orientador: Dr. Mario F. M. Campos (UFMG)

Co-Orientador: Dr. Rodrigo L. Carceroni (UFMG)

Propósito: Encontrar o n-esimo maior entre dois vetores ordenados

BH 14/06/02 */

#define n 8 // define tamanho n dos vetores

/* -------------Estruturas e Variaveis Globais -----------------------*/

 

/* -------------Area de Declaracao de Funcoes ------------------------*/

void IniciaRand();

void GeraVetores(int A[n],int B[n]);

int Nmax(int p1, int q1, int p2, int q2, int A[n], int B[n]);

void ImprimeVetores(int p1, int q1, int p2, int q2, int A[n],int B[n]);

 

/* -----------------------------------------------------------------

Módulo .h p/ resolucao da questao 3 - Lista1 de PAA (2002/01)

Doutorado em Ciencia da Computacao - UFMG

Autor: José Pinheiro de Queiroz Neto - 2002201999

Orientador: Dr. Mario F. M. Campos (UFMG)

Co-Orientador: Dr. Rodrigo L. Carceroni (UFMG)

Propósito: Encontrar o n-esimo maior entre dois vetores ordenados

BH 14/06/02 */

#include "t1quest3.h"

#include <sys/types.h>

#include <sys/timeb.h>

/* -------------Area de Funcoes de Operações --------------------------*/

/* Funcao IniciaRand. Gera uma semente diferente para a geracao de um

numero aleatorio em rand(), a cada execucao do programa */

void IniciaRand() { /* Substituir por uma funcao que tome tempo em ms */

time_t ltime;

time(&ltime);

ltime%=10000;

srand(ltime);

}// Fim de IniciaRand

/* Funcao GeraVetores. Gera dois vetores de tamanho n, em ordem decrescente, utilizando 2n numeros distintos. para garantir a distincao entre eles, um vetor será formado por números pares e outro por números ímpares, a partir de números aleatórios gerados pela funcão rand() */

void GeraVetores(int A[n],int B[n]){

int i,aux,Aprox=0,Bprox=1;

IniciaRand();

for (i=n-1;i>=0;i--){

aux=rand()/0x3E8; //divide por 1000 para reduzir o numero

if (aux%2==0)

A[i]=aux+(Aprox+2); //soma Aprox+2 para o caso de aux=0

else

A[i]=aux+(Aprox+1);

Aprox=A[i];

}

for (i=n-1;i>=0;i--){

aux=rand()/0x3E8; //divide por 1000 para reduzir o numero

if (aux%2==0)

B[i]=aux+Bprox;

else

B[i]=aux+Bprox+1;

Bprox=B[i];

}

}// Fim de GeraVetores

/* Funcao Nmax. Consiste em dividir os vetores ao meio (metade -1) e eliminar aqueles elementos que não possuem o n-esimo maior elemento, comparando A[i] com B[j] e eliminando o maior entre as duas chaves e todos os maiores que ele (do mesmo vetor) e os menores que a menor chave (do mesmo vetor), sendo que em um caso particular (n ímpar), serão eliminados m-1 menores. A funcão é chamada recursivamente e a condicão de parada é quando restar um único elemento em cada vetor, sendo que o maior entre eles será o n-esimo maior elemento. */

int Nmax(int p1, int q1, int p2, int q2, int A[n], int B[n]){

int i,j;

ImprimeVetores(p1,q1,p2,q2,A,B); // Imprime vetores particionados

// Condicão de parada

if (p1==q1 && p2==q2){

// Determina o n-ésimo maior entre os valores restantes de cada vetor

printf("\nFaz a última comparacão de A[%d] com B[%d] e obtém:\n",p1,q1);

if(A[p1]>B[p2])

return A[p1];

else

return B[p2];

}

else {

i=(int)(q1-p1-1)/2 + p1; // Particiona A

j=(int)(q2-p2-1)/2 + p2; // Particiona B

printf("\nFaz uma comparacão de A[%d] com B[%d] e obtém:\n",i,j);

if(A[i]>B[j]) // Mantém os menores que A[i] e os maiores e igual a B[j]

if ((q1-p1+1)%2==0){

p1=i+1;

q2=j;

}else { // Mantém os menores+1 que A[i] e os maiores e igual a B[j]

p1=i+1;

q2=j+1; // Caso particular em que o tamanho do vetor é impar

}

else // Mantem os menores que B[j] e os maiores e igual a A[i]

if ((q2-p2+1)%2==0){

p2=j+1;

q1=i;

}else { // Mantem os menores+1 que B[j] e os maiores e igual a A[i]

p2=j+1;

q1=i+1; // Caso particular em que o tamanho do vetor é impar

}

return Nmax(p1,q1,p2,q2,A,B); //Faz a recursão

}

}//fim de Nmax

/* Funcao ImprimeVetores. imprime os dois vetores de tamanho (q1-p1+1), ou

seja, imprime os elementos dos vetores que foram particionados */

void ImprimeVetores(int p1, int q1, int p2, int q2, int A[n],int B[n]){

int i;

printf("\nVetor A[%d]:",q1-p1+1);

for (i=p1;i<=q1;i++){

printf("\t%d",A[i]);

}

printf("\nVetor B[%d]:",q2-p2+1);

for (i=p2;i<=q2;i++){

printf("\t%d",B[i]);

}

printf("\n");

}//Fim de ImprimeVetores

/* -----------------------------------------------------------------

Programa p/ resolucao da questao 3 - Lista1 de PAA (2002/01)

Doutorado em Ciencia da Computacao - UFMG

Autor: José Pinheiro de Queiroz Neto - 2002201999

Orientador: Dr. Mario F. M. Campos (UFMG)

Co-Orientador: Dr. Rodrigo L. Carceroni (UFMG)

Propósito: Encontrar o n-esimo maior entre dois vetores ordenados

BH 14/06/02 */

/* -----------------------Comentarios---------------------------------*/

/*

Este programa gera dois vetores A e B, com 2n números distintos, cada

vetor com n elementos ordenados, tal que A[1] > A[2] > ...> A[n] e

B[1] > B[2] > ...>B[n]. A partir destes vetores é implementado um

algoritmo que determine o n-esimo maior número entre os 2n elementos,

em complexidade de tempo de O(logn) na base 2

O algoritmo consiste em dividir os vetores ao meio e eliminar aqueles

elementos que não possuem o n-esimo maior elemento, e assim sucessi-

vamente até restar somente um elemento em cada vetor, onde o maior

entre eles será o elemento procurado.

Sendo desenvolvido no ambiente solaris, e compilado no gcc

(g++ -o maior t1quest3.cpp). A linha de comando é: <executável>

Os testes foram efetuados considerando a geracão aleatória de 2n

elementos, para n=1, n=2, n=3, n=4, n=5, n=6, n=7, n=8, n=9 e n=10,

sendo a busca alcancada com sucesso em todos os casos.

*/

/* ---------------Bibliotecas ---------------------------------------*/

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include "modt1quest3.c"

/* -------------- Area da Funcao Principal --------------------------*/

int main(int argc, char *argv[]){

int A[n],B[n], // Vetores ordenados A e B

i,j, // indices de particao dos vetores

p1=0, q1=n-1, // indices inicial e final do vetor A

p2=0, q2=n-1, // indices inicial e final do vetor B

maior; // n-esimo maior elemento entre os dois vetores

/* verifica se o numero de argumentos esta correto */

if (argc != 1){

fprintf(stderr, "Numero incorreto de parametros\n");

printf("entre com: maior\n");

exit(1);

}

GeraVetores(A,B); // Gera elementos ordenados para os vetores A e B

maior = Nmax(p1,q1,p2,q2,A,B); // Algoritmo de busca binária

printf("\nO %d° maior é: %d\n",n,maior);

printf("\n*****Fim do Programa*****\n\n");

return 0;

}

 

 

ANEXO II (Resultados – Questão 3)

N=1

Vetor A[1]: 18

Vetor B[1]: 9

Faz a última comparacão de A[0] com B[0] e obtém:

O 1° maior é: 18

*****Fim do Programa*****

N=2

Vetor A[2]: 14 10

Vetor B[2]: 27 15

Faz uma comparacão de A[0] com B[0] e obtém:

Vetor A[1]: 14

Vetor B[1]: 15

Faz a última comparacão de A[0] com B[0] e obtém:

O 2° maior é: 15

*****Fim do Programa*****

N=3

Vetor A[3]: 42 26 14

Vetor B[3]: 63 37 23

Faz uma comparacão de A[0] com B[0] e obtém:

Vetor A[2]: 42 26

Vetor B[2]: 37 23

Faz uma comparacão de A[0] com B[1] e obtém:

Vetor A[1]: 26

Vetor B[1]: 37

Faz a última comparacão de A[1] com B[1] e obtém:

O 3° maior é: 37

*****Fim do Programa*****

N=4

Vetor A[4]: 64 54 38 20

Vetor B[4]: 87 59 37 27

Faz uma comparacão de A[1] com B[1] e obtém:

Vetor A[2]: 64 54

Vetor B[2]: 37 27

Faz uma comparacão de A[0] com B[2] e obtém:

Vetor A[1]: 54

Vetor B[1]: 37

Faz a última comparacão de A[1] com B[1] e obtém:

O 4° maior é: 54

*****Fim do Programa*****

N=5

Vetor A[5]: 120 90 70 52 24

Vetor B[5]: 71 59 27 15 7

Faz uma comparacão de A[1] com B[1] e obtém:

Vetor A[3]: 70 52 24

Vetor B[3]: 71 59 27

Faz uma comparacão de A[2] com B[0] e obtém:

Vetor A[2]: 70 52

Vetor B[2]: 59 27

Faz uma comparacão de A[2] com B[1] e obtém:

Vetor A[1]: 52

Vetor B[1]: 59

Faz a última comparacão de A[3] com B[3] e obtém:

O 5° maior é: 59

*****Fim do Programa*****

N=6

Vetor A[6]: 80 76 60 48 28 12

Vetor B[6]: 67 59 47 41 37 5

Faz uma comparacão de A[2] com B[2] e obtém:

Vetor A[3]: 48 28 12

Vetor B[3]: 67 59 47

Faz uma comparacão de A[3] com B[0] e obtém:

Vetor A[2]: 48 28

Vetor B[2]: 59 47

Faz uma comparacão de A[3] com B[1] e obtém:

Vetor A[1]: 48

Vetor B[1]: 47

Faz a última comparacão de A[3] com B[3] e obtém:

O 6° maior é: 48

*****Fim do Programa*****

N=7

Vetor A[7]: 156 146 124 94 62 42 18

Vetor B[7]: 111 103 95 65 49 21 9

Faz uma comparacão de A[2] com B[2] e obtém:

Vetor A[4]: 94 62 42 18

Vetor B[4]: 111 103 95 65

Faz uma comparacão de A[4] com B[1] e obtém:

Vetor A[2]: 94 62

Vetor B[2]: 95 65

Faz uma comparacão de A[3] com B[2] e obtém:

Vetor A[1]: 94

Vetor B[1]: 65

Faz a última comparacão de A[3] com B[3] e obtém:

O 7° maior é: 94

*****Fim do Programa*****

N=8

Vetor A[8]: 130 102 96 78 62 40 18 4

Vetor B[8]: 183 165 135 105 99 67 39 17

Faz uma comparacão de A[3] com B[3] e obtém:

Vetor A[4]: 130 102 96 78

Vetor B[4]: 99 67 39 17

Faz uma comparacão de A[1] com B[5] e obtém:

Vetor A[2]: 96 78

Vetor B[2]: 99 67

Faz uma comparacão de A[2] com B[4] e obtém:

Vetor A[1]: 96

Vetor B[1]: 67

Faz a última comparacão de A[2] com B[2] e obtém:

O 8° maior é: 96

*****Fim do Programa*****

N=9

Vetor A[9]: 122 102 86 82 68 66 52 28 26

Vetor B[9]: 131 107 89 81 49 31 27 25 17

Faz uma comparacão de A[3] com B[3] e obtém:

Vetor A[5]: 68 66 52 28 26

Vetor B[5]: 131 107 89 81 49

Faz uma comparacão de A[5] com B[1] e obtém:

Vetor A[3]: 68 66 52

Vetor B[3]: 89 81 49

Faz uma comparacão de A[4] com B[2] e obtém:

Vetor A[2]: 68 66

Vetor B[2]: 81 49

Faz uma comparacão de A[4] com B[3] e obtém:

Vetor A[1]: 68

Vetor B[1]: 49

Faz a última comparacão de A[4] com B[4] e obtém:

O 9° maior é: 68

*****Fim do Programa*****

N=10

Vetor A[10]: 140 130 106 102 100 88 68 62 38 12

Vetor B[10]: 151 123 97 87 69 37 35 29 27 23

Faz uma comparacão de A[4] com B[4] e obtém:

Vetor A[5]: 88 68 62 38 12

Vetor B[5]: 151 123 97 87 69

Faz uma comparacão de A[6] com B[1] e obtém:

Vetor A[3]: 88 68 62

Vetor B[3]: 97 87 69

Faz uma comparacão de A[5] com B[2] e obtém:

Vetor A[2]: 88 68

Vetor B[2]: 87 69

Faz uma comparacão de A[5] com B[3] e obtém:

Vetor A[1]: 68

Vetor B[1]: 87

Faz a última comparacão de A[6] com B[6] e obtém:

O 10° maior é: 87

*****Fim do Programa*****