Aula 02Fundamentos

Tipos Abstratos de Dados (TAD)

Antes de definir um TAD, precisamos acompanhar o caminho completo: valores primitivos viram campos, campos formam registros ou objetos, e estruturas organizam muitos objetos. O TAD aparece quando descrevemos essa organização pelas operações e regras, sem depender da representação interna.

Objetivo 01Distinguir dado primitivo e abstração
Objetivo 02Agrupar alunos em arrays e objetos
Objetivo 03Chegar de listas a grafos
01

Da linguagem para o modelo

O que é um dado primitivo?

Um tipo primitivo representa uma categoria básica de valor oferecida diretamente pela linguagem. Ele define quais valores cabem ali e quais operações básicas fazem sentido. Em C++, exemplos fundamentais são inteiros, números de ponto flutuante, caracteres e booleanos.

42
int

Inteiro

Contagem, idade, índice e quantidade.

8.7
double

Decimal

Média, distância, preço e medida.

'A'
char

Caractere

Uma unidade de texto codificada.

true
bool

Lógico

Uma condição verdadeira ou falsa.

Atenção em C++: std::string não é um tipo primitivo; é uma classe da biblioteca padrão que organiza uma sequência de caracteres. Isso já mostra como uma abstração pode parecer “básica” para quem a utiliza.

E o dado abstrato?Ele é observado pelo que representa e permite fazer.

Não é simplesmente “o contrário de primitivo”. É um valor visto por meio de um modelo que esconde detalhes de armazenamento.

02

Primeira organização

Variáveis numeradas não formam uma coleção

Criar uma variável nova para cada aluno funciona somente enquanto a quantidade é pequena e fixa. Os nomes das variáveis não permitem que um laço percorra automaticamente todos os alunos.

Dados espalhados

Uma variável por aluno

std::string nomeDoAluno1 = "Ana";
std::string nomeDoAluno2 = "Bia";
std::string nomeDoAluno3 = "Caio";

// E quando chegarem mais 100 alunos?
  • Não existe um tamanho da coleção.
  • Não podemos usar um índice variável.
  • Inserir mais alunos exige declarar mais nomes.
organizar
Uma coleção

Array de alunos

std::array<std::string, 3> nomes{
    "Ana", "Bia", "Caio"
};

for (const auto& nome : nomes) { ... }
  • Os valores possuem uma ordem.
  • Índices identificam as posições.
  • Um laço percorre toda a coleção.
O ganho não é apenas escrever menos.Agora “nomes” é uma unidade organizada sobre a qual podemos definir operações gerais.
03

Campos que pertencem juntos

Do aluno espalhado para struct e objeto

O array resolveu a repetição de nomes, mas um aluno não possui somente nome. Se criarmos uma variável separada para cada campo e para cada pessoa, voltamos ao mesmo problema.

Aluno 1 espalhado nomeDoAluno1 = "Ana"idadeDoAluno1 = 19mediaDoAluno1 = 8.7
Um registro coerente
Aluno ananome"Ana"idade19media8.7
Registro em C++struct
struct Aluno {
    std::string nome;
    int idade;
    double media;
};

A struct declara o formato de um registro. Cada instância reúne os campos de um aluno.

Orientação a objetosclass
class Aluno {
    std::string nome;
    int idade;

public:
    void apresentar() const;
    bool maiorDeIdade() const;
};

A classe pode esconder os campos e oferecer operações que mantêm o objeto em um estado válido.

Em termos de estruturas de dados: um objeto é uma unidade composta por estado — seus campos — e operações que atuam sobre esse estado. Orientação a objetos ajuda a modelar e proteger cada unidade; listas, árvores e grafos dizem como muitas unidades serão organizadas.

04

Organizando muitos objetos

Lista quando a ordem importa; grafo quando a relação importa

Depois de modelar um aluno, surge uma nova pergunta: como organizar muitos objetos Aluno? A resposta depende das operações e relações do problema.

Objetos
AnaBiaCaio
Organização linearLista de alunos
AnaBiaCaio

Cada elemento ocupa uma posição na sequência. Percorremos primeiro, segundo, terceiro...

std::vector<Aluno> turma;
Organização relacionalGrafo de alunos

Cada objeto é um nó. As ligações registram quem se relaciona com quem.

Grafo<Aluno, Amizade> rede;
Lista é um conceito abstrato.Ela especifica uma sequência e operações como inserir, remover e acessar. Um array, um vector ou uma lista encadeada podem fornecer implementações diferentes desse conceito.
05

Agora chegamos ao TAD

O TAD é o painel de controle, não o mecanismo interno

Ao dirigir, você usa volante, acelerador e freio sem precisar conhecer o motor. Carros diferentes preservam esse conjunto de operações, mesmo usando mecanismos internos diferentes. Um TAD aplica essa mesma separação ao software.

A ideia decisiva: o programa cliente depende das operações da pilha. Ele não deve depender do vetor ou da lista usados internamente.

06

Não confunda

TAD, estrutura de dados e classe não são sinônimos

Pergunta: o quê?

Tipo Abstrato de Dados

Especifica os valores possíveis, as operações disponíveis e o comportamento esperado.

ExemploPilha com regra LIFO e operações empilhar, desempilhar e topo.
Pergunta: como?

Estrutura de dados

Organiza fisicamente os dados e executa concretamente as operações definidas pelo TAD.

ExemploUm std::vector privado guarda os elementos da pilha.
Pergunta: onde está o código?

Classe em C++

É um recurso da linguagem que pode reunir a interface pública e uma implementação privada.

ExemploPilhaVetor<int> é uma classe que implementa o TAD Pilha.
TADestrutura concretaobjeto em memória
07

Especificação

As operações formam o contrato do TAD

Uma assinatura informa nome, entradas e saída. O contrato completa a informação dizendo o que precisa ser verdade antes da chamada e o que será garantido depois dela.

C

Criadora

Produz um novo valor do TAD.

criar()
O

Observadora

Consulta sem alterar o valor abstrato.

topo() · vazia()
M

Modificadora

Altera o estado do valor existente.

empilhar() · desempilhar()
OperaçãoPré-condiçãoPós-condição
empilhar(x)Nenhumax passa a ser o topo.
topo()A pilha não está vazia.Retorna o último valor empilhado sem removê-lo.
desempilhar()A pilha não está vazia.Remove e retorna o valor do topo.
vazia()NenhumaInforma se a pilha possui zero elementos.
Invariante da pilha

Todo elemento, exceto o topo, possui exatamente um elemento acima dele. Somente o topo pode ser removido. Cada operação pública deve preservar essa regra.

08

Experimente

Laboratório do contrato LIFO

LIFO significa last in, first out: o último valor que entra é o primeiro que sai. Use os controles e observe que a regra não depende de saber como a pilha foi armazenada.

Operação executadapilha criada

O topo atual é “codificar”.

base da pilha
tamanho: 3
O que observar
  1. empilhar altera somente o topo.
  2. topo consulta, mas não remove.
  3. desempilhar sempre remove o último valor inserido.
  4. Tentar remover uma pilha vazia viola a pré-condição.
09

Aplicação em C++

Uma interface, duas representações possíveis

A classe abstrata abaixo registra as operações públicas. Ela não decide onde os elementos serão guardados. Essa escolha pertence às classes concretas.

pilha.hpp
// Contrato do TAD Pilha
template <typename T>
class Pilha {
public:
    virtual ~Pilha() = default;

    virtual void empilhar(T valor) = 0;
    virtual T desempilhar() = 0;
    virtual const T& topo() const = 0;
    virtual bool vazia() const = 0;
};
Implementação ACom vetor
template <typename T>
class PilhaVetor : public Pilha<T> {
    std::vector<T> dados;

public:
    void empilhar(T valor) override {
        dados.push_back(valor);
    }

    T desempilhar() override {
        T valor = dados.back();
        dados.pop_back();
        return valor;
    }
    // topo() e vazia() seguem o contrato.
};
Implementação BCom nós encadeados
template <typename T>
class PilhaLista : public Pilha<T> {
    struct No {
        T valor;
        std::unique_ptr<No> proximo;
    };
    std::unique_ptr<No> topoDaPilha;

public:
    void empilhar(T valor) override {
        topoDaPilha = std::make_unique<No>(
            No{valor, std::move(topoDaPilha)}
        );
    }
    // As mesmas operações públicas.
};
O código cliente continua pensando em “pilha”:Pilha<std::string>& historico

Trocar a representação não exige reescrever quem usa o TAD, desde que o contrato seja preservado.

10

Método

Como projetar um TAD

1

Defina o valor abstrato

O que o tipo representa para quem vai usá-lo?

2

Escolha poucas operações

Elas devem ser simples, coerentes e suficientes para o propósito.

3

Escreva o contrato

Declare entradas, saídas, pré-condições e pós-condições.

4

Escolha a representação

Somente agora decida entre vetor, lista, tabela hash ou outra estrutura.

5

Declare os invariantes

Registre o que deve continuar verdadeiro após cada operação.

6

Teste pela interface

Os testes devem verificar o comportamento público, não detalhes internos.

11

Verifique se entendeu

Três perguntas rápidas

Se uma pilha troca vetor por lista, o código cliente deve mudar?

Não. Se o contrato foi preservado e a representação estava encapsulada, a troca é interna à implementação.

Uma pilha pode permitir remover o elemento da base?

Não dentro do contrato tradicional de pilha. Isso quebraria a regra LIFO e caracterizaria outro conjunto de operações.

Por que os atributos da implementação devem ser privados?

Para impedir que o cliente altere a representação diretamente, viole invariantes ou passe a depender de detalhes que deveriam poder mudar.

12

Conexões como dados

Grafos em redes sociais e bancos de dados

Uma lista responde bem “quais elementos estão na sequência?”. Um grafo foi feito para perguntas como “quem está conectado?”, “qual caminho liga duas pessoas?” e “quais relações existem entre estas entidades?”.

Exemplo 2Rede bancária
POSSUIPOSSUITRANSFERIUACESSOUACESSOU ClienteAna ClienteBia DispositivoX

Em um banco financeiro, clientes, contas e dispositivos podem ser nós. Relações como POSSUI, TRANSFERIU e ACESSOU tornam visíveis caminhos que ajudam a analisar transferências e conexões suspeitas.

Banco de dados em grafo

Nós + relacionamentos + propriedades

Em vez de guardar apenas linhas isoladas, o modelo registra as conexões como parte central dos dados.

:PessoaAnaidade: 19SEGUE:PessoaBiaidade: 21

Quando usar: grafos são especialmente úteis quando a pergunta principal exige percorrer relações — amigos de amigos, rotas, dependências, transferências ou entidades que compartilham um mesmo dispositivo.

13

Pesquisa utilizada

Fontes acadêmicas e técnicas

A aula foi construída a partir das definições e princípios apresentados nestas referências.