---
# System prepended metadata

title: BD

---

# Lista Etapa 2 - Parte 1 (AED)

**1) a)** - É uma estrutura que é sequencial, só pode ir para uma direção seguindo uma ordem linear.
**b)** 
- Pilha - A pilha é uma é uma estrutura de dados linear que funciona como uma pilha de pratos, onde você coloca um prato no topo e retira sempre o prato que está no topo.
- Fila - É uma estrutura que segue uma ordem em que o primeiro elemento inserido é o primeiro a ser removido.
- Lista -  A lista é uma estrutura de dados linear que armazena uma sequência de elementos de forma ordenada, permitindo inserções, remoções e acessos de elementos em qualquer posição.

**c)** 
- Pilha : 
  - Inserir - O(n) ou O(1)
  - Remover - O(1)
  - Pesquisar - O(1)
- Fila:
  - Inserir - O(1)
  - Remover - O(1)
  - Pesquisar - O(n)
- Lista:
  - Inserir - O(n)
  - Remover - O(n)
  - Pesquisar - O(n)

**d)** 
- Arrays:
  - Vantagens: acesso rápido, eficiência em espaço e desempenho.
  - Desvantagens: tamanho fixo, inserções/remoções caras.
- Collections:
  - Vantanges: tamanho dinâmico, facilidade de uso, menos erros de gerenciamento de memória.
  - Desvantagens: sobrecarga de memória/tempo, desempenho variável.

---
**2) a)** Fornece conhecimento sobre eficiência no processamento de dados, desempenho e complexidade, e uma base para entender algoritmos mais complexos.

**b)** Complexidade de tempo e espaço, estabilidade, facilidade de implementação e manutenção.

**c)** é um algoritmo de ordenação que não exige espaço adicional significativo além do que já é necessário para armazenar a entrada original.

**d)** Um algoritmo de ordenação estável é o que mantém a ordem relativa dos elementos que são iguais no conjunto de dados. Ou seja, quando dois elementos possuem o mesmo valor, a ordem de inserção desses elementos no conjunto original é preservada após a ordenação. Como exemplo podemos citar o MergeSort.

**e)** 
- Ordenação interna: Ocorre quando todos os dados a serem ordenados cabem na memória principal (RAM). O algoritmo pode operar diretamente sobre os dados, sem a necessidade de acessar dispositivos de armazenamento externo.
- Ordenação externa: É usada quando o volume de dados a ser ordenado é maior que a capacidade de memória RAM disponível. Nesse caso, o algoritmo precisa acessar dispositivos de armazenamento externo, como SSDs, para ordenar os dados.

**f)** C(n) representa o número de comparações realizadas pelo algoritmo de ordenação para ordenar um conjunto de n elementos, já o M(n) representa o número de movimentações ou trocas de elementos realizadas pelo algoritmo de ordenação.

**g)** Esses valores se referem ao nível de complexidade do algoritmo.

---

**3) a)** 
- No Bubblesort o algoritmo percorre repetidamente o vetor, comparando pares de elementos adjacentes.
- O Selection Sort é um algoritmo simples que seleciona o menor (ou maior) elemento da lista e o coloca na posição correta.
- O Insertion Sort é um algoritmo simples que constrói a lista ordenada um item de cada vez, inserindo o item correto na posição certa, em um vetor parcialmente ordenado.
- O QuickSort escolhe um "pivô" no vetor e divide o vetor em duas partes: uma contendo elementos menores que o pivô e outra com elementos maiores. Essas duas partes são então ordenadas recursivamente.
**b)** ![image](https://hackmd.io/_uploads/SJ7PPv0Zkg.png)

**c)** Estabilidade dos algoritmos:
- Estáveis: BubbleSort, InsertionSort e MergeSort.
- Não estáveis: SelectionSort e QuickSort.

---

**4) a)** A pesquisa simples (ou pesquisa linear) é o método mais básico de pesquisa em que o algoritmo percorre todos os elementos de uma lista ou vetor, um por um, até encontrar o item desejado ou até que todos os elementos tenham sido verificados. Pode ser usado em listas não ordenadas, em pequenos conjuntos de dados e quando a ordenação não é uma prioridade.
**b)** A pesquisa binária é um método eficiente para buscar um item em uma lista ordenada. Ela segue o princípio da divisão e conquista, reduzindo o espaço de busca pela metade a cada comparação. O algoritmo compara o item desejado com o elemento do meio da lista e decide se deve procurar na metade inferior ou superior da lista, repetindo esse processo recursivamente. Pode ser usado em listas ordenadas, grandes conjuntos de dados e quando a perfomance é crítica.

---

**5)**

```csharp
 static int pesquisaSimples(int[] v, int n, int chave) {
        for (int i = 0; i < n; i++)
            if (v[i] == chave) return i;
        return -1;
    }
```

---

**6)**

```csharp
public int pesquisaBinaria(int[] v, int n, int chave)
{
    int inicio = 0;
    int fim = n - 1;

    while (inicio <= fim)
    {
        int meio = inicio + (fim - inicio) / 2;
        if (v[meio] == chave)
            return meio;

        if (v[meio] < chave)
            inicio = meio + 1;
        else fim = meio - 1;
    }

    return -1;
}
```

---

**7)** A notação C(n) representa o custo de uma operação de pesquisa sequencial em uma lista de tamanho n, ou seja, quantas comparações o algoritmo realiza para encontrar o item procurado.
Melhor Caso (C(n) = 1) (1° posição)
Pior Caso (C(n) = n) (última posição ou não está na lista)
Caso Médio (C(n) = (n + 1) / 2) (está em uma posição aleatória)

---

**8)**

**A)** A função M realiza uma pesquisa binária em um vetor X ordenado. Ela procura um valor K no vetor X que possui N elementos.

**B)** 
1. pivo é calculado como o índice central do vetor, sendo i = 0 e j = 6
2. No primeiro cálculo, pivo = (0 + 6) / 2 = 3, e v[3] = 19. Como 80 > 19, i é atualizado para pivo + 1 = 4.
3. No segundo cálculo, pivo = (4 + 6) / 2 = 5, e v[5] = 80, que é o valor buscado (k=80).
4. A função retorna o índice 5, indicando que 80 foi encontrado na posição 5 do vetor.

**C)** 
1. A busca binária começa com i=0 e j=6.
2. pivo inicialmente é 3, e v[3] = 19. Como 12 < 19, j é atualizado para pivo - 1 = 2.
3. No próximo cálculo, pivo = (0 + 2) / 2 = 1, e v[1] = 8. Como 12 > 8, i é atualizado para pivo + 1 = 2.
4. pivo é recalculado como 2, e v[2] = 11. Como 12 > 11, i é atualizado para pivo + 1 = 3.
5. Agora, i=3 e j=2, o que termina o while. Como 12 não foi encontrado, a função retorna -1.

**D)** 

1. pivo começa como 3, e v[3] = 9. Como 32 > 9, i é atualizado para pivo + 1 = 4.
2. pivo é então calculado como 5, e v[5] = 23. Como 32 > 23, i é atualizado para pivo + 1 = 6.
3. pivo é agora 6, e v[6] = 77. Como 32 < 77, j é atualizado para pivo - 1 = 5.
4. O while termina sem encontrar 32, e a função retorna -1, mesmo que 32 esteja presente no vetor. Isso ocorre porque o vetor não está ordenado.

**E)**

```csharp
public int M<T>(T[] x, int n, T k) where T : IComparable<T>
{
    int i = 0, j = n - 1, pivo = 0;

    do
    {
        pivo = (i + j) / 2;
        if (k.CompareTo(x[pivo]) > 0)
            i = pivo + 1;
        else
            j = pivo - 1;
    }
    while (x[pivo].CompareTo(k) != 0 && i <= j);

    if (x[pivo].CompareTo(k) == 0)
        return pivo;

    return -1;
}
```

---

**9) a)** Falso. O algoritmo quickSort tem essa complexidade apenas no melhor e médio caso, no pior caso sua complexidade é O(n²).
**b)** Verdadeiro.
**c)** Falso. Um algoritmo com O(n²) não pode ser considerado melhor que um com O(n), pois o primeiro cresce muito mais rapidamente à medida que o tamanho de n aumenta.

---

**10)** 

Primeira Partição:

Pivô: A
Após reorganizar, resultado: A B U M C K R
Segunda Partição (B U M C K R):

Pivô: R
Resultado: A B M C K R U
Terceira Partição (B M C K):

Pivô: K
Resultado: A B C K M R U
Quarta Partição (B C):

Pivô: C
Resultado: A B C K M R U

A sequência ordenada é: A B C K M R U.

---

**11) a)** Top-Down (Quicksort): Começa com o problema inteiro e divide recursivamente até chegar a subproblemas triviais. A ordenação é feita enquanto o algoritmo recursivo vai "subindo" das divisões.
Bottom-Up (MergeSort): Começa com os subproblemas triviais e vai "construindo" a solução final de forma iterativa, fundindo sublistas até que se obtenha a lista ordenada.
**b)** A estratégia "dividir para conquistar" consiste em dividir o problema em subproblemas menores, resolvê-los e depois combinar as soluções, sendo uma técnica fundamental para melhorar a eficiência de algoritmos como MergeSort e QuickSort.

---

**12)** C.

---

**13)** B.

---

**14)** D.

---

**15)** A.

---

**16)** A escolha do pivô pode ser feita de diversas maneiras. A forma mais comum é o pivô na mediana, que ocorre somando o primeiro índice com o último e dividindo o resultado por 2. A eficiência do QuickSort depende fortemente de como o pivô divide a lista. O ideal é que o pivô divida a lista em duas sublistas aproximadamente iguais. Quando isso ocorre, o algoritmo tem uma complexidade O(n log n).

---

**17)** A.

---

**18)** A.

---

**19)** O HeapSort é um algoritmo de ordenação eficiente baseado em uma estrutura de dados chamada heap. O HeapSort é um algoritmo eficiente de ordenação, particularmente quando a memória é um recurso limitado, já que é um algoritmo in-place. Sua complexidade no pior caso é O(n log n), o que o torna robusto para arrays grandes. No entanto, ele não é estável e pode ser mais lento que outros algoritmos como o QuickSort em algumas situações práticas.