Você está na página 1de 7

Universidade Federal de Viçosa INF 610 – Estrutura de dados e algoritmos

Departamento de Informática Lista de exercícios 01


Prof.: Fabio R. Cerqueira 22 de abril de 2011
Análise de algoritmos e estrutura de dados

Entrega em 02/05/2011

1) Calcule os seguintes somatórios:

2) Resolva as seguintes relações de recorrência:

a) x(n) = x(n-1) + 5 para n > 1, x(1) = 0

b) x(n) = 3x(n-1) para n > 1, x(1) = 4

3) Para as funções a seguir, indique de quanto o valor de cada uma será alterado se o argumento for
incrementado em quatro vezes.

4) Prove formalmente as seguintes proposições:

5) Considere o algoritmo abaixo:

a) O que este algoritmo calcula?


b) Qual é sua operação básica?
c) Quantas vezes a operação básica é executada?
d) Dê a complexidade assintótica deste algoritmo?

6) Considere o algoritmo abaixo:

Responda os itens de (a) a (d) da questão anterior.

7) Considere o algoritmo abaixo:

Responda os itens de (a) a (d) da questão anterior.

8) Considere o seguinte algoritmo recursivo para computar o somatório: S(n) = 13 + 23 + … + n3.

a) Monte e resolva uma relação de recorrência para o número de vezes que a operação básica
do algoritmo é executada.

b) Dê a complexidade assintótica do algoritmo.

c) Mostre um algoritmo não-recursivo para realizar a mesma computação e compare sua


complexidade com a complexidade do algoritmo recursivo.

9) Mostre formalmente a complexidade de pior caso da operação de inserção em listas estáticas


contíguas.
10) Considerando a lista simplesmente encadeada estática vista em sala, faça uma função que receba
duas listas e concatene os elementos da segunda ao final da primeira.

11) Para resolver a questão a seguir considere a pilha estática vista em sala. O seguinte método para
codificar despachos diplomáticos foi adotado:
▪ Primeira etapa: todas as sequencias não vogais, incluindo o espaço em branco e os caracteres
de pontuação, são invertidas;
▪ Segunda etapa: a mensagem inteira resultante é invertida dando origem à mensagem
codificada.

Por exemplo, a mensagem original:


PROBLEMAS HIPER-INTERESSANTES.
passa a ser, após a primeira etapa:
RPOLBEMAH SIPE-RITNERESSATNE.S
e é codificada, após a segunda etapa, como:
S.ENTASSERENTIR-EPIS HAMEBLOPR

O embaixador recebeu uma mensagem codificada como se segue:


TS.ECOXES ES TRIAR MAMPRO CEUGENSO CE SE. VENTERGU

Escreva um programa em C++, utilizando pilha de caracteres, que ajude o embaixador a


decodificar mensagens assim construídas.

12) Pesquise e descreva a estrutura de dados Fila de Prioridade.

13)Dada a estrutura de dados abaixo, que vimos em sala, para implementar uma lista simplesmente
encadeada dinâmica de inteiros em C++, crie uma função para inserir um nodo de forma ordenada.
A ordenação deve ser crescente. A assinatura da função é dada abaixo. Passa-se uma lista,
supostamente ordenada, por referência e o ponteiro para o nodo que se deseja inserir.

struct NodoLista {
int info;
NodoLista* prox;
};

struct Lista {
NodoLista* primeiro;
int tam;
};

// Assinatura da funcao insereOrdenado


int insereOrdenado(Lista& l, NodoLista* novo);
14) Dada a estrutura de dados abaixo, vista em sala de aula, para representar uma pilha dinâmica de
inteiros em C++, bem como a assinatura de suas funções (suponha as mesmas funcionando), faça
um programa para converter um número decimal em binário, utilizando uma pilha para empilhar os
restos das divisões por dois necessárias para a conversão.

struct NodoPilha {
int info;
NodoPilha* prox;
};

struct Pilha {
NodoPilha* topo;
};

// Inicia a pilha como vazia


void fazPilhaVazia(Pilha& p)

// retorna V se pilha vazia e F c.c.


int pilhaVazia(const Pilha& p)

// Aloca memoria para um nodo e retorna apontador


// para este. Se memoria cheia, retorna NULL
NodoPilha* criaNodo(int e)

// desaloca area ocupada por nodo apontado por p


void destroiNodo(NodoPilha* p)

// empilha nodo apontado por n


int empilha(Pilha* p, NodoPilha* n)

// desempilha e retorna ponteiro para nodo desempilhado


NodoPilha* desempilha(Pilha& p)

// retorna ponteiro para nodo do topo


NodoPilha* obtemTopo(const Pilha& p)

// imprime a pilha
void imprime(const Pilha& p)

// Desaloca toda a memoria ocupada pelos


// nodos da pilha
void destroi(Pilha& p)
15) Desenvolva um programa em C++, utilizando fila dinâmica, que permita gerir uma pista para
decolagem de aviões de um aeroporto. Para o correto funcionamento desta pista, é necessário que
sejam implementadas as seguintes funcionalidades:
• No de aviões à espera de decolar;
• Decolagem de um avião;
• Entrada de um novo avião para decolar;
• Listar todos os aviões (nome e numero) a espera de decolar;
• Listar as características (nome e numero) do próximo avião a decolar.

16) Pesquise e descreva a estrutura de dados hash.

17) Seja uma árvore de busca binária de inteiros inicialmente vazia. Esquematize o seu estado final,
após terem sido inseridos os elementos 4, 1, 0, 5, 3, 7, 2, 6, 9 e 8, nesta ordem.

18) Informe a ordem em que os elementos acima inseridos serão visitados utilizando os
atravessamentos:
• em-ordem;
• pós-ordem;
• pré-ordem.

19) Dada a estrutura de dados abaixo, que vimos em sala, para representar uma árvore de busca
binária de caracteres em C++, faça uma função recursiva que receba uma árvore de busca binária e
retorne o número de nodos não-terminais da mesma.

typedef struct NodoArvore* ArvoreBin;

struct NodoArvore {
char info; // arvore de caracteres
ArvoreBin subArvEsq;
ArvoreBin subArvDir;
};

20) Ainda baseado na estrutura de dados da questão anterior, faça uma função em C++ que retire o
maior elemento de uma árvore de busca binária.

21) Em sala de aula, demos a função em C++ abaixo para localizar um elemento numa árvore de
busca binária (baseada na estrutura de dados da questão 19). Mostre formalmente a complexidade
de pior caso deste procedimento. Suponha que a árvore esteja balanceada e completa.

NodoArvore* localiza(ArvoreBin arv, char elem) {


/* funcao para localizar um elemento na arvore binaria */
if (arvVazia(arv))
return NULL;
if (arv->info == elem)
return arv;
if (elem < arv->info)
return (localiza(arv->subArvEsq,elem));
else
return (localiza(arv->subArvDir,elem));
}

Vê-se então que a eficiência, para o pior caso, da localização em árvores de busca binária é
maior do que em listas (em que não haja nenhum tipo de ordenamento). É correto então dizer
que, entre uma e outra estrutura, sempre devemos preferir a primeira? Justifique.

22) Pesquise e descreva sucintamente a estrutura de dados Heap.

23) Pesquise e descreva sucintamente árvores digitais.

24) Pesquise e descreva sucintamente árvore B.

25) Implemente uma pilha genérica seguindo a mesma ideia vista para lista genérica.

26) Implemente uma fila genérica seguindo a mesma ideia vista para lista genérica.

27) Dada a estrutura de dados abaixo, vista em sala, para implementar uma árvore de busca binária
genérica em C++ (suponha que os métodos estejam devidamente implementados de acordo com o
que já vimos), mostre tudo que for necessário para implementar uma árvore de busca binária de
caracteres, a partir da árvore genérica abaixo. Mostre um pequeno programa que utilize sua árvore.
No seu programa, crie uma árvore, insira elementos, remova elementos, localize, imprima.

typedef class NodoArvBin* PNodoArv;

class NodoArvBin {
friend class ArvBin;
private:
ArvBin subArvEsq;
ArvBin subArvDir;
public:
NodoArvBin();
virtual ~NodoArvBin();
virtual void imprime();
virtual int compara(PNodoArv pArv);
};

class ArvBin {
private:
PNodoArv pRaiz;
PNodoArv tiraMenor();
public:
ArvBin();
~ArvBin();
int vazia();
void insere(PNodoArv pn);
void remove(PNodoArv pn);
PNodoArv localiza(PNodoArv pn);
void imprime();
void apagaArvore();
};