# Prova – Estruturas de Dados e Paralelismo --- ## Parte A — Árvore Rubro-Negra ### 0 Usando o código: [https://github.com/leoinfnet/redblack-tp3] ### 1. Rotação e recoloração Considere a sequência de inserções `41, 38, 31, 12, 19, 8` em uma **Árvore Rubro-Negra** vazia. - Após inserir `31`, qual rotação ocorre (se ocorrer) e quem é o novo nó raiz? - Após inserir `19`, descreva **apenas** as operações de fix-up até o balanceamento final. Cite o caso Tio-Vermelho, as rotações e as recolorações envolvidas. --- ### 2. Verdadeiro ou Falso Justifique brevemente cada afirmação. - a) Todo caminho da raiz até uma folha externa (NIL) tem a mesma quantidade de nós pretos. - b) Em uma árvore Rubro-Negra, a raiz pode ser vermelha. - c) Após uma remoção, só há correção se o nó removido fosse vermelho. - d) A altura negra nunca diminui após uma inserção. --- ### 3. Complexidade e limites - a) Explique por que a altura `h` de uma árvore Rubro-Negra com `n` chaves é da ordem de `O(log n)`. - b) Qual é o número máximo de rotações necessárias em uma inserção? Quando isso ocorre? --- ### 4. Implementação: Usando o repositório informado: 1- Implemente a lógica de remoção de um nó na árvore. 2- Implemente o método inorder que deverá RECURSIVAMENTE percorrer a árvore e imprimir todos os elementos em ordem crescente. 3- Implemente o método: blackHeight que deverá calcular a quantidade de nós pretos de um determinado nó até um nó folha. ## Parte B — Árvore B Considere uma Árvore B de grau mínimo `t = 2`. ### 1. Inserções Insira, nessa ordem, as chaves `10, 20, 5, 6, 12, 30, 7, 17`. Desenhe a árvore **após cada split**. Ao final, mostre o conteúdo da **raiz** e de **cada filho direto da raiz**. --- ### 2. Busca e custo - a) Qual o número **mínimo** e **máximo** de chaves que podem estar na raiz (não-folha)? - b) Qual o número máximo de nós acessados em uma operação de busca (em termos de altura `h`)? --- ### 3. Remoção Comece com a árvore resultante da questão anterior. Remova, nessa ordem: `6`, depois `7`, depois `20`. Para cada remoção: - Indique se houve **empréstimo** ou **concatenação**. - Informe de qual lado ocorreu o empréstimo, se houver. - Mostre a chave promovida ou absorvida e o estado final dos nós alterados. --- ### 4. Implementação prática — Inserção na Árvore B Implemente em Java, Python ou C++ a função abaixo para dividir um nó cheio em uma Árvore B de grau `t = 2`. Não é necessário implementar a árvore completa — apenas o trecho responsável pelo **split** e a **promoção da chave mediana**. ```c // Estrutura básica (pode adaptar) struct No { int chaves[3]; int n; // número atual de chaves struct No* filhos[4]; bool folha; }; // Função esperada void divideNo(struct No* pai, int i, struct No* cheio); ``` Requisitos: - O nó `cheio` possui 3 chaves. - Promova a chave do meio para o pai. - Crie um novo nó com as chaves da direita. - Atualize os ponteiros de filho do pai. > **Itens para entregar:** código fonte do `divideNo` (arquivo separado ou colado no espaço de resposta), comentários curtos explicando as etapas do split e instruções mínimas de compilação (se aplicável). --- ## Parte C — OpenMP ### 1. Race condition e reduction Analise o código a seguir: ```c #include <omp.h> #include <stdio.h> int main() { long n = 1000000; long hits = 0; #pragma omp parallel for for (long i = 0; i < n; i++) { if ((i * 37) % 101 == 0) { hits++; } } printf("%ld\n", hits); } ``` - a) Explique por que há **data race**. - b) Reescreva apenas a diretiva para corrigir o problema usando `reduction`. - c) Qual a diferença prática entre `schedule(static)` e `schedule(dynamic)` nesse caso? --- ### 2. Implementação prática — Estimativa de π com Monte Carlo paralelo Implemente um programa em C usando OpenMP que estime o valor de π pelo método de Monte Carlo. ## Dica: Utilize docker para criar a estrutura para rodar OpenMP. Requisitos: 1. Gere `N` pontos aleatórios `(x, y)` no quadrado `[0, 1] × [0, 1]`. 2. Conte quantos pontos caem dentro do quarto de círculo `x² + y² ≤ 1`. 3. Paralelize o loop principal com OpenMP. 4. Use `reduction(+:contador)` para evitar race condition. 5. Calcule `π ≈ 4 × contador / N`. 6. Mostre o valor estimado e o tempo de execução com 1 thread e com todos os núcleos. > **Itens para entregar:** código fonte compilável, breve instrução de compilação (ex.: `gcc -fopenmp ...`), exemplo de execução com `N` indicado e saída exibida. ---