Algoritmos para concursos Questões comentadas Handbook de Questões de TI Comentadas para Concursos Volume questões de TI Prefácio Um algoritmo é um conjunto de operações em sequência para resolver determinado problema. A noção de algoritmo é extremamente importante para a computação. Não existe um con- junto de regras que nos permita criar novos algoritmos e, portanto, trata-se de umas maiores diculdades dos iniciantes em programação. O estudo de algoritmos é muito cobrado nos concursos na área de tecnologia da informação e, por isso, o Grupo Handbook de TI preparou este volume, que traz uma série de questões comentadas sobre Algoritmos para você se preparar ainda melhor para os certames de seu interesse. Bons estudos, Grupo Handbook de TI Página 1 de 27 www.handbookdeti.com.br Handbook de Questões de TI Comentadas para Concursos Volume questões de TI Direitos Autorais Este material é registrado no Escritório de Direitos Autorais (EDA) da Fundação Biblioteca Nacional. Todos os direitos autorais referentes a esta obra são reservados exclusivamente aos seus autores. Os autores deste material não proíbem seu compartilhamento entre amigos e colegas próximos de estudo. Contudo, a reprodução, parcial ou integral, e a disseminação deste material de forma indiscriminada através de qualquer meio, inclusive na Internet, extrapolam os limites da colaboração. Essa prática desincentiva o lançamento de novos produtos e enfraquece a comunidade concurseira Handbook de TI. A série Handbook de Questões de TI Comentadas para Concursos Além do Gabarito produção independente e contamos com você para mantê-la sempre viva. Grupo Handbook de TI Página 2 de 27 www.handbookdeti.com.br é uma Handbook de Questões de TI Comentadas para Concursos Volume questões de TI Canais de Comunicação O Grupo Handbook de TI disponibiliza diversos canais de comunicação para os concurseiros de TI. Loja Handbook de TI Acesse a nossa loja virtual em http://www.handbookdeti.com.br Serviço de Atendimento Comunique-se diretamente conosco através do e-mail [email protected] Twitter do Handbook de TI Acompanhe de perto promoções e lançamentos de produtos pelo nosso Twitter com/handbookdeti Página 3 de 27 www.handbookdeti.com.br http://twitter. Handbook de Questões de TI Comentadas para Concursos 1. Volume questões de TI Assuntos relacionados: Algoritmos, Complexidade de Algoritmos, Banca: Cesgranrio Instituição: Petrobras Cargo: Analista de Sistemas Pleno - Processos Ano: 2006 Questão: 52 A respeito de funções e algoritmos, assinale a armativa correta. (a). O limite inferior de um algoritmo (Ω) é utilizado para a análise do pior caso de sua execução. (b). Uma função tivas c e n0 , f (n) domina assintoticamente n ≥ n0 , tais que, para f (5log2 N ) (d). A função f (5N 3 + 2N 2 ) (e). Se duas funções f () e constantes posi- O2 (N ). (c). A função é g(n), se existem duas |g(n)| ≥ c|f (n)|. temos que O(N ). é g() têm limite superior justo, então f () é O(g()) e g() é O(f ()). Solução: Uma avaliação analítica pode ser feita com o objetivo de se obter uma estimativa de esforço de um algoritmo em termos do tamanho do problema. Tal estimativa resulta em uma função do crescimento do tempo de execução de um algoritmo em relação ao tamanho da entrada. Em geral, o trabalho que um algoritmo precisa fazer para resolver um problema cresce de acordo com o número de itens de entrada. Para determinar a complexidade de um algoritmo, conta-se o número de operações que ele faz para cada item, onde cada operação pode ser leituras de disco, comparações, trocas etc. Em seguida, é determinada uma expressão que representa essa quantidade. O que se considera no estudo de complexidade de algoritmos é o seu comportamento assintótico, ou seja, uma tendência a um limite à medida do crescimento do tamanho do problema. Vamos elucidar as notações geralmente utilizadas para esse tipo de avaliação analítica. g(n) é O(f (n)), notando-se g = O(f (n)) se existir alguma consn0 , tal que n > n0 implica g(n) ≤ c x f (n). Diz-se também que g(n) tem taxa de crescimento proporcional a f (n), é de ordem máxima f (n), de complexidade f (n) ou magnitude f (n), simplesmente que é O de f (n). A análise O é conhecida Diz-se que uma função tante c>0 e um inteiro também como a análise do pior caso. Dadas funções assintoticamente não-negativas g e f, dizemos que g está na ordem Ω de f , e escrevemos g = Ω(f (n)), se existir alguma constante c > 0 e um inteiro n0 tal que n > n0 implica g(n) ≥ c x f (n). É fácil notar que f = O(g) se e somente se g = Ω(f ). A análise Ômega é conhecida como a análise do melhor caso e é pouco utilizada. As notações utilizadas em minúsculo através dos símbolos o (o minúsculo) e ω são utili- zadas para representar limites assintóticos não justos, as denições anteriores mudam de algum c > 0 para todo todo c > 0. Já que foi dada um explicação básica em relação à complexidade de algoritmos e suas Página 4 de 27 www.handbookdeti.com.br Handbook de Questões de TI Comentadas para Concursos Volume questões de TI notações, vamos analisar as alternativas de uma a uma. A alternativa (A) está claramente errada, já que a notação Ω é utilizada para denotar a análise do melhor caso e não do pior caso. Também está equivocada a alternativa (B), visto que quando dizemos que assintoticamente g(n) A notação O2 g(n) = O(f (n)) |g(n)| ≤ c x |f (n)|. dizemos também que errada visto que o correto, neste caso, é f (n) domina e a denição está ligeiramente não faz sentido em complexidade de algoritmos, logo, a alternativa (C) pode ser invalidada. O termo dominante em uma função polinomial pode ser utilizado para determinar a análise de pior caso de um algoritmo. Na função bém sendo aceito que f é O(5N 3 ), f (5N 3 + 2N 2 ), O(N 3 ) tamO(N ), visto que podemos dizer que é por exemplo, mas, com certeza, f não é N não é o termo dominante do polinômio. Portanto, a alternativa (D) está errada. A alternativa (E) está correta, pois a notação O maiúsculo representa o limite superior justo das funções. E se as funções f f () é equivalente, podemos dizer que g tem o limite superior O(g()) e g() é O(f ()) e Página 5 de 27 www.handbookdeti.com.br justo entre elas de maneira Handbook de Questões de TI Comentadas para Concursos 2. Volume questões de TI Assuntos relacionados: Algoritmos, Complexidade de Algoritmos, Banca: Cesgranrio Instituição: Petrobras Cargo: Analista de Sistemas Pleno - Processos Ano: 2006 Questão: 56 Considere os algoritmos a seguir e as suas correspondentes complexidades indicadas. Estão corretas apenas as complexidades indicadas para os algoritmos: I Busca seqüencial de um elemento em um vetor de tamanho N O(N ) II Busca, via pesquisa binária, de um elemento, em um vetor de tamanho N O(log2N ) III Busca de um rótulo de um nó em uma árvore binária completa, com N nós O(log2N ) IV Busca de um rótulo de um nó em uma árvore binária de busca, com N nós O(N ) V Inclusão de um elemento em um vetor ordenado de tamanho N, mantendo-se a ordenação O(1) (a). I, II e III. (b). I, II e IV. (c). II, III e V. (d). II, III, IV e V. (e). I, III, IV e V. Solução: A complexidade algorítmica é uma medida que expressa a eciência de um algoritmo em termos da quantidade de operações relevantes realizadas pelo algoritmo até que ele alcance o seu resultado nal. Exemplos de operações que podem ser consideradas relevantes para um algoritmo são as operações de comparação, operações aritméticas, operações de movimentação de dados etc. A complexidade algorítmica é então expressa em função do tamanho do problema. Em um problema que envolva a ordenação de um vetor, por exemplo, o tamanho do problema seria o tamanho do vetor. Em um problema que envolva a busca por um elemento em uma árvore binária, o tamanho do problema seria a quantidade de elementos contidos na árvore. É comum que se utilize a letra N para expressar o tamanho de um determinado problema. Boa parte das vezes, na avaliação da complexidade de um algoritmo, interessa ao avaliador descobrir qual será a complexidade do algoritmo quando for submetido a uma entrada de dados que o faça operar em seu pior caso, ou seja, que o faça executar o maior número de operações até que se alcance o resultado nal. No estudo da complexidade algorítmica, tal valor é denotado pela notação O. Se um algoritmo, no seu pior caso, precisa executar N operações, diz-se que sua complexidade é O(N ). Já se, em seu pior caso, ele executa um número de operações constate, diz que ele possui complexidade O(1). Agora, vamos analisar cada uma das correspondências algoritmo/complexidade e vericar quais delas estão corretas. (I) CORRETA Página 6 de 27 www.handbookdeti.com.br Handbook de Questões de TI Comentadas para Concursos Volume questões de TI Uma busca sequencial é aquela em que o vetor é percorrido a partir de uma extremidade no sentido da outra até que o elemento procurado seja encontrado. Imaginando o caso em que o elemento procurado seja o último elemento a ser avaliado em um vetor de tamanho N, para que se encontre tal elemento o algoritmo precisará executar N operações de comparação. Com isso, o pior caso de tal algoritmo é O(N ). (II) CORRETA O processo de busca binária inicia-se com a escolha de um elemento chamado pivot, localizado no centro do vetor. Caso o elemento procurado seja menor que o pivot, somente o sub vetor da esquerda será pesquisado. Caso contrário, somente o sub vetor da direita será pesquisado. E assim, a cada etapa, o escopo da busca é divido pela metade. No limite, o número máximo de divisões que poderão acontecer até que o elemento procurado seja eleito como pivot é o valor do logaritmo de N na base 2. Portanto, o pior caso da busca binária é O(log2 N ). (III) ERRADA Em processo de busca por um elemento em uma árvore binária, a particionamento do escopo de busca é determinado pelo fato de o elemento procurado ser maior ou menor que o nó corrente da árvore. Caso o elemento seja maior, a busca prossegue explorando apenas o ramo à direita do nó. Caso contrário, o processo prossegue explorando o ramo à esquerda. Aparentemente, o processo é bem semelhante ao processo de pesquisa binária. No entanto, pode acontecer de existir árvore binárias mal balanceadas, podendo chegar ao extremo de a árvore possuir uma única ramicação para um único lado. Nessa situação, como a navegação na árvore se dá necessariamente apenas entre nós conectados, pode acontecer de o processo de busca ter que percorrer todo a ramicação, desde a raiz até a folha, passando por todos os nós internos. Esse seria, portanto, o pior caso da busca em uma árvore binária, no qual seriam necessárias N operações de comparação. Portanto, a complexidade de tal algoritmo no pior caso é O(N ). (IV) CORRETA Nesta armativa, a situação é exatamente a ilustrada no item anterior, onde foi mostrado que a complexidade da busca em uma árvore binária no pior caso é O(N ). (V) ERRADA O processo de inclusão de um elemento em um vetor ordenado de tamanho N jamais poderia possuir complexidade O(1), ou seja, ser realizado com um número constante de operações. Isso se deve ao simples fato de que, para determinar em que posição o elemento deverá ser inserido para que se mantenha a ordenação, será necessário antes realizar um processo de busca que, se implementado da forma mais eciente possível (no caso, através de uma busca binária), teria complexidade O(log2 N ). Portanto, como apenas as armativas I, II e IV estão corretas, a resposta da questão é a alternativa B. Página 7 de 27 www.handbookdeti.com.br Handbook de Questões de TI Comentadas para Concursos 3. Volume questões de TI Assuntos relacionados: Métodos de Busca, Pesquisa Binária, Árvore B, Banca: CESGRANRIO Instituição: BNDES Cargo: Analista de Suporte Ano: 2008 Questão: 50 Os dados de uma agenda contendo nome, telefone e endereço de pessoas estão organizados em um arquivo de dados com acesso somente de leitura. Um dispositivo eletromecânico D, que possibilita acesso direto, contém, aproximadamente, 90 milhões de registros ordenados por nome. Assumindo que o tamanho do campo endereço é variável e que D pode ter arquivos (pré-existentes) de índices que se referenciam ao arquivo de dados, e supondo que não possui cache, qual é a estratégia que realizará, em média, menos operações de I/O para consultar todos os registros cujo nome começa por uma determinada letra? (a). Pesquisa binária diretamente sobre o arquivo de dados, uma vez que já existe ordenação por nome. (b). Pesquisa sobre o arquivo de índices indexados pelo nome, implementando um algoritmo de busca em uma árvore B-Tree balanceada. (c). Pesquisa seqüencial sobre um arquivo de índices indexado pelas letras do alfabeto e posterior leitura sequencial sobre o arquivo de dados, nos quais cada índice aponta para o endereço do início da respectiva letra na agenda. (d). Pesquisa binária sobre um arquivo de índices indexado pelo nome, para posterior acesso ao arquivo de dados. (e). Leitura seqüencial diretamente sobre o arquivo de dados, sem a utilização de arquivos auxiliares de índice. Solução: (A) ERRADA Para que fosse possível pesquisa binária diretamente sobre arquivo de dados, como seus registros tem tamanhos variáveis, seria necessário incluir informações que serviriam de ponteiros em cada registro. O que não é possível, já que o arquivo de dados permite apenas leitura. Portanto, a alternativa A não é possível. (B) ERRADA De maneira geral, a abordagem por B-Tree é uma boa opção. Entretanto, é importante observar que para recuperar cada registro é necessária uma consulta à B-Tree e posteriormente ao arquivo de dados. Tal implementação utilizaria um número de operações da ordem (n/26)/*log(n), onde n é o número total de registros. Analisaremos as outras opções adiante. Note que a opção nem explicitou como seria o acesso ao arquivo de dados. (C) CORRETA Essa é uma opção bem eciente para o caso, já que será necessário apenas encontrar a letra do alfabeto correspondente (mesmo que de maneira sequencial) no arquivo de índices e depois percorrer sequencialmente o arquivo de dados. A ordem neste caso é 13+n/26. Ou seja, mais rápido que o caso descrito na alternativa B. Página 8 de 27 www.handbookdeti.com.br Handbook de Questões de TI Comentadas para Concursos Volume questões de TI (D) ERRADA O caso e o custo são muito parecidos com aqueles explicitados na alternativa B e, como consequência, o seu resultado não supera o desempenho descrito na alternativa C. (E) ERRADA Neste caso, a ordem seria percorrer o arquivo de dados até encontrar o primeiro registro cujo nome começa com a letra especicada e depois percorrer todos os elementos que atendam a condição. O custo seria da ordem n/2+n/26. Concluímos que a alternativa mais eciente é a alternativa C. Página 9 de 27 www.handbookdeti.com.br Handbook de Questões de TI Comentadas para Concursos 4. Volume questões de TI Assuntos relacionados: Busca Binária, Busca Sequencial, Banca: FCC Instituição: MPU Cargo: Analista de Desenvolvimento de Sistemas Ano: 2007 Questão: 36 Considere: I. Os algoritmos de busca binária e de busca seqüencial executam processamento repetitivo. II. Os algoritmos de busca binária e de busca seqüencial utilizam a técnica de recursão. III. A busca seqüencial executa cada fase da repetição na forma de uma subtarefa da fase anterior. IV. A busca binária trabalha com uma forma circular de repetição. Está correto o que consta em (a). I, apenas. (b). II, apenas. (c). I e II, apenas. (d). I, III e IV, apenas. (e). I, II, III e IV. Solução: Os algoritmos de busca binária e de busca sequencial são técnicas para localizar um valor em particular em uma lista. A pesquisa ou busca binária (em inglês binary search ou binary chop ) é um algoritmo de busca que parte do pressuposto de que os elementos da lista já estão ordenados. O algoritmo de busca binária é um exemplo clássico de dividir-e-conquistar e sua ideia principal consiste em analisar o elemento do meio da lista para inferir se o elemento que está sendo procurado está depois ou antes desse elemento e, assim sucessivamente, dividir o espaço de busca por dois. Já o algoritmo de busca sequencial, ou busca linear como também é conhecido, percorre a lista, elemento por elemento, vericando se o elemento desejado está presente. Note que não é preciso no algoritmo de busca sequencial que a lista esteja ordenada. Ambos algoritmos necessitam de explorar o processamento repetitivo, que em linguagem de programação pode ser implementado tanto em laços de iteração (for, loop, while etc) tanto como de maneira recursiva. Vamos analisar as alternativas de I a IV para chegarmos na resposta. (I) Está correta, pois ambos algoritmos executam o processamento repetitivo. O termo processamento repetitivo é usualmente utilizado para denotar o uso repetitivo das operações de computador, o que é o nosso caso, já que esses algoritmos utilizarão repetitivamente operações de comparação entre dois valores. (II) Está errada, pois, mesmo que ambos algoritmos possam ser implementados de forma recursiva, ambos também podem ser implementados com o uso de laços iterativos. Logo, a Página 10 de 27 www.handbookdeti.com.br Handbook de Questões de TI Comentadas para Concursos Volume questões de TI técnica de recursão não é necessária e as ideias desses algoritmos não se baseiam na maneira de como eles serão implementados e, sim, de que maneira os dados da lista serão tratados. A alternativa se tornaria correta se utilizassem o predicado podem utilizar a técnica de recursão. (III) Está errada, o algoritmo que utiliza a ideia de dividir em subtarefas é o algoritmo de busca binária e não o de busca sequencial. (IV) Errada, pois a técnica de busca binária utiliza a ideia do dividir-e-conquistar, que não tem relação com repetição circular. Como somente (I) está correta, a letra (A) é a letra ser marcada nesta questão. Página 11 de 27 www.handbookdeti.com.br Handbook de Questões de TI Comentadas para Concursos 5. Volume questões de TI Assuntos relacionados: Estruturas de Dados, Árvores Binárias, Árvore Binária de Busca, Banca: Cesgranrio Instituição: Petrobras Cargo: Analista de Sistemas Pleno - Processos Ano: 2006 Questão: 50 Insira as chaves Lina, Ana, Lia, Ada, Lua, Sol, Cris, Bia, Rita, Mel, Rosa, Val em uma árvore binária de busca (considere que a árvore está inicialmente vazia). Considere agora, a execução dos seguintes percursos sobre a estrutura após a inserção das chaves. I - Um percurso em pré-ordem seria: Ada, Bia, Cris, Lia, Ana, Mel, Rosa, Rita, Val, Sol, Lua, Lina II - Um percurso em ordem simétrica seria: Val, Sol, Rosa, Rita, Mel, Lua, Lina, Lia, Cris, Bia, Ana, Ada III - Um percurso em nível seria: Lina, Ana, Lua, Ada, Lia, Sol, Cris, Rita, Val, Bia, Mel, Rosa IV - Um percurso em pós-ordem seria: Lina, Ana, Ada, Lia, Cris, Bia, Lua, Sol, Rita, Mel, Rosa, Val Estão corretos apenas os percursos indicados em: (a). I e II. (b). II e III. (c). I, II e III. (d). I, II e IV. (e). II, III e IV. Solução: Classicamente, uma árvore binária é denida como uma estrutura de dados com as seguintes características: • não ter elemento algum (uma árvore vazia); • ter um elemento distinto (nó raiz da árvore), com dois ponteiros para estruturas distintas, denominadas sub-árvore esquerda e sub-árvore direita. Cada um dos dois nós sub-sequentes a um nó raiz (nó da esquerda e nó da direita) são chamados lhos do nó raiz. Uma árvore binária de busca (ou árvore de busca binária ou árvore de pesquisa binária) é organizada em uma árvore binária, sendo uma estrutura onde todos os nós possuem chaves que são valores e, por padrão, os nós à esquerda formam uma sub-árvore com valores inferiores ao do nó raiz e os nós à direita formam uma sub-árvore com valores superiores ao do nó da raiz. Assim, as chaves em uma árvore binária de busca são sempre armazenadas satisfazendo à propriedade de árvore de pesquisa binária: Seja x um nó em uma árvore binária de busca. Se y é um nó na sub-árvore esquerda de x, então chave[y] <= chave[x]. Se y é um nó na sub-árvore direita de x, então chave[x] <= chave[y]. Página 12 de 27 www.handbookdeti.com.br Handbook de Questões de TI Comentadas para Concursos Volume questões de TI Essa propriedade orienta tanto a busca por valores na árvore quanto a inserção de novos nós, que são operações recorrentes nessa estrutura de dados. Uma outra operação interessante, que permite a impressão de todos os valores armazenados em uma árvore binária de busca, é chamada de percurso e pode-se dar, de acordo com a literatura comumente encontrada, de três formas distintas: percurso de árvore em ordem (ou em ordem simétrica), percurso de árvore de pré-ordem (ou em pré-ordem) e percurso de árvore de pós-ordem (ou em pós-ordem). Há, ainda, autores que registram um quarto tipo de percurso conhecido como percurso em largura (ou percurso em nível). No percurso de árvore em ordem simétrica, a chave da raiz de uma sub-árvore é impressa entre os valores de sua sub-árvore esquerda e aqueles de sua sub-árvore direita. Semelhantemente, o percurso de árvore de pré-ordem imprime a raiz antes dos valores em uma ou outra sub-árvore, e o percurso de árvore de pós-ordem imprime a raiz depois dos valores contidos em suas sub-árvores. Esses três tipos de percurso, denidos recursivamente, são considerados percursos em profundidade. O percurso em nível (percurso em largura), mais bem compreendido de forma não-recursiva, visita os nós na ordem em que aparecem nos níveis da árvore: primeiramente, são visitados todos os nós do nível 0; em seguida, visitam-se os nós do próximo nível; e assim por diante. Em geral, os nós são visitados da esquerda para a direita em cada um dos níveis. Dadas as informações apresentadas na questão, tem-se a seguinte árvore binária de busca: Figura 1: exemplo de gura. Como Lina é o primeiro valor apresentado à árvore binária de busca que está inicialmente vazia, ele é considerado a raiz da árvore principal. O valor seguinte, Ana, é considerado menor do que o anterior (critério: ordem alfabética) e, portanto, deverá ser inserido à esquerda do nó raiz. O valor seguinte, Lia, também é inferior ao valor da raiz e, consequentemente, será inserido à esquerda do mesmo. Como é superior ao valor Ana já presente, situar-se-á à direita do mesmo. E assim por diante. Um percurso em pré-ordem (isto é, um percurso no qual a raiz é visitada antes de seus lhos) é Lina, Ana, Ada, Lia, Cris, Bia, Lua, Sol, Rita, Mel, Rosa, Val. Observa-se que a raiz de cada (sub-)árvore é visita antes de seus lhos (Lina vem antes de Ana e Lua, Ana vem antes de Ada e Lia, e assim sucessivamente) e na sequência visitam-se primeiramente os lhos da esquerda e, em seguida, os lhos da direita. A outra opção para um percurso em pré-ordem, agora visitando os lhos da direita antes dos lhos da esquerda, é Lina, Lua, Sol, Val, Rita, Rosa, Mel, Ana, Lia, Cris, Bia, Ana. Página 13 de 27 www.handbookdeti.com.br Handbook de Questões de TI Comentadas para Concursos Volume questões de TI Um percurso em ordem simétrica (isto é, um percurso no qual a raiz aparece entre seus lhos) é Ada, Ana, Bia, Cris, Lia, Lina, Lua, Mel, Rita, Rosa, Sol, Val. Considerou-se a visita aos lhos da esquerda antes dos lhos da direita. A ordem inversa, ou seja, lhos da direita antes dos lhos da esquerda, também é possível: Val, Sol, Rosa, Rita, Mel, Lua, Lina, Lia, Cris, Bia, Ana, Ada. Para a árvore dada, um percurso em pós-ordem (isto é, a raiz é visita após seus lhos), visitando primeiramente os lhos da esquerda, é Ada, Bia, Cris, Lia, Ana, Mel, Rosa, Rita, Val, Sol, Lua, Lina. Visitando os lhos da direita antes dos lhos da esquerda, o outro percurso em pós-ordem é Val, Rosa, Mel, Rita, Sol, Lua, Bia, Cris, Lia, Ada, Ana, Lia. Para o percurso em nível, tem-se Lina, Ana, Lua, Ada, Lia, Sol, Cris, Rita, Val, Bia, Mel, Rosa como um percurso que realiza uma visita aos lhos da esquerda antes dos lhos da direita. Inversamente, visitando os lhos da direita primeiramente, obtêm-se Lina, Lua, Ana, Sol, Lia, Ada, Val, Rita, Cris, Rosa, Mel, Bia. Apenas as assertivas II e III condizem com a teoria exposta. As demais, buscam confundir o candidado, embaralhando resultados possíveis (a assertiva I é um percurso em nível e a assertiva IV apresenta um percurso em pré-ordem). Desta forma, a resposta da questão é a letra (B). Página 14 de 27 www.handbookdeti.com.br Handbook de Questões de TI Comentadas para Concursos 6. Volume questões de TI Assuntos relacionados: Algoritmos de Ordenação, Heapsort, Ordenação por Árvore de Decisão, Ordenação por Comparação, Quicksort, Ordenação por Inserção, Ordenação por Intercalação, Banca: CESGRANRIO Instituição: Petrobras Cargo: Analista de Sistemas - Eng. de Software Ano: 2008 Questão: 56 Sobre o algoritmo de ordenação heapsort, assinale a armação correta. (a). Utiliza ordenação por árvore de decisão, ao invés de ordenação por comparação. (b). A estrutura de dados que utiliza, chamada heap, pode ser interpretada como uma árvore binária. (c). Seu desempenho de pior caso é pior do que o do algoritmo quicksort. (d). Seu desempenho de pior caso é o mesmo da ordenação por inserção. (e). Seu desempenho de pior caso é menor do que o da ordenação por intercalação. Solução: O Heapsort utiliza uma estrutura de dados chamada heap binário (árvore binária mantida na forma de vetor) para ordenar os elementos a medida que os insere na estrutura. Dessa forma, ao nal das inserções, os elementos podem ser sucessivamente removidos da raiz da heap, na ordem desejada. Para uma ordenação crescente, deve ser construída uma heap máxima (o maior elemento ca na raiz). Já para uma ordenação decrescente, deve ser construída uma heap mínima (o menor elemento ca na raiz). Em resumo, as principais características desse algoritmo são: • ordenação por seleção; • heap gerada e mantida no próprio vetor a ser ordenado (utilização eciente da memória); • complexidade (em qualquer caso: pior, médio ou melhor): O(n log n); • consumo de memória ao construir a árvore; • não é indicado para vetores pequenos por conta do tempo de construção da árvore. (A) ERRADA Algoritmos que se baseiam apenas em comparações entre os elementos de entrada para efetuarem ordenações são denominados algoritmos de ordenação por comparação. Os algoritmos Heapsort, Quicksort e Ordenação por Intercalação (Mergesort) são alguns exemplos desse tipo de algoritmo. Uma árvore de decisão representa, de modo abstrato, as comparações executadas por um algoritmo de ordenação. Suas principais propriedades são: é uma árvore binária; possui no mínimo n! folhas (para n igual ao número de elementos a serem ordenados); cada folha contém uma permutação dos dados de entrada. O caminho mais longo da árvore representa o pior caso de execução do algoritmo. É sempre possível construir uma árvore de decisão para algoritmos de ordenação por comparação. Essa construção é realizada da seguinte forma: Página 15 de 27 www.handbookdeti.com.br Handbook de Questões de TI Comentadas para Concursos Volume questões de TI • xe o n; • verique qual é a primeira comparação do algoritmo, que pode resultar em sim ou não. Nesse passo, é necessário saber quais são os índices que estão sendo comparados; • a primeira comparação é colocada na raiz da árvore de decisão, incluindo os arcos sim e não; • repita os passos anteriores para cada nó da árvore. Em cada comparação, é necessário saber quais são os índices que estão sendo comparados. Observe que sempre se deve analisar os índices originais, ou seja, não devem ser consideradas as trocas de índices ocorridas durante a execução do algoritmo. Tendo em vista os conceitos apresentados, conclui-se que o algoritmo Heapsort pode ser representado por uma árvore de decisão, já que é um dos algoritmos que realiza ordenação por comparação. Portanto, essa alternativa está errada. (B) CORRETA Considerando a explicação apresentada acima, se torna fácil concluir que é essa a alternativa correta. (C) ERRADA Seu desempenho no pior caso (igual ao do melhor ou médio caso) é O(n log n). Esse é o melhor resultado dentre os algoritmos baseados em comparações. Esse conhecimento já bastaria para concluir que essa alternativa está incorreta. As complexidades do algoritmo Quicksort são O(nlogn) para o melhor caso e O(n2 ) para o pior caso. É sempre importante ter em mente que quanto mais eciente for a escolha do pivot, mais eciente será o desempenho da ordenação do algoritmo Quicksort. (D) ERRADA No pior caso, a ordenação por inserção apresenta complexidade igual a caso são necessárias n(n − 1)/2 ≈ O(n2 ), pois nesse (n2 )/2 comparações. Esse cenário sempre ocorre quando a sequência de entrada está ordenada na ordem inversa à desejada. (E) ERRADA Também chamado de Mergesort, o algoritmo de ordenação por intercalação, um algoritmo recursivo, se utiliza da técnica dividir para conquistar. Sua idéia básica é que é mais fácil criar uma sequência ordenada a partir de duas outras também ordenadas. Para isso, ele divide a sequência original em pares de dados, as ordena, depois as agrupa em sequências de quatro elementos, e assim por diante, até ter toda a sequência dividida em apenas duas partes. Sua complexidade tanto para o pior quanto para o melhor caso é O(n log n). Seu ponto fraco é a baixa eciência na utilização de memória, complexidade espacial O(n). Contudo, existe uma variante desse algoritmo que realiza a ordenação no próprio vetor de entrada, ou seja, complexidade espacial O(1), mas a sua implementação é extremamente complicada. Página 16 de 27 www.handbookdeti.com.br Handbook de Questões de TI Comentadas para Concursos 7. Volume questões de TI Assuntos relacionados: Programação, Algoritmos de Ordenação, Banca: FCC Instituição: TRT 15a Região Cargo: Analista Judiciário - Tecnologia da Informação Ano: 2009 Questão: 21 São algoritmos de classicação por trocas apenas os métodos (a). SelectionSort e InsertionSort. (b). MergeSort e BubbleSort. (c). QuickSort e SelectionSort. (d). BubbleSort e QuickSort. (e). InsertionSort e MergeSort. Solução: Os algoritmos de ordenação são uns dos principais objetos de estudo na área de computação. Tais algoritmos tem por objetivo colocar os elementos de uma sequência em uma determinada ordem, sendo as mais utilizadas as ordens numéricas e alfabéticas. Uma das principais razões para se ordenar uma sequência é permitir que os seus elementos sejam acessados de forma mais eciente. Os métodos de ordenação mais conhecidos e utilizados são os seguintes: • Ordenação por Troca • InsertionSort (Método da Inserção Direta) BinaryInsertionSort (Método da Inserção Direta Binária) Ordenação por Seleção • QuickSort (Método da Troca e Partição) Ordenação por Inserção • BubbleSort (Método da Bolha) SelectionSort (Método da Seleção Direta) HeapSort (Método da Seleção em Árvore) Outros métodos MergeSort (Método da Intercalação) BucketSort (Método da Distribuição de Chave) CountingSort (Método da Ordenação por Contagem) Como podemos ver, dentre os métodos apresentados nas alternativas da questão, os únicos baseados na ordenação troca são o BubbleSort e o QuickSort. Portanto, a resposta da questão é a alternativa D. Tais algoritmos são classicados como de troca por que seus processos de ordenação se dão através de trocas entre pares de elementos do vetor. Embora o BubbleSort e o QuickSort se baseiem em trocas, seu funcionamento geral e o seu desempenho diferem substancialmente. O BubbleSort é, talvez, o método simples de ordenação, que funciona através de sucessivas trocas entre pares de elementos do vetor. O método realiza varreduras no vetor, trocando pares adjacentes de elementos sempre que o próximo elemento for menor que o anterior. Página 17 de 27 www.handbookdeti.com.br Handbook de Questões de TI Comentadas para Concursos Volume questões de TI Após uma varredura, o maior elemento está corretamente posicionado no vetor e não precisa mais ser comparado. Dessa forma, após a i-ésima varredura, os i maiores elementos estão ordenados. A complexidade algorítmica de tempo do BubbleSort é O(n2 ). O Quicksort adota uma estratégia conhecida como divisão e conquista. Por isso, usual- mente, o Quicksort é implementado utilizando-se o paradigma recursivo. No primeiro passo do QuickSort, um elemento da lista é escolhido como pivô. Em seguida, a lista é rearranjada (por meio de trocas de posição entre os elementos) de modo que todos os elementos anteriores ao pivô sejam menores que ele, e todos os elementos posteriores ao pivô sejam maiores que ele. Ao m desse processo, que denomina-se particionamento, o pivô estará em sua posição nal e haverá duas sublistas não ordenadas. Em seguida, o algoritmo QuickSort é reaplicado a cada uma das sublistas, sendo a base da recursão as sublistas de tamanho zero ou um que, por denição, estão sempre ordenadas. O processo é nito, pois a cada iteração pelo menos um elemento é posto em sua posição nal e não será mais manipulado na iteração seguinte. A complexidade algorítmica de tempo do QuickSort é O(nlgn). A seguir, exemplos de implementação do bubble sort e do quicksort usando a linguagem de programação ruby. #BubbleSort em Ruby def bubblesort(list) return list if list.size <= 1 # already sorted loop do swapped = false 0.upto(list.size-2) do |i| if list[i] > list[i+1] list[i], list[i+1] = list[i+1], list[i] # swap values swapped = true end end break unless swapped end return list end #QuickSort em Ruby def quicksort (array) return array if array.size <= 1 pivot = array[0] return quicksort (array.select {|y| y < pivot }) + array.select { |y| y == pivot } + quicksort (array.select {|y| y > pivot }) end Página 18 de 27 www.handbookdeti.com.br Handbook de Questões de TI Comentadas para Concursos 8. Volume questões de TI Assuntos relacionados: Estruturas de Dados, Algoritmos de Ordenação, Banca: FCC Instituição: TRT 16a Região Cargo: Analista Judiciário - Tecnologia da Informação Ano: 2009 Questão: 35 São, respectivamente, um método de busca e um método de ordenação: (a). linear e por seleção direta. (b). por permutação e linear. (c). por seleção direta e por permutação. (d). por permutação e binária. (e). linear e binária. Solução: Os principais algoritmos de ordenação podem ser classicados em: ordenação por inserção, ordenação por troca, ordenação por seleção e ordenação por intercalação (permutação). Na ordenação por inserção, dividi-se o vetor em dois segmentos; o primeiro com os elementos já ordenados e o seguinte com o restante dos elementos ainda não ordenados. O primeiro elemento é colocado no primeiro segmento. Retira-se o primeiro elemento do segmento desordenado e insere-se no segmento ordenado em sua posição correta. Repete-se o processo para os demais elementos do vetor. A complexidade de tempo deste algoritmo é de O(n2 ). Exemplos de algoritmos de ordenação por inserção são a inserção direta e o incremento decrescente (Shell sort ). Na ordenação por troca, comparam-se dois elementos e trocam-se suas posições se o segundo elemento é menor do que o primeiro. A complexidade de tempo deste algoritmo é de O(n2 ). Exemplos de algoritmos de ordenação por troca são o método da bolha (buble e o método da troca e partição (quicksort ) Na ordenação por seleção, seleciona-se o menor item do vetor. sort ) Em seguida, troca esse elemento com o item que está na primeira posição do vetor. Repete-se este procedimento para o n−1 elementos restantes. A complexidade de tempo deste algoritmo é de O(n2 ). Exemplos de algoritmos de ordenação por seleção são a inserção direta e a inserção em árvore (heapsort ). Na ordenação por intercalação, dividi-se o vetor em madamente n/2. 2 sub-vetores de comprimento, aproxi- Ordena recursivamente cada sub-vetor (dividindo-se novamente, quando possível). Faz o merge dos 2 sub-vetores ordenados para obter o vetor ordenado completo. A complexidade de tempo deste algoritmo é de nação por intercalação é o O(nlog(n)). Exemplo de algoritmo de orde- mergesort. Os principais algoritmos de busca são classicados em linear e binário. O algoritmo de busca linear é a forma mais simples de se consultar um vetor em busca de um elemento. A busca é realizada da seguinte maneira: a partir do início do vetor, examina-se cada um de seus elementos até que o elemento desejado seja encontrado ou até que o nal do vetor seja atingido. A complexidade de tempo deste algoritmo é de Página 19 de 27 www.handbookdeti.com.br O(n). Handbook de Questões de TI Comentadas para Concursos Volume questões de TI O algoritmo de busca binária é aplicado quando os elementos de um vetor estão ordenados. A busca é realizada por meio de sucessivas divisões do espaço de busca (divisão e conquista), comparando o elemento buscado (chave) com o elemento no meio do vetor. Se o elemento do meio do vetor for a chave, a busca termina com sucesso. Caso contrário, se o elemento do meio vier antes do elemento buscado, então a busca continua na metade posterior do vetor. E nalmente, se o elemento do meio vier depois da chave, a busca continua na metade anterior do vetor. A complexidade de tempo deste algoritmo é de O(log2 (n)). De acordo com as alternativas desta questão, um método de busca e um de ordenação, respectivamente, é o linear e por seleção direta. Logo, a alternativa correta é Página 20 de 27 www.handbookdeti.com.br (A). Handbook de Questões de TI Comentadas para Concursos 9. Volume questões de TI Assuntos relacionados: Programação, Algoritmos de Ordenação, Método de Ordenação da Bolha, Bubble Sort, Banca: Cesgranrio Instituição: Petrobras Cargo: Analista de Sistemas Pleno - Processos Ano: 2006 Questão: 53 O seguinte algoritmo, chamado ordena, implementa um conhecido método de ordenação para listas seqüenciais: ordena (int vet[], int n) { int i, j, pos, aux; para ( i = 0; i < n - 1; i++ ){ pos = i; para ( j = i + 1; j < n; j++ ) se ( vet [pos] > vet [j] ) pos = j; se ( pos <> i ) { aux = vet[i]; vet[i] = vet[pos]; vet[pos] = aux; } } } Se o algoritmo for executado recebendo como parâmetros 5, 3, 1, 2, 4 e 5, quantas trocas são efetuadas e em que sentido é feita a ordenação (crescente ou decrescente)? (a). 4, crescente. (b). 6, crescente. (c). 9, crescente. (d). 4, decrescente. (e). 7, decrescente. Solução: O algoritimo de ordenação apresentado na questão é conhecido como bubblesort ou método da bolha. Entre os algoritmos de ordenação, o bubblesort é classicado como um algoritmo de ordenação por seleção e troca, pois o processo de ordenação baseia-se na comparação e na troca entre elementos em um vetor. O nome bubblesort tem origem em uma analogia feita com um tubo cheio de bolhas de diferentes tamanhos. Se o vetor de tamano N for imaginado na vertical, com elemento da posição N em cima e o elemento da posição 1 embaixo, durante cata etapa do processo de ordenação o menor elemento subirá até encontrar um elemento menor ainda, como se uma bolha subisse dentro de um tubo de acordo com sua densidade. Para analisar melhor o algoritmo, vamos adicionar numeros as linhas, para que possamos fazer referencia a cada um dos passos relevantes do algoritmo. Página 21 de 27 www.handbookdeti.com.br Handbook de Questões de TI Comentadas para Concursos Volume questões de TI 1 ordena (int vet[], int n) { 2 int i, j, pos, aux; 3 para ( i = 0; i < n - 1; i++ ){ 4 pos = i; 5 para ( j = i + 1; j < n; j++ ) 6 se ( vet [pos] > vet [j] ) 7 pos = j; 8 se ( pos <> i ) { 9 aux = vet[i]; 10 vet[i] = vet[pos]; 11 vet[pos] = aux; 12 } 13 } 14 } Na linha 4, é selecionado o elemento que será comparado na rodada corrente. Este processo é repetido para todos os elementos do vetor através do loop, implementado na linha 3. Já o loop implementado na linha 5, garante que o elemento corrente só seja comparado com os elementos que estão a sua frente no vetor. É na linha 6 que de fato ocorre a comparação entre os elementos. Por m, da linha 8 até a linha 12, ocorre o processo de troca de posição entre os elementos do vetor, de modo que o menor elemento que antes. Portanto, já podemos armar que o algoritmo irá executar colocar os elementos do vetor em ordem crescente. O que já elimina as alternativas D e E. Nos resta agora determinar o numero total de trocas que serão efetuadas quando o algoritmo for executado recebendo como parâmetros o vetor 5, 3, 1, 2, 4. Para isso, teremos que executar o algoritmo passo a passo, até que o vetor esteja completamente ordenado, momento a partir do qual não ocorreram mais trocas de posição entre os elementos. O passo a passo da execução é mostrado a seguir: Início i=0,j=4,pos=2 i=1,j=4,pos=3 i=2,j=4,pos=3 i=3,j=4,pos=4 :: :: :: :: :: vet vet vet vet vet = = = = = {5;3;1;2;4} {1;3;5;2;4} {1;2;5;3;4} {1;2;3;5;4} {1;2;3;4;5} Portanto, ocorreram 4 trocas no total, e o vetor será ordenado de forma crescente. isso, a resposta da questão é a alternativa A. Página 22 de 27 www.handbookdeti.com.br Com Handbook de Questões de TI Comentadas para Concursos 10. Volume questões de TI Assuntos relacionados: Algoritmos de Ordenação, Heapsort, Banca: ESAF Instituição: Secretaria do Tesouro Nacional (STN) Cargo: Analista de Finanças e Controle - Tecnologia da Informação / Desenvolvimento de Sistemas de Informação Ano: 2008 Questão: 24 Considere a execução do algoritmo de ordenação Heap (ou Heap Sort), em sua versão emlocal (in-place), ao arranjo 13, 18, 10, 8, 11. Qual é a saída gerada, após a execução dos três (3) primeiros passos do algoritmo? (a). 13, 18, 10, 11, 8 (b). 18, 13, 10, 11, 8 (c). 8, 13, 10, 11, 18 (d). 13, 10, 11, 8, 18 (e). 18, 13, 10, 8, 11 Solução: O Heap Sort (ou Heapsort) é um algoritmo de ordenação que faz uso de uma estrutura de dados chamada heap. Ele ordena localmente (in-place), signicando que apenas um número constante de elementos do arranjo é armazenado fora do arranjo de entrada em qualquer instante. Em outras palavras, um algoritmo in-place pode até utilizar estruturas auxiliares de dados, mas a quantidade dessas estruturas deve ser xa, e não relacionada (dependente) ao tamanho da estrutura de entrada. A estrutura de dados heap é um objeto arranjo que pode ser visto como uma árvore binária praticamente completa, sendo que cada nó dessa árvore corresponde a um elemento do arranjo que armazena o valor no nó. Um arranjo A, com uma quantidade de elementos denida por comprimento[A], tem por raiz o elemento A[1]. Dado o índice i de um nó, o índice de seu pai PARENT(i), do lho da esquerda LEFT(i) e do lho da direita RIGHT(i) podem ser calculados de modo simples. Existem dois tipos de heaps binários: heaps máximos e heaps mínimos. Os primeiros satisfazem a seguinte propriedade: A[PARENT(i)] ≥ A[i] isto é, o valor de um nó é no máximo o valor de seu pai. Desse modo, o maior elemento em um heap máximo é armazenado na raiz, e a subárvore que tem raiz em um nó contém valores menores que o próprio nó. Um heap mínimo, organizado de forma oposta, satisfaz a seguinte propriedade: A[PARENT(i)] ≥ A[i] sendo que sua raiz contém o menor elemento do arranjo. A Figura 2 ilustra uma estrutura heap máximo de 10 elementos para o arranjo A = [16, 14, 10, 8, 7, 9, 3, 2, 4, 1]. Página 23 de 27 www.handbookdeti.com.br Handbook de Questões de TI Comentadas para Concursos Volume questões de TI Figura 2: estrutura heap máximo de 10 elementos para o arranjo A = [16, 14, 10, 8, 7, 9, 3, 2, 4, 1]. Quando um novo elemento é adicionado ao arranjo, é necessário manter a propriedade de heap, o que pode ser feito com as sub-rotinas MAX-HEAPFY e MIN-HEAPFY. Para o caso de um heap máximo, tem-se: MAX-HEAPFY(A, i) l ← LEFT(i) R ← RIGHT(i) if l ≤ tamanho-do-heap[A] e A[l] > A[i] then maior ← l else maior ← i if r ≤ tamanho-do-heap[A] e A[r] > A[maior] then maior ← r if maior 6= i then trocar A[i] ↔ A[maior] MAX-HEAPFY(A, maior) Quando MAX-HEAPFY é chamada, supõe-se que as árvores binárias com raízes em LEFT(i) e RIGHT(i) são heaps máximos, mas que A[i] pode ser menor que seus lhos, violando assim a propriedade de heap máximo. A função de MAX-HEAPFY é possibilitar que o valor em A[i] ocupe o lugar adequado na estrutura, de tal forma que a subárvore com raiz no índice i se torne um heap máximo. É possível utilizar o procedimento MAX-HEAPFY para transformar um arranjo A[1..n], com n=comprimento[A], em um heap máximo. O procedimento BUILD-MAX-HEAP efetua tal operação: BUILD-MAX-HEAP(A) tamanho-do-heap[A] ← comprimento[A] for i ← b comprimento[A]/2 c downto 1 do MAX-HEAPFY(A, i) A Figura 3 ilustra o uso do procedimento BUILD-MAX-HEAP para o arranjo A=[4, 1, 3, 2, 16, 9, 10, 14, 8, 7]. Página 24 de 27 www.handbookdeti.com.br Handbook de Questões de TI Comentadas para Concursos Volume questões de TI Figura 3: uso do procedimento BUILD-MAX-HEAP para o arranjo A=[4, 1, 3, 2, 16, 9, 10, 14, 8, 7]. Observa-se que existe uma tendência de os valores do arranjo A carem ordenados após a execução do procedimento. Mas não há tal obrigatoriedade, pois a propriedade de heap máximo não tem relação com ordenação. Entretanto, é possível utilizar os dois procedimentos previamente apresentados para ordenar o arranjo A. E é essa a função do algoritmo Heap Sort. HEAPSORT(A) BUILD-MAXHEAP(A) for i ← comprimento[A] downto 2 do trocar A[1] ↔ A[i] tamanho-do-heap[A] ← tamanho-do-heap[A] 1 MAX-HEAPFY(A, 1) Para os dados apresentados na questão, A = [13, 18, 10, 8, 11], tem-se a sequência de processamento apresentada na Figura 4. Página 25 de 27 www.handbookdeti.com.br Handbook de Questões de TI Comentadas para Concursos Volume questões de TI Figura 4: sequência de processamento do algoritmo de ordenação Heap ao arranjo 13, 18, 10, 8, 11. Infelizmente, a questão não especica o signicado de passo, de sorte que ca difícil para o candidato denir saídas. Questão prejudicada. Página 26 de 27 www.handbookdeti.com.br Handbook de Questões de TI Comentadas para Concursos Questão 1 2 3 4 5 6 7 8 9 10 Página 27 de 27 Volume questões de TI Resposta E B C A B B D A A E Handbook de TI Além do Gabarito Índice Remissivo Árvore B, 8 Árvore Binária de Busca, 12 Árvores Binárias, 12 Algoritmos, 4, 6 Algoritmos de Ordenação, 15, 17, 19, 21, 23 Bubble Sort, 21 Busca Binária, 10 Busca Sequencial, 10 Complexidade de Algoritmos, 4, 6 Estruturas de Dados, 12, 19 Heapsort, 15, 23 Método de Ordenação da Bolha, 21 Métodos de Busca, 8 Ordenação por Árvore de Decisão, 15 Ordenação por Comparação, 15 Ordenação por Inserção, 15 Ordenação por Intercalação, 15 Pesquisa Binária, 8 Programação, 17, 21 Quicksort, 15 28