Você está na página 1de 13

Curso de Graduação em Engenharia da Computação

Disciplina: ESTRUTURA DE DADOS AVANÇADAS E ANÁLISES


Turma: 1INF35A Modalidade: Presencial Professor: André Lucio de Oliveira

ATIVIDADE INDIVIDUAL AVALIATIVA

Data de Entrega: 01/07/2020 (23:59)


Pontuação máxima: 10,0 (dez)
Forma de entrega: por e-mail (andre.oliveira@uva.br) no formato .pdf
OBS: O campo "Assunto" do e-mail deve ter o seguinte padrão:
 EDAA-ATIVIDADE_INDIVIDUAL_AVALIATIVA-NOME_COMPLETO_DO_ALUNO

OBS: Nas questões objetivas marquem a resposta escolhida utilizando a formatação de


"realce", conforme o exemplo a seguir:
a) opção 1
b) opção 2
c) opção 3
d) opção 4
e) opção 5

OBS: Nas questões objetivas, o aluno deve justificar a resposta escolhida e todas a
demais não escolhidas, apontando o que está certo/errado nas opções.

Especificação da atividade:

QUESTÃO 1 – Uma lista encadeada é uma estrutura que corresponde a uma sequência
lógica de entradas ou nós. Cada nó armazena a localização do próximo elemento na
sequência, ou seja, de seu nó sucessor.
Este tipo de estrutura é muito utilizado em diversas linguagens de programação, tais
como: C, C++, Java, C#, Python, etc. Em muitas destas linguagens já existem “bibliotecas
prontas” que oferecem os serviços fundamentais para manipular a lista de elementos, não
sendo necessário que os desenvolvedores se preocupem em desenvolvê-las.
Sabendo destas informações, podemos dizer que em uma lista encadeada, (marque a
opção correta) (0,8)

Universidade Veiga de Almeida - UVA Página 1 de 13


Curso de Graduação em Engenharia da Computação

a) para se estabelecer a ligação entre um nó já pertencente a uma lista e um novo nó,


basta fazer com que o novo nó referencie no campo next, o nó que anteriormente era
referenciado pelo nó original, desde que esse campo não tenha o valor nulo.
b) a existência de um ponteiro apontando para o 1º elemento e outro para o fim da lista
permite que a inserção ou deleção de dados de um nó que esteja no meio da lista seja
rapidamente executada.
c) enquanto a entrada que determina o topo da lista é mantida em um nó descritor dessa
lista, a entrada que marca o fim da lista é mantida fora do descritor.
d) o armazenamento de uma lista requer uma área contígua de memória para permitir a
otimização no processamento de criação e remoção de nós da lista.
e) o armazenamento de uma lista não requer uma área contígua de memória. Como listas
são estruturas dinâmicas, normalmente são definidos procedimentos que permitem criar e
remover nós na memória.
R:
A) O novo nó deverá apontar para NULL quando for feita a inserção no fim da lista,
No caso da inserção no meio da lista ou inicio, o novo nó deve apontar para o next do
anterior e o anterior da posição a ser inserida deve apontar para o novo nó, concluindo
assim a inclusão na lista.
B) Um ponteiro apontando para o inicio e fim da lista, pode até ajudar em algumas
operações, mas para a busca no meio da lista, não fará com que o processo seja executa
rapidamente.
C) Questão um pouco confusa e está relacionado com pilha
D) Como cada registro armazena o endereço do próximo elemento, cada registro pode
estar em qualquer local da memória.
E) Conforme explicação da alternativa D, lista não requer uma área contígua de memória.

Universidade Veiga de Almeida - UVA Página 2 de 13


Curso de Graduação em Engenharia da Computação

QUESTÃO 2 – Em uma implementação de listas por meio de apontadores, cada item da


lista é encadeado com o seguinte, mediante uma variável do tipo apontador. Sobre listas
encadeadas, analise as assertivas e, em seguida, assinale a alternativa que apresenta as
corretas (0,7).

I. Não é possível inserir e retirar elementos sem necessidade de deslocar os itens


seguintes da lista.
II. A implementação de listas por meio de apontadores permite utilizar posições não
contíguas de memória.
III. Uma das desvantagens deste tipo da implementação de listas, por meio de
apontadores, é a utilização de memória extra para armazenar os apontadores.
IV. Em aplicações em que não existe previsão sobre o crescimento da lista, é conveniente
utilizar listas encadeadas por apontadores, porque neste caso o tamanho máximo da lista
não precisa ser definido a priori.
a) As asserções I, II e III são proposições verdadeiras e a IV é falsa.
b) As asserções I, II e IV são proposições verdadeiras e a III é falsa.
c) As asserções II, III e IV são proposições verdadeiras e a I é falsa.
d) As asserções I e II são proposições verdadeiras e III e IV são falsas.
e) As asserções III e IV são proposições verdadeiras e I e II são falsas.
R:
I. É possível inserir e retirar elementos, em uma lista ligada durante esse
processo, são atualizados os ponteiros que apontam para os outros registros
em memória.
II. Assim como na questão anterior, listas permitem a utilização de posições de
memória que não sejam contíguas.
III. Sim, todo registro irá carregar consigo um campo que armazena o endereço de
memória do elemento seguinte, em casos de listas duplamente ligadas ou lista
circulares, o uso da memória será até maior.
IV. Verdade, também com a utilização de alocação dinâmica de memória, não
precisamos definir o tamanho da lista, podendo excluir e limpar o registro da
memória ou criar um registro e inserir na lista a qualquer momento.

Universidade Veiga de Almeida - UVA Página 3 de 13


Curso de Graduação em Engenharia da Computação

QUESTÃO 3 – <Aplicação> Um aluno de graduação, chamado Antônio, recebeu um


desafio de implementar uma árvore binária de busca com as suas principais
funcionalidades. Antes de começar a desenvolver, resolveu primeiro estudar toda a parte
teórica sobre este assunto, desenhando uma árvore com a notação de grafos e
analisando a forma de inserção, exclusão e de percurso neste tipo de árvore. A primeira
árvore desenha por ee pode ser observada a seguir:

Considerando a árvore desenha por Antônio, responda:


a) Qual foi a política de inserção utilizada nesta árvore. Evite uma explicação muito
sucinta, apresentando com detalhes o que foi solicitado (0,2)?
b) Quantos nós, no mínimo, deveriam ser inseridos para tornar esta árvore cheia?
Redesenhe a árvore considerando a inserção destes possíveis nós (0,2).
c) Apresente a ordem de impressão dos elementos da árvore, considerando cada uma
das seguintes abordagens de percurso: pré-ordem, em ordem, pós-ordem e em nível
(0,5).
d) Qual seria uma possível implementação na linguagem C para um “nó” desta árvore?
(0,3).

R:
A) A politica de inserção foi que o 1º elemento será a raiz e o restante será alocado
conforme algoritmo, maior para a direita e menor para a esquerda.
B) Arvore cheia é quando cada nó tem 0 ou 2 filhos, deveria ser inserido 2 nós
deveriam ser inseridos, o valor 9 e 15 por exemplo ocupariam os espaços
necessários para se tornar uma arvore cheia.
C) Pré-ordem: 8 3 1 6 4 7 10 14 13
Em ordem: 1 3 6 4 7 8 10 14 13
Pós ordem: 1 3 6 4 7 10 14 13 8
D) Seria criado uma struct com ponteiros para esquerda e direita, e um valor chave,
criado o método de inserção e de leitura(Em ordem, pré-ordem, pós ordem) e seus
testes no método main

Universidade Veiga de Almeida - UVA Página 4 de 13


Curso de Graduação em Engenharia da Computação

QUESTÃO 4 – <Análise> Árvore, no contexto da programação, engenharia de software e


ciência da computação, é uma das mais importantes estruturas de dados não lineares. Este
tipo de estrutura herda as características da topologia em árvore.
Em uma definição mais formal, uma árvore é uma estrutura que contém um conjunto finito
de um ou mais nós, sendo que um dos nós é especialmente designado como o nó raiz e os
demais nós são particionados em 0 ou mais conjuntos disjuntos onde cada um desses
conjuntos é em si uma árvore, que recebe o nome de subárvore.
Sobre a estrutura de dados "Árvore", analise seguintes as afirmativas: (0,8).

I. A árvore é uma estrutura linear que permite representar uma relação de hierarquia. Ela
possui um nó raiz e subárvores não vazias.
II. Na árvore binária o percurso permite a obtenção da sequência linear de seus nós. Na
árvore binária de busca, um dos percursos permite que os nós sejam obtidos de forma
ordenada.
III. O processo de balanceamento (estático ou dinâmico) otimiza a busca em árvores
binárias, minimizando sua altura.
IV. Uma árvore-B não pode ser usada para armazenamento de dados em disco, pois
necessita de um número maior de nós (maior altura) quando comparada a uma árvore
binária.

Está correto o que se afirma em:


a) Todas as asserções são proposições verdadeiras.
b) Apenas as asserções II e III são proposições verdadeiras.
c) As asserções I e II são proposições verdadeiras, e as demais são falsas.
d) As asserções I e II são proposições falsas e a III e IV são verdadeiras.
e) Apenas a asserção II é uma proposição verdadeira

R:
I. As arvores são estruturas hierárquicas.
II. Como os registros são inseridos sempre analisando maior para a direita e o
menos para a esquerda, os registro são armazenados ordenados, fazendo com
que os nós sejam obtidos de forma ordenada.
III. O processo de balanceamento em arvores, proporciona uma arvore bem
estruturada e proporciona ganhos de processamento e otimização.
IV. Uma árvore B é uma estrutura de dados projetada para funcionar especialmente
em memória secundária como um disco magnético ou outros dispositivos de
armazenamento secundário.

Universidade Veiga de Almeida - UVA Página 5 de 13


Curso de Graduação em Engenharia da Computação

QUESTÃO 5 – <Análise> Árvore AVL é uma árvore binária de busca balanceada. O nome
AVL vem de seus criadores soviéticos Adelson Velsky e Landis, e sua primeira referência
encontra-se no documento “Algoritmos para organização da informação” de 1962. Uma
árvore binária T é denominada AVL quando, para qualquer nó de T, as alturas de suas
duas subárvores, esquerda e direita, diferem em módulo de até uma unidade. Baseado
nestas informações, qual das figuras de árvores mostradas a seguir representa uma
árvore do tipo AVL (0,8)?

R: A, D e E são uma arvore AVL pois as alturas são no máximo 1 , B e C não é uma
arvore AVL pois as alturas de cada arvore esquerda e direita são maiores que 1.

QUESTÃO 6 – Sobre uma árvore AVL, responda as seguintes questões:

a) Considerando a ordem de inserções, apresentadas na tabela seguir, em uma árvore binária do


tipo AVL, desenhe a árvore final resultante, descrevendo com detalhes os rebalanceamentos
através das rotações: RR, LL, RL e LR.

Ordem de Inserção Chave a ser Inserida


1 109
2 208
3 84
4 45
5 90
6 98

Universidade Veiga de Almeida - UVA Página 6 de 13


Curso de Graduação em Engenharia da Computação

7 95
8 92
9 122
10 266
11 212

OBS: A cada necessidade de rotação (desbalanceamento), redesenhe a árvore com a atualização


dos FBN (fator de desbalanceamento), indicando qual deve ser a rotação a ser executada e,
seguindo o passo a passo dos algoritmos de rotação (mostrados no final desta questão), torne a
árvore balanceada novamente. Os ponteiros pA, pB e PC devem ser mostrados na resposta da
questão.

R:

Inserir: 109 não houve desbalanceamento.


Inserir: 208 não houve desbalanceamento.
Inserir: 84 não houve desbalanceamento.
Inserir: 45 não houve desbalanceamento.
Inserir: 90 não houve desbalanceamento.

Inserir: 98 houve desbalanceamento na subarvore da esquerda, que é corrigida com uma rotação
LR

90
84 109
45 98 208

Inserir: 95 não houve desbalanceamento.

Inserir: 92 houve desbalanceamento na subarvore da direita, que é corrigida com uma rotação
RR.
90
84 109
45 95 208
92 98

Inserir: 122 não houve desbalanceamento na subarvore da direita.


Inserir: 122 não houve desbalanceamento na subarvore da direita.
Inserir: 266 não houve desbalanceamento na subarvore da direita.

Universidade Veiga de Almeida - UVA Página 7 de 13


Curso de Graduação em Engenharia da Computação

Inserir: 212 houve desbalanceamento na subarvore da direita de raiz 109, que é corrigida com
uma rotação LL.

109
90 208
84 95 122 266
45 92 98 212

b) Utilizando o mesmo princípio da questão A, remova o elemento 90. OBS: mostre


apenas a versão final da árvore, após a remoção do nó (1,0).
R: O nó a ser removido possui dois filhos, seu predecessor de valor 84 foi copiado ao
local do no removido e excluído o nó copiado de raiz 84.

109
84 208
45 95 122 266
92 98 212

c) Qual a importância da manutenção de uma árvore AVL balanceada (0,5)?


R: é necessário verificar sempre se a arvore está balanceada, com o objetivo sempre de
diminuir custos na busca, inserção e outras operações na arvore, proporcionando assim
uma estrutura bem planejada.
Algoritmos:
Rotação RR
Rotação LL
pB = pA  RightNode;
pB = pA LeftNode;
pA  RightNode = pB  LeftNode;
pA  LeftNode = pB  RightNode;
Rotação LR Rotação RL
pB  LeftNode = pA;
pB  RightNode = pA;
pB = pALeftNode; pB = pA  RightNode;
pC = pB  RightNode; pC = pB  LeftNode;
pB  RightNode = pC  LeftNode; pB  LeftNode = pC  RightNode;

QUESTÃO 7 – Uma
pC  LeftNode pC que
= pB; árvore B é um tipo de árvore RightNode = pB; balanceada com o
se mantém
decorrer do tempo, usando-se uma série de operações que garantem a manutenção de
pA  LeftNode = pC  RightNode; pA  RigthNode = pC  LeftNode;
uma série de propriedades importantes. Ela possui uma propriedade denominada ordem,
que consiste no número máximo de filhos que cada nó pode ter. Com base nesses
conceitos, considere as seguintes propriedades da árvore B [Cormen,T – Algoritmos –
Capítulo 10 – 2a edição] (0,7):

Universidade Veiga de Almeida - UVA Página 8 de 13


Curso de Graduação em Engenharia da Computação

I) em uma árvore B de ordem d, a raiz armazena um número de elementos n tal que d n


2d;

II) em um nó de uma árvore B que contenha n elementos, têm-se exatamente n+1


ponteiros que não apontam para vazio (nil ou null);

III) em uma árvore B de ordem maior do que 1, é possível que uma folha armazene
apenas um elemento.

Analisando as afirmativas acima, é correto afirmar que:

a) Todas as asserções são proposições verdadeiras.


b) A asserção II é uma proposição falsa e as demais são verdadeiras.
c) A asserção III é uma proposição verdadeira e as demais são falsas.
d) A asserção I é uma proposição verdadeira e as demais são falsas.
e) Todas as asserções são proposições falsas.

R:
I. A raiz pode armazenar somente 1 elemento
II. Nó folha sempre aponta para null
III. Sim , é possível em uma arvore de ordem 2 sendo a ordem o número máximo
de filhos. Entao a folha poderá ter 2 filhos (apontando para null) contendo
apenas 1 chave.

QUESTÃO 8 – <Aplicação> Considerando a ordem de inserções de chaves,


apresentadas a seguir, em uma árvore B com fator de ramificação T = 3, desenhe a
árvore final resultante (e as árvores intermediárias – geradas durante o processo de
inserção), descrevendo com detalhes as etapas do algoritmo de inserção (mostrado no
final desta questão), indicando qual o método foi acionado, e se houve a necessidade de
split, e indicando os casos da remoção (passo a passo) – OBS: Utilize o Algoritmo do
Cormen (visto em aula) (2,0).

INSERIR (201, 102, 304, 403, 508, 152, 602, 651, 273, 284, 701, 291, 805, 286, 276, 752,
641, 160).
REMOVER (602, 284, 701, 805, 201, 152, 508, 273 e 291)

Universidade Veiga de Almeida - UVA Página 9 de 13


Curso de Graduação em Engenharia da Computação

QUESTÃO 9 – Ao estudar escalonamento de processos em sistemas operacionais,


aprendemos um algoritmo que considera a prioridade de um processo para ingressa no
processador. Existem versões preemptivas e cooperativas para este algoritmo. As
cooperativas consideram que, uma vez que um processo ganha a vez de utilizar o
processador, o mesmo vai executar até o final. Já a preemptiva, considera que existe um
tempo de quantum tq que determina um período que o processo pode permanecer no
processador. Neste caso, o processo pode ir e voltar diversas vezes ao processador.

A implementação básica de um algoritmo de prioridade seja de forma cooperativa ou


preemptiva pode resultar em starvation, uma vez que processos de alta prioridade sempre
ganhariam de processos com baixa prioridade.

Uma forma de resolver isso é implementar o conceito de envelhecimento de tarefas,


utilizando a ideia de prioridade estática e dinâmica. Inicialmente, as prioridades estáticas
e dinâmicas dos processos são iguais. A partir daí, toda vez que um processo ganha o
processador sua prioridade dinâmica volta a ser a prioridade estática e os demais
processos são "bonificados" com um valor "alfa" sendo somado às suas prioridades
dinâmicas. Ou seja, a comparação para decidir que ganhará o processador se dará
sempre com base na prioridade dinâmica.

O gráfico a seguir mostra um exemplo deste tipo de escalonamento de processos, onde o


processo T1 tem maior prioridade que os demais:

Considerando as questões mencionadas e o algoritmo apresentado abaixo, desenvolva


um método em C que implementa a retirada de um processo de uma fila de prioridades, a
qual utiliza o conceito de envelhecimento de tarefas. Esta fila considera que os processos
mais prioritários possuem um valor de prioridade mais alto. Lembre-se que o algoritmo a
seguir é apenas uma explicação dos critérios de retirada da fila de prioridades, uma vez
que o analista de sistemas implementou a inserção na fila de prioridades utilizando o
conceito de heap-max [Cormen,T - Algoritmos – Capítulo 6 – 6a edição]. (1,5)

Universidade Veiga de Almeida - UVA Página 10 de 13


Curso de Graduação em Engenharia da Computação

R: Para deletar o Heap seria remover o elemento na raiz do nó. O processo deleta o
elemento máximo.

Se o elemento a ser removido não estiver nas pontas, isso é, for um elemento
intermediário, pode virar um problema. Então o elemento a ser deletado troca de lugares
com o último elemento e então deletamos o novo último elemento.

O passo a passo seria:

● Trocar a raíz ou elemento a ser deletado pelo último elemento do heap.


● Deletar o novo último elemento do heap.
● Como o último elemento agora ficou na posição de raiz, pode causar problemas.
Heapificamos o último nó na posição de raiz.

Por exemplo:
Se tratando de um Heap Max onde se quer deletar a raíz (7):

5 3

1 4

O último elemento é o 4. Trocamos a raíz pelo último elemento e então deletamos.

5 3

Universidade Veiga de Almeida - UVA Página 11 de 13


Curso de Graduação em Engenharia da Computação

Chamamos o método de heapificar a raiz. Heap final:

4 3

Código:

//Pra colocar como heap uma subárvore de raíz i


void heapificar(int []ele, int n, int i){
int maior = i;
int esq = 2 * i + 1; // esquerda = 2*i + 1
int dir = 2 * i + 2; // direita = 2*i + 2

if (esq < n && ele[esq] > ele[maior])


maior = esq;

if (dir < n && ele[dir] > ele[maior])


maior = dir;

if (maior != i) {
int temp = ele[i];
ele[i] = ele[maior];
ele[maior] = temp;

Universidade Veiga de Almeida - UVA Página 12 de 13


Curso de Graduação em Engenharia da Computação

heapificar(ele, n, maior);
}
}

int deletaRaiz(int []ele, int n) {


int ultimo = ele[n - 1];
ele[0] = ultimo;
n = n - 1;
heapify(ele, n, 0);
return n;
}

// Uso das funções em Max-Heap poderia ser algo parecido como:


// int []ele = { x, y, z (...) }; // Declarando a lista dos nós
// int n = ele.Length; // Pega o tamanho
// n = deletaRaiz(ele, n); // pede pra deletar a raiz

Universidade Veiga de Almeida - UVA Página 13 de 13

Você também pode gostar