Você está na página 1de 49

CONTENTS

Contents

1 Introdução ao Python 5
1.1 O que é Python? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.1.1 Características: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.2 Vantagens do Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3 Instalação do Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.3.1 Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.3.2 Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.3.3 Mac . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

2 Configuração de Ambiente de Desenvolvimento 8


2.1 Escolhendo um Editor de Código . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.2 Gerenciamento de Pacotes com pip . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.3 Ambientes Virtuais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.3.1 O que é um Ambiente Virtual? . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.3.2 Vantagens dos Ambientes Virtuais . . . . . . . . . . . . . . . . . . . . . . . 9
2.3.3 Criando um Ambiente Virtual . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.3.4 Desativando e Removendo um Ambiente Virtual . . . . . . . . . . . . . . 10

3 Primeiros Passos com Python 11


3.1 Sintaxe Básica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.2 Entrada e Saída de Dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.3 Funções . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.4 Tratamento de Erros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.5 Exercícios Práticos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

4 Estruturas Condicionais 14
4.1 if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
4.2 if-else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
4.3 if-elif-else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
4.4 Exercícios Práticos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

5 Estruturas de Repetição 17
5.1 while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
5.2 for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
5.3 Instruções de Controle de Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
5.3.1 break . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
5.3.2 continue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

Guia do Ninja Jounin Python 2


CONTENTS

5.4 Exercícios práticos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

6 Orientação a Objetos 20
6.1 Introdução à Programação Orientada a Objetos . . . . . . . . . . . . . . . . . . . 20
6.1.1 Classes e Objetos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
6.1.2 Atributos e Métodos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
6.2 Herança, Polimorfismo e Encapsulamento . . . . . . . . . . . . . . . . . . . . . . . 21
6.2.1 Herança . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
6.3 Polimorfismo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
6.4 Encapsulamento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
6.5 Exemplo prático . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
6.6 Conclusão . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

7 Estruturas de Dados 25
7.1 Definição e Importância . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
7.2 Classificação de Estruturas de Dados . . . . . . . . . . . . . . . . . . . . . . . . . . 25
7.3 Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
7.3.1 Conceito e Utilização . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
7.3.2 Operações Básicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
7.3.3 Vantagens e Desvantagens . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
7.3.4 Atividade Prática . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
7.4 Listas encadeadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
7.4.1 Conceito e Implementação . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
7.4.2 Operações Básicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
7.4.3 Vantagens e Desvantagens . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
7.5 Lista Duplamente Encadeada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
7.5.1 Conceito e Implementação . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
7.5.2 Operações Básicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
7.5.3 Vantagens e Desvantagens . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
7.5.4 Exemplo de Uso em Python: . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
7.6 Lista Circular . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
7.6.1 Conceito e Implementação . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
7.6.2 Operações Básicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
7.6.3 Vantagens e Desvantagens . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
7.6.4 Exemplo de Uso em Python: . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
7.7 Pilhas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
7.7.1 Conceito e Implementação . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
7.7.2 Implementação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
7.7.3 Operações Básicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

Guia do Ninja Jounin Python 3


CONTENTS

7.7.4 Vantagens e Aplicações . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36


7.7.5 Exemplo de Uso em Python: . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
7.8 Filas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
7.8.1 Conceito . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
7.8.2 Implementação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
7.8.3 Operações Básicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
7.8.4 Vantagens e Aplicações . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
7.8.5 Exemplo de Uso em Python: . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
7.9 Árvore Binária . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
7.9.1 Conceito . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
7.9.2 Implementação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
7.9.3 Operações Básicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
7.9.4 Vantagens e Aplicações . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
7.9.5 Implementação Em Python . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
7.10 Árvore de Busca Binária . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
7.10.1 Conceito . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
7.10.2 Implementação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
7.10.3 Operações Básicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
7.10.4 Vantagens e Aplicações . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
7.10.5 Implementação em Python: . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
7.11 Árvore AVL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
7.11.1 Conceito . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
7.11.2 Implementação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
7.11.3 Operações Básicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
7.11.4 Vantagens e Aplicações . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
7.11.5 Implementação em Python: . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

Guia do Ninja Jounin Python 4


1 INTRODUÇÃO AO PYTHON

1 INTRODUÇÃO AO PYTHON
Neste capítulo, vamos explorar os conceitos fundamentais do Python, suas vantagens como
linguagem de programação e como instalar o Python em diferentes sistemas operacionais, in-
cluindo Windows, Linux e macOS.

1.1 O QUE É PYTHON?


Python é uma linguagem de programação de alto nível, interpretada e de propósito geral. Foi
criada por Guido van Rossum e lançada pela primeira vez em 1991. Python é conhecido por
sua sintaxe clara, legibilidade e facilidade de aprendizado.

1.1.1 CARACTERÍSTICAS:

• Sintaxe legível: A sintaxe do Python é projetada para ser clara e legível, enfatizando a
compreensão do código.

• Ampla biblioteca padrão: O Python possui uma biblioteca padrão abrangente, que fornece
uma ampla gama de módulos e funções prontos para uso.

• Facilidade de aprendizado: Python possui uma curva de aprendizado suave, o que o torna
uma ótima escolha para iniciantes em programação.

• Multiplataforma: Python é executado em vários sistemas operacionais, incluindo Win-


dows, Linux, macOS e outros.

• Grande comunidade e suporte: Python possui uma comunidade ativa de desenvolve-


dores e oferece suporte extensivo por meio de fóruns, documentação e bibliotecas de
terceiros.

• Flexibilidade: Python pode ser usado para uma ampla variedade de tarefas, desde script-
ing simples até desenvolvimento web e científico.

• Open-source: Python é uma linguagem de programação de código aberto, o que significa


que seu código-fonte está disponível para visualização e modificação.

1.2 VANTAGENS DO PYTHON


Python oferece várias vantagens como linguagem de programação:

• Simplicidade: A sintaxe do Python é concisa e fácil de entender, o que facilita a escrita e


a leitura do código.

Guia do Ninja Jounin Python 5


1 INTRODUÇÃO AO PYTHON

• Produtividade: Python permite que você desenvolva soluções rapidamente, graças à sua
sintaxe clara e à vasta biblioteca padrão.

• Portabilidade: O Python é executado em diferentes sistemas operacionais, permitindo


que você escreva código uma vez e o execute em várias plataformas.

• Ampla biblioteca padrão: A biblioteca padrão do Python é extensa e oferece uma ampla
gama de recursos para diferentes necessidades de desenvolvimento.

• Integração: Python pode ser facilmente integrado a outras linguagens como C, C++, Java
e .NET.

• Comunidade ativa: Python possui uma comunidade de desenvolvedores ativa e enga-


jada, que contribui com bibliotecas, frameworks e suporte.

• Aplicações diversificadas: Python é usado em várias áreas, desde desenvolvimento web


e científico até automação de tarefas e inteligência artificial.

1.3 INSTALAÇÃO DO PYTHON


Nesta seção, abordaremos o processo de instalação do Python nos sistemas operacionais Win-
dows, Linux e macOS.

1.3.1 WINDOWS

• Acesse o site oficial do Python (https://www.python.org) e vá para a seção de downloads.

• Baixe o instalador do Python para Windows, adequado à arquitetura do seu sistema (32
bits ou 64 bits).

• Execute o arquivo baixado e siga as instruções do instalador.

• Na tela de instalação, certifique-se de marcar a opção ”Adicionar Python ao PATH” para


facilitar o acesso ao Python a partir do prompt de comando.

• Conclua a instalação e verifique se o Python foi instalado corretamente abrindo o prompt


de comando e digitando ”python –version”.

1.3.2 LINUX

• A maioria das distribuições Linux já possui o Python pré-instalado. No entanto, você


pode verificar se o Python está instalado digitando ”python –version” no terminal.

Guia do Ninja Jounin Python 6


1 INTRODUÇÃO AO PYTHON

• Se o Python não estiver instalado, abra o terminal e execute o seguinte comando, depen-
dendo da distribuição:
Ubuntu e Debian: sudo apt-get install python3
Fedora: sudo dnf install python3
CentOS: sudo yum install python3
Certifique-se de usar o comando correto para sua distribuição específica.

1.3.3 MAC

• O macOS geralmente vem com uma versão pré-instalada do Python. No entanto, é re-
comendável instalar uma versão mais recente.

• Acesse o site oficial do Python (https://www.python.org) e vá para a seção de downloads.

• Baixe o instalador do Python para macOS e execute o arquivo baixado.

• Siga as instruções do instalador para concluir a instalação.

• Verifique se o Python foi instalado corretamente abrindo o terminal e digitando:

python3 --version

Neste capítulo, introduzimos o Python, suas vantagens como linguagem de programação e


explicamos o processo de instalação do Python nos sistemas Windows, Linux e macOS. Agora
você está pronto para começar a escrever seus primeiros programas em Python!

Guia do Ninja Jounin Python 7


2 CONFIGURAÇÃO DE AMBIENTE DE DESENVOLVIMENTO

2 CONFIGURAÇÃO DE AMBIENTE DE DESENVOLVIMENTO


Neste capítulo, exploraremos os elementos essenciais para configurar um ambiente de desen-
volvimento eficiente para Python. Discutiremos a escolha de um editor de código, o gerencia-
mento de pacotes com o pip e a configuração de ambientes virtuais.

2.1 ESCOLHENDO UM EDITOR DE CÓDIGO


Ao desenvolver em Python, é importante escolher uma ferramenta adequada para escrever e
gerenciar seu código. Existem várias opções disponíveis, e a escolha depende das preferências
pessoais e das necessidades do projeto. Alguns dos editores de código populares para Python
são:

• Visual Studio Code (VS Code): Um editor de código leve e altamente configurável, desen-
volvido pela Microsoft. Possui suporte a Python por meio de extensões e oferece recur-
sos poderosos para depuração e gerenciamento de projetos.

• PyCharm: Uma IDE (Integrated Development Environment) desenvolvida pela JetBrains,


projetada especificamente para desenvolvimento Python. Oferece recursos avançados,
como depuração, refatoração de código e suporte a testes automatizados.

• Sublime Text: Um editor de código leve e personalizável que suporta Python com plugins.
É conhecido por sua velocidade e interface intuitiva.

• Atom: Um editor de código de código aberto desenvolvido pelo GitHub. Possui um ecos-
sistema de pacotes e plugins extensível, permitindo personalização e suporte a Python.

• PyDev: Uma IDE que se integra ao Eclipse, fornecendo recursos avançados para desen-
volvimento Python, como depuração e autocompletar.

Esses são apenas alguns exemplos, e você pode experimentar diferentes editores para encon-
trar aquele que melhor se adapta às suas necessidades.

2.2 GERENCIAMENTO DE PACOTES COM PIP


O pip é um gerenciador de pacotes para Python, permitindo instalar, atualizar e remover pa-
cotes facilmente. Com o pip, você pode adicionar bibliotecas de terceiros aos seus projetos e
aproveitar o vasto ecossistema do Python.

pip --version

Guia do Ninja Jounin Python 8


2 CONFIGURAÇÃO DE AMBIENTE DE DESENVOLVIMENTO

2.3 AMBIENTES VIRTUAIS


Um ambiente virtual Python é uma ferramenta poderosa para isolar projetos e suas dependên-
cias. Ele permite que você crie um ambiente de desenvolvimento específico para cada pro-
jeto, evitando conflitos entre pacotes e facilitando a reprodução do ambiente em diferentes
máquinas.

2.3.1 O QUE É UM AMBIENTE VIRTUAL?

Um ambiente virtual é uma instância isolada do Python, onde você pode instalar pacotes e de-
pendências específicos para um projeto. Cada ambiente virtual possui seu próprio diretório de
instalação de pacotes, independente dos pacotes instalados no Python global do sistema.

2.3.2 VANTAGENS DOS AMBIENTES VIRTUAIS

• Isolamento de dependências: Com ambientes virtuais, você pode ter diferentes versões
de pacotes instalados para projetos diferentes, evitando conflitos de dependências.

• Reprodutibilidade do ambiente: Ao compartilhar um projeto com outras pessoas, é pos-


sível fornecer o ambiente virtual para garantir que todos tenham as mesmas dependên-
cias.

• Facilidade de limpeza: Se você não precisa mais de um ambiente virtual, basta excluí-lo,
e todos os pacotes e dependências associados serão removidos.

• Agilidade no desenvolvimento: Alternar entre diferentes ambientes virtuais é rápido e


fácil, permitindo que você trabalhe em projetos separadamente, sem interferências.

2.3.3 CRIANDO UM AMBIENTE VIRTUAL

Para criar um ambiente virtual Python, você pode usar a biblioteca venv, que está disponível
nas versões mais recentes do Python.
Criando um ambiente virtual no Windows:

• Abra o prompt de comando e navegue até o diretório onde deseja criar o ambiente virtual.

• Execute o seguinte comando para criar o ambiente virtual:

python -m venv nome_do_ambiente

• Ative o ambiente virtual executando o seguinte comando:

Guia do Ninja Jounin Python 9


2 CONFIGURAÇÃO DE AMBIENTE DE DESENVOLVIMENTO

nome_do_ambiente\Scripts\activate

Criando um ambiente virtual no Linux e macOS:

• Abra o terminal e navegue até o diretório onde deseja criar o ambiente virtual.

• Execute o seguinte comando para criar o ambiente virtual:

python3 -m venv nome_do_ambiente

• Ative o ambiente virtual executando o seguinte comando:

source nome_do_ambiente/bin/activate

2.3.4 DESATIVANDO E REMOVENDO UM AMBIENTE VIRTUAL

Para sair do ambiente virtual, basta digitar o seguinte comando no prompt de comando ou ter-
minal:

deactivate

Para remover completamente um ambiente virtual, basta excluir a pasta correspondente


ao ambiente virtual.
Neste capítulo, discutimos a importância de criar ambientes virtuais Python para isolar pro-
jetos e suas dependências. Exploramos os benefícios dos ambientes virtuais e como criá-los
usando a biblioteca venv. Com essa abordagem, você terá mais controle sobre as dependên-
cias

Guia do Ninja Jounin Python 10


3 PRIMEIROS PASSOS COM PYTHON

3 PRIMEIROS PASSOS COM PYTHON


Neste capítulo, vamos dar os primeiros passos com a linguagem de programação Python. Ex-
ploraremos a sintaxe básica da linguagem, entrada e saída de dados, o uso de funções e o trata-
mento de erros.

3.1 SINTAXE BÁSICA


Python possui uma sintaxe simples e legível, o que facilita a escrita e a compreensão do código.
Aqui estão alguns conceitos básicos da sintaxe do Python:

• Comentários: Os comentários são trechos de texto que não são executados pelo inter-
pretador Python. Eles são úteis para adicionar anotações ou explicar partes do código.
Em Python, os comentários são iniciados com o caractere ”” e vão até o final da linha.

# Isto é um comentário em Python

• Indentação: A indentação é fundamental em Python e define a estrutura do código. Em


vez de usar chaves ou palavras-chave para delimitar blocos de código, Python utiliza a
indentação. Recomenda-se usar quatro espaços para cada nível de indentação.

if x > 5:
print("x é maior que 5")
# Ocorre um espaçamento depois da definição da estrutura if

• Variáveis: Em Python, as variáveis são usadas para armazenar valores. Você pode atribuir
um valor a uma variável usando o sinal de igual ”=”.

x = 10
nome = "Maria"

• Tipos de Dados: Python suporta vários tipos de dados, como números, strings, listas, tu-
plas, dicionários, entre outros. Esses tipos de dados são fundamentais para realizar op-
erações e manipular informações.

numero = 10
texto = "Olá, mundo!"
lista = [1, 2, 3, 4, 5]
dicionario = {"chave": "valor"}

Guia do Ninja Jounin Python 11


3 PRIMEIROS PASSOS COM PYTHON

3.2 ENTRADA E SAÍDA DE DADOS


Python oferece mecanismos para interagir com o usuário por meio de entrada e saída de dados.
Você pode exibir informações para o usuário e receber dados de entrada.

• Exibindo Informações: Para exibir informações na tela, utilizamos a função print(). Ela
aceita um ou mais argumentos e os imprime na saída padrão.

print("Olá, mundo!")

• Recebendo Dados de Entrada: Para receber dados de entrada do usuário, utilizamos a


função input(). Ela exibe uma mensagem opcional e aguarda o usuário fornecer um valor,
que é retornado como uma string.

nome = input("Digite seu nome: ")

3.3 FUNÇÕES
Funções são blocos de código reutilizáveis que realizam uma tarefa específica. Elas permitem
que você estruture seu código de forma modular e organizada.

• Definindo uma Função: Em Python, definimos uma função usando a palavra-chave def,
seguida pelo nome da função, parênteses que podem conter parâmetros e dois pontos.
O corpo da função é indentado.

def saudacao():
print("Olá, seja bem-vindo!")
saudacao()

• Parâmetros e Argumentos: Uma função pode receber parâmetros, que são valores forneci-
dos quando a função é chamada. Esses valores são chamados de argumentos.

def saudacao(nome):
print("Olá,", nome)
saudacao("João")

3.4 TRATAMENTO DE ERROS


O tratamento de erros é importante para lidar com exceções e situações inesperadas durante
a execução do programa.
Guia do Ninja Jounin Python 12
3 PRIMEIROS PASSOS COM PYTHON

• Try-Except: Em Python, usamos blocos try e except para tratar exceções. O código den-
tro do bloco try é executado, e se ocorrer um erro, o código dentro do bloco except é
executado em vez de interromper o programa.

try:
resultado = 10 / 0
except ZeroDivisionError:
print("Erro: divisão por zero!")

• Finally: O bloco finally é opcional e é usado para executar código independentemente de


ocorrer ou não uma exceção.

try:
arquivo = open("dados.txt", "r")
# código para ler o arquivo
except FileNotFoundError:
print("Erro: arquivo não encontrado!")
finally:
arquivo.close()

Neste capítulo, exploramos os conceitos básicos da sintaxe Python, entrada e saída de da-
dos, o uso de funções e o tratamento de erros. Agora você está preparado para continuar sua
jornada no desenvolvimento Python e explorar recursos mais avançados da linguagem.

3.5 EXERCÍCIOS PRÁTICOS


• Escreva um programa que solicite o nome do usuário e exiba uma saudação personal-
izada.

• Crie uma função que receba dois números como argumentos e retorne a soma deles.

• Implemente um programa que leia a idade do usuário e exiba uma mensagem informando
se ele é menor ou maior de idade.

• Escreva um programa que solicite três números do usuário e exiba o maior valor entre
eles.

• Crie uma função que verifique se um número é par ou ímpar e retorne True ou False.

Guia do Ninja Jounin Python 13


4 ESTRUTURAS CONDICIONAIS

4 ESTRUTURAS CONDICIONAIS
Neste capítulo, vamos explorar as estruturas condicionais em Python. As estruturas condi-
cionais permitem que você execute diferentes blocos de código com base em uma condição
ou conjunto de condições. Veremos a estrutura básica do if, a estrutura if-else e a estrutura
if-elif-else. Além disso, forneceremos exercícios práticos para reforçar o aprendizado.

4.1 IF
A estrutura básica do if em Python permite executar um bloco de código se uma condição for
avaliada como verdadeira.

if condição:
# bloco de código a ser executado se a condição for verdadeira

Exemplo:

idade = 18
if idade >= 18:
print("Você é maior de idade!")

4.2 IF-ELSE
A estrutura if-else permite que você execute um bloco de código se a condição for verdadeira
e outro bloco de código se a condição for falsa.

if condição:
# bloco de código a ser executado se a condição for verdadeira
else:
# bloco de código a ser executado se a condição for falsa

Exemplo:

idade = 16

if idade >= 18:


print("Você é maior de idade!")
else:
print("Você é menor de idade.")

Guia do Ninja Jounin Python 14


4 ESTRUTURAS CONDICIONAIS

4.3 IF-ELIF-ELSE
A estrutura if-elif-else permite que você avalie várias condições sequencialmente e execute
blocos de código correspondentes à primeira condição verdadeira encontrada. O bloco elif
(abreviação de ”else if”) é opcional e pode aparecer várias vezes.

if condição1:
# bloco de código a ser executado se a condição1 for verdadeira
elif condição2:
# bloco de código a ser executado se a condição2 for verdadeira
else:
# bloco de código a ser executado se nenhuma das condições anteriores for verdadei

Exemplo:

idade = 25

if idade < 18:


print("Você é menor de idade.")
elif idade >= 18 and idade < 65:
print("Você é adulto.")
else:
print("Você é idoso.")

4.4 EXERCÍCIOS PRÁTICOS


• Escreva um programa que verifique se um número é positivo, negativo ou zero.

• Escreva um programa que determine se um ano é bissexto. Um ano é bissexto se for di-
visível por 4, mas não por 100, a menos que também seja divisível por 400.

• Escreva um programa que peça ao usuário que digite uma temperatura em Celsius e converta-
a para Fahrenheit. A fórmula para conversão é: fahrenheit = (celsius * 9/5) + 32.

• Escreva um programa que peça ao usuário que digite um número e verifique se o número
é par ou ímpar.

• Escreva um programa que peça ao usuário que digite um caractere e verifique se é uma
vogal ou consoante.

Guia do Ninja Jounin Python 15


4 ESTRUTURAS CONDICIONAIS

Neste capítulo, aprendemos sobre as estruturas condicionais em Python. Com o if, if-else
e if-elif-else, você pode controlar o fluxo do seu programa com base em condições específi-
cas. Pratique os exercícios para consolidar o seu entendimento dessas estruturas. No próximo
capítulo, abordaremos as estruturas de repetição em Python.

Guia do Ninja Jounin Python 16


5 ESTRUTURAS DE REPETIÇÃO

5 ESTRUTURAS DE REPETIÇÃO
Neste capítulo, exploraremos as estruturas de repetição em Python. Veremos como usar o loop
while e o loop for para executar blocos de código repetidamente. Também discutiremos as in-
struções de controle de loop para personalizar o comportamento de repetição. Além disso,
incluiremos exercícios práticos para aprimorar sua compreensão das estruturas de repetição.

5.1 WHILE
O loop while é usado quando você deseja repetir um bloco de código enquanto uma condição
for verdadeira. A estrutura básica do loop while é a seguinte:

while condição:
# Bloco de código a ser repetido

O bloco de código é repetido enquanto a condição for avaliada como verdadeira. Veja o
exemplo abaixo:

contador = 0
while contador < 5:
print(contador)
contador += 1

Neste exemplo, o bloco de código é repetido enquanto o valor da variável contador for
menor que 5. A cada iteração, o valor do contador é incrementado em 1.

5.2 FOR
O loop for é usado para iterar sobre uma sequência (como uma lista, uma string, um dicionário,
etc.) e executar um bloco de código para cada elemento da sequência. A estrutura básica do
loop for é a seguinte:

for elemento in sequência:


# Bloco de código a ser repetido

O bloco de código é repetido para cada elemento na sequência. Veja o exemplo abaixo:

frutas = ["maçã", "banana", "laranja"]


for fruta in frutas:
print(fruta)

Neste exemplo, o bloco de código é repetido para cada elemento da lista frutas, exibindo
cada fruta em uma linha separada.
Guia do Ninja Jounin Python 17
5 ESTRUTURAS DE REPETIÇÃO

5.3 INSTRUÇÕES DE CONTROLE DE LOOP


Existem algumas instruções especiais que podem ser usadas dentro das estruturas de repetição
para controlar o fluxo de execução do loop.

5.3.1 BREAK

A instrução break é usada para interromper a execução do loop prematuramente, mesmo se a


condição ainda for verdadeira. Veja o exemplo abaixo:

contador = 0
while True:
print(contador)
contador += 1
if contador == 5:
break

Neste exemplo, o loop while é interrompido quando o valor do contador atinge 5, mesmo
que a condição True ainda seja verdadeira.

5.3.2 CONTINUE

A instrução continue é usada para pular para a próxima iteração do loop, ignorando o restante
do bloco de código. Veja o exemplo abaixo:

for i in range(10):
if i % 2 == 0:
continue
print(i)

Neste exemplo, o bloco de código dentro do loop for é executado para todos os valores ím-
pares de i, enquanto os valores pares são ignorados usando a instrução continue.

5.4 EXERCÍCIOS PRÁTICOS


Agora é hora de praticar o uso das estruturas de repetição. Aqui estão alguns exercícios para
você:

• Escreva um programa que exiba os números de 1 a 10 usando um loop while.

• Crie um programa que solicite ao usuário que digite uma palavra e exiba cada caractere
em uma linha separada usando um loop for.

Guia do Ninja Jounin Python 18


5 ESTRUTURAS DE REPETIÇÃO

• Implemente um programa que calcule a soma de todos os números de 1 a 100 usando um


loop for.

• Escreva um programa que solicite ao usuário que adivinhe um número entre 1 e 10. O
programa deve continuar solicitando palpites até que o usuário acerte o número, exibindo
uma mensagem de sucesso.

• Crie uma função que receba uma lista de números como argumento e retorne a soma de
todos os números pares na lista.

Neste capítulo, exploramos as estruturas de repetição em Python. Aprendemos a usar o


loop while e o loop for para repetir blocos de código. Também discutimos as instruções de con-
trole de loop, como break e continue, para personalizar o comportamento da repetição. Com
os exercícios práticos, você pode aplicar o conhecimento adquirido e fortalecer sua compreen-
são das estruturas de repetição. Continue praticando e explorando os recursos da linguagem
para se tornar um programador Python mais habilidoso.

Guia do Ninja Jounin Python 19


6 ORIENTAÇÃO A OBJETOS

6 ORIENTAÇÃO A OBJETOS
Neste capítulo, vamos explorar o paradigma de programação orientada a objetos (POO) em
Python. Veremos os conceitos fundamentais da POO, como classes, objetos, atributos e méto-
dos. Além disso, abordaremos herança, polimorfismo e encapsulamento. A teoria será comple-
mentada com exemplos práticos em Python para ilustrar como aplicar esses conceitos.

6.1 INTRODUÇÃO À PROGRAMAÇÃO ORIENTADA A OBJETOS


A programação orientada a objetos é um paradigma de programação que organiza o código
em objetos, que são instâncias de classes. Essa abordagem permite a criação de estruturas
de software mais modular e reutilizável. Vamos explorar os principais conceitos da POO em
Python.

6.1.1 CLASSES E OBJETOS

Uma classe é uma estrutura que define o comportamento e os atributos de um objeto. Ela fun-
ciona como um molde para criar objetos específicos. Um objeto é uma instância de uma classe,
ou seja, uma representação concreta de um conceito abstrato. Veja o exemplo abaixo:

class Pessoa:
def __init__(self, nome, idade):
self.nome = nome
self.idade = idade

pessoa1 = Pessoa("João", 25)

Neste exemplo, definimos a classe Pessoa com os atributos nome e idade. Em seguida, cri-
amos um objeto pessoa1 a partir dessa classe, passando valores para os atributos.

6.1.2 ATRIBUTOS E MÉTODOS

Atributos são características de um objeto, como nome, idade, cor, etc. Métodos são funções
associadas a uma classe ou a um objeto e definem seu comportamento. Veja o exemplo abaixo:

class Retangulo:
def __init__(self, largura, altura):
self.largura = largura
self.altura = altura

def calcular_area(self):

Guia do Ninja Jounin Python 20


6 ORIENTAÇÃO A OBJETOS

return self.largura * self.altura

retangulo1 = Retangulo(10, 5)
area = retangulo1.calcular_area()

Neste exemplo, a classe Retângulo possui os atributos largura e altura. O método calcu-
lar_area() calcula a área do retângulo. Criamos um objeto retangulo1 e usamos o método cal-
cular_area() para obter a área do retângulo.

6.2 HERANÇA, POLIMORFISMO E ENCAPSULAMENTO


Além dos conceitos básicos, também veremos outros conceitos importantes da POO em Python:
herança, polimorfismo e encapsulamento.

6.2.1 HERANÇA

A herança permite que uma classe herde atributos e métodos de outra classe. A classe que
herda é chamada de classe filha ou subclasse, enquanto a classe da qual é herdado é chamada
de classe pai ou superclasse. Veja o exemplo abaixo:

class Animal:
def __init__(self, nome):
self.nome = nome

def fazer_som(self):
pass

class Cachorro(Animal):
def fazer_som(self):
return "Au Au!"

cachorro1 = Cachorro("Rex")
som = cachorro1.fazer_som()

Neste exemplo, a classe Animal é a superclasse e a classe Cachorro é a subclasse. A sub-


classe herda o atributo nome e o método fazer_som() da superclasse.

Guia do Ninja Jounin Python 21


6 ORIENTAÇÃO A OBJETOS

6.3 POLIMORFISMO
O polimorfismo permite que um objeto possa ser tratado como um objeto de qualquer uma de
suas classes ancestrais. Isso significa que diferentes classes podem ter métodos com o mesmo
nome, mas comportamentos diferentes. Veja o exemplo abaixo:

class Animal:
def fazer_som(self):
pass

class Cachorro(Animal):
def fazer_som(self):
return "Au Au!"

class Gato(Animal):
def fazer_som(self):
return "Miau!"

def fazer_barulho(animal):
return animal.fazer_som()

cachorro1 = Cachorro()
gato1 = Gato()

som_cachorro = fazer_barulho(cachorro1)
som_gato = fazer_barulho(gato1)

Neste exemplo, as classes Cachorro e Gato têm o método fazer_som(), mas cada um retorna
um som diferente. A função fazer_barulho() pode receber um objeto de qualquer uma das duas
classes e chamar o método fazer_som() apropriado.

6.4 ENCAPSULAMENTO
O encapsulamento é o princípio de ocultar os detalhes internos de um objeto e fornecer apenas
uma interface pública para interagir com ele. Em Python, usamos convenções de nomenclatura
para indicar a visibilidade dos atributos e métodos. Veja o exemplo abaixo:
Guia do Ninja Jounin Python 22
6 ORIENTAÇÃO A OBJETOS

class Carro:
def __init__(self, marca, modelo):
self.marca = marca
self.modelo = modelo
self.__velocidade = 0 # Atributo privado

def acelerar(self):
self.__velocidade += 10

def frear(self):
self.__velocidade -= 10

def obter_velocidade(self):
return self.__velocidade

carro1 = Carro("Toyota", "Corolla")


carro1.acelerar()
velocidade_atual = carro1.obter_velocidade()

Neste exemplo, o atributo __velocidade é definido como privado usando dois underscores
no início do nome. Isso indica que o atributo não deve ser acessado diretamente de fora da
classe. Em vez disso, usamos os métodos acelerar() e obter_velocidade() para interagir com o
atributo.

6.5 EXEMPLO PRÁTICO


Agora que exploramos os conceitos de orientação a objetos em Python, vamos criar um exem-
plo prático. Vamos criar uma classe ContaBancaria que simule uma conta bancária básica. Veja
o código abaixo:

class ContaBancaria:
def __init__(self, numero_conta, saldo_inicial):
self.numero_conta = numero_conta
self.saldo = saldo_inicial

def depositar(self, valor):


self.saldo += valor

def sacar(self, valor):


if self.saldo >= valor:
Guia do Ninja Jounin Python 23
6 ORIENTAÇÃO A OBJETOS

self.saldo -= valor
return valor
else:
print("Saldo insuficiente.")

def consultar_saldo(self):
return self.saldo

conta1 = ContaBancaria("12345", 1000)


conta1.depositar(500)
valor_sacado = conta1.sacar(300)
saldo_atual = conta1.consultar_saldo()

Neste exemplo, a classe ContaBancaria possui os atributos numero_conta e saldo. Os méto-


dos depositar(), sacar() e consultar_saldo() permitem interagir com a conta bancária.

6.6 CONCLUSÃO
Neste capítulo, exploramos os conceitos fundamentais da orientação a objetos em Python.
Aprendemos sobre classes, objetos, atributos e métodos. Além disso, discutimos herança, polimor-
fismo e encapsulamento. Com os exemplos práticos, você pôde ver como aplicar esses con-
ceitos na prática. A orientação a objetos é uma poderosa abordagem de programação que pro-
move a modularidade e a reutilização de código. Continue praticando e explorando os recursos
da POO em Python para se tornar um programador mais eficiente e eficaz.

Guia do Ninja Jounin Python 24


7 ESTRUTURAS DE DADOS

7 ESTRUTURAS DE DADOS

7.1 DEFINIÇÃO E IMPORTÂNCIA


A estrutura de dados é um conceito fundamental no campo da ciência da computação. Em ter-
mos simples, uma estrutura de dados é uma maneira de organizar e armazenar dados de forma
eficiente em um programa de computador. Ela define como os dados serão organizados, aces-
sados e manipulados.
A escolha adequada da estrutura de dados é crucial para o desempenho e eficiência de um
programa. Diferentes estruturas de dados têm características distintas e são projetadas para
atender a diferentes necessidades. Por exemplo, algumas estruturas de dados são eficientes
para inserção e remoção rápida de elementos, enquanto outras são otimizadas para busca ou
acesso aleatório. Compreender os fundamentos das estruturas de dados é essencial para de-
senvolver programas eficientes e escaláveis.

7.2 CLASSIFICAÇÃO DE ESTRUTURAS DE DADOS


As estruturas de dados podem ser classificadas em duas categorias principais: estruturas de
dados lineares e estruturas de dados não lineares.
As estruturas de dados lineares são aquelas em que os elementos de dados são organiza-
dos sequencialmente, um após o outro. Exemplos de estruturas de dados lineares incluem ar-
rays, listas ligadas, pilhas e filas. Essas estruturas são frequentemente usadas quando a ordem
dos elementos é importante ou quando operações como inserção e remoção precisam ser re-
alizadas de maneira específica.
Já as estruturas de dados não lineares não têm uma organização sequencial dos elementos.
Elas são utilizadas para representar relações complexas entre os dados. Exemplos de estru-
turas de dados não lineares incluem árvores, tabelas hash e grafos. Essas estruturas são par-
ticularmente úteis para representar hierarquias, relações de dependência e conexões entre os
dados.
Cada tipo de estrutura de dados possui vantagens e desvantagens, e a escolha da estrutura
correta depende das necessidades do programa e das operações que serão realizadas com os
dados. É essencial entender as características de cada estrutura de dados para selecionar a
mais adequada para cada situação.
Neste capítulo, exploraremos em detalhes diversas estruturas de dados lineares e não lin-
eares, fornecendo exemplos de implementação e discutindo as operações básicas, vantagens e
desvantagens de cada uma delas. Ao final desta jornada, você terá uma base sólida para utilizar
estruturas de dados de forma eficiente e eficaz em seus projetos de programação.
Continue lendo para descobrir mais sobre arrays, listas ligadas, pilhas, filas, árvores, tabelas
hash, grafos e algoritmos de ordenação e busca, e como eles podem ser aplicados para resolver

Guia do Ninja Jounin Python 25


7 ESTRUTURAS DE DADOS

problemas complexos e otimizar a manipulação de dados em seus programas.

7.3 ARRAYS

7.3.1 CONCEITO E UTILIZAÇÃO

Um array é uma estrutura de dados linear que armazena um conjunto de elementos do mesmo
tipo em uma ordem contígua na memória. Ele permite o acesso direto e eficiente aos elementos
através de um índice numérico. Os arrays são amplamente utilizados em programação para
armazenar e manipular coleções de dados de forma eficiente.
Em um array, cada elemento é identificado por um índice, que representa sua posição na
estrutura. O primeiro elemento geralmente tem o índice 0, o segundo tem o índice 1 e assim por
diante. Essa característica de acesso direto aos elementos através de índices torna os arrays
ideais para operações que exigem acesso aleatório aos dados.

7.3.2 OPERAÇÕES BÁSICAS

As operações básicas em arrays incluem:


Acesso: Permite acessar o valor de um elemento do array com base no seu índice. Inserção:
Permite adicionar um novo elemento ao array em uma posição específica. Remoção: Permite
remover um elemento do array a partir de um índice especificado. Atualização: Permite alterar
o valor de um elemento existente no array.

7.3.3 VANTAGENS E DESVANTAGENS

Vantagens:
Acesso direto e rápido aos elementos através de índices. Utilização eficiente de memória,
pois os elementos são armazenados de forma contígua. Operações de busca e acesso aleatório
têm tempo de execução constante (O(1)). Desvantagens:
O tamanho do array é fixo após a sua criação, o que significa que não é possível aumentar ou
reduzir o número de elementos facilmente. Inserção e remoção de elementos no meio do array
requerem deslocamento dos elementos subsequentes, o que pode ser uma operação custosa
em termos de tempo. Os arrays só podem armazenar elementos do mesmo tipo.

# Declaração e inicialização de um array em Python


numbers = [1, 2, 3, 4, 5]

# Acesso aos elementos do array


print(numbers[0]) # Saída: 1
print(numbers[2]) # Saída: 3

Guia do Ninja Jounin Python 26


7 ESTRUTURAS DE DADOS

# Atualização de um elemento do array


numbers[1] = 10
print(numbers) # Saída: [1, 10, 3, 4, 5]

# Inserção de um elemento no final do array


numbers.append(6)
print(numbers) # Saída: [1, 10, 3, 4, 5, 6]

# Remoção de um elemento do array


del numbers[2]
print(numbers) # Saída: [1, 10, 4, 5, 6]

7.3.4 ATIVIDADE PRÁTICA

• Escreva um programa em Python para calcular a soma dos elementos de um array.

• Implemente uma função que receba um array como parâmetro e retorne o valor máximo
presente no array.

• Crie uma função que receba um array como parâmetro e retorne uma nova lista contendo
apenas os números pares do array.

• Escreva um programa que verifique se um determinado elemento está presente em um


array.

• Implemente uma função que inverta a ordem dos elementos em um array.

• Crie um programa que encontre o segundo menor elemento em um array.

• Escreva uma função que receba dois arrays como parâmetros e retorne um novo array
que contenha os elementos comuns entre os dois arrays.

• Implemente um algoritmo de ordenação para ordenar os elementos de um array em or-


dem crescente.

• Crie uma função que receba um array e um número como parâmetros e retorne a quan-
tidade de vezes que esse número aparece no array.

• Escreva um programa que encontre o índice do primeiro elemento repetido em um array.

Guia do Ninja Jounin Python 27


7 ESTRUTURAS DE DADOS

7.4 LISTAS ENCADEADAS

7.4.1 CONCEITO E IMPLEMENTAÇÃO

As listas ligadas, também conhecidas como linked lists, são estruturas de dados lineares que
consistem em uma sequência de nós, onde cada nó contém um valor e uma referência para o
próximo nó da lista. Diferentemente dos arrays, as listas ligadas não exigem que os elementos
estejam armazenados em locais de memória contíguos.
Cada nó em uma lista ligada possui dois componentes principais: o valor, que é o dado ar-
mazenado, e o ponteiro para o próximo nó. O último nó da lista tem um ponteiro nulo, indicando
o fim da lista.

7.4.2 OPERAÇÕES BÁSICAS

As operações básicas em listas ligadas incluem:


Inserção: Permite adicionar um novo nó à lista ligada. Remoção: Permite remover um nó
existente da lista ligada. Busca: Permite procurar um valor específico na lista ligada. Acesso:
Permite acessar o valor de um nó em uma determinada posição na lista ligada. Atualização:
Permite alterar o valor de um nó existente na lista ligada.

7.4.3 VANTAGENS E DESVANTAGENS

Vantagens:
Tamanho flexível: As listas ligadas podem crescer e encolher conforme necessário, pois não
têm tamanho fixo como os arrays. Inserção e remoção eficientes: Adicionar ou remover ele-
mentos no início ou no final da lista ligada é uma operação eficiente, pois envolve apenas a atu-
alização dos ponteiros. Eficiência de memória: As listas ligadas são ideais quando não se sabe
o tamanho exato da coleção de dados antecipadamente, evitando desperdício de memória.
Desvantagens:
Acesso sequencial: A busca em uma lista ligada requer percorrer a lista do início até o el-
emento desejado, o que pode levar tempo linear, especialmente em listas grandes. Uso de
memória adicional: Cada nó em uma lista ligada requer um espaço adicional de memória para
armazenar o ponteiro para o próximo nó.

# Implementação de uma lista ligada em Python

# Definição da classe Node para representar um nó


class Node:
def __init__(self, value):
self.value = value
self.next = None
Guia do Ninja Jounin Python 28
7 ESTRUTURAS DE DADOS

# Definição da classe LinkedList para representar a lista ligada


class LinkedList:
def __init__(self):
self.head = None

def insert(self, value):


new_node = Node(value)
if self.head is None:
self.head = new_node
else:
current = self.head
while current.next is not None:
current = current.next
current.next = new_node

def remove(self, value):


if self.head is None:
return
if self.head.value == value:
self.head = self.head.next
return
current = self.head
while current.next is not None:
if current.next.value == value:
current.next = current.next.next
return
current = current.next

def search(self, value):


current = self.head
while current is not None:
if current.value == value:
return True
current = current.next
return False

# Exemplo de uso da lista ligada


linked_list = LinkedList()

Guia do Ninja Jounin Python 29


7 ESTRUTURAS DE DADOS

linked_list.insert(10)
linked_list.insert(20)
linked_list.insert(30)
linked_list.insert(40)

print(linked_list.search(20)) # Saída: True

linked_list.remove(30)
print(linked_list.search(30)) # Saída: False

Neste exemplo, uma lista ligada simples é criada e alguns nós são inseridos. Em seguida, é
feita uma busca pelo valor 20 e, posteriormente, um nó com valor 30 é removido. As operações
básicas de uma lista ligada são demonstradas.

7.5 LISTA DUPLAMENTE ENCADEADA

7.5.1 CONCEITO E IMPLEMENTAÇÃO

A lista duplamente encadeada, também conhecida como doubly linked list, é uma variação da
lista ligada em que cada nó possui uma referência tanto para o próximo nó quanto para o nó
anterior. Isso permite percorrer a lista em ambas as direções: da cabeça para a cauda e da
cauda para a cabeça.
Cada nó em uma lista duplamente encadeada contém três componentes principais: o valor
armazenado, um ponteiro para o nó anterior e um ponteiro para o próximo nó. O primeiro nó
da lista é chamado de cabeça, e o último nó é chamado de cauda. A cabeça tem seu ponteiro
anterior definido como nulo, e a cauda tem seu ponteiro próximo definido como nulo.

7.5.2 OPERAÇÕES BÁSICAS

As operações básicas em listas duplamente encadeadas são semelhantes às da lista ligada, mas
com a capacidade adicional de percorrer a lista em ambas as direções. As principais operações
incluem:
Inserção: Permite adicionar um novo nó à lista duplamente encadeada.
Remoção: Permite remover um nó existente da lista duplamente encadeada.
Busca: Permite procurar um valor específico na lista duplamente encadeada.
Acesso: Permite acessar o valor de um nó em uma determinada posição na lista duplamente
encadeada.
Atualização: Permite alterar o valor de um nó existente na lista duplamente encadeada.

Guia do Ninja Jounin Python 30


7 ESTRUTURAS DE DADOS

7.5.3 VANTAGENS E DESVANTAGENS

Vantagens:
Percorrendo em ambas as direções: A lista duplamente encadeada permite percorrer a lista
tanto da cabeça para a cauda quanto da cauda para a cabeça, o que pode ser útil em certos
cenários.
Remoção mais eficiente: A remoção de um nó em uma lista duplamente encadeada pode
ser mais eficiente em comparação com uma lista ligada, pois não é necessário percorrer a lista
a partir do início para encontrar o nó anterior ao nó a ser removido.
Flexibilidade de manipulação: Com os ponteiros para o próximo e o anterior, é possível re-
alizar operações complexas, como inserção ou remoção de nós em qualquer posição da lista.
Desvantagens:
Uso adicional de memória: Cada nó em uma lista duplamente encadeada requer espaço
adicional de memória para armazenar o ponteiro anterior, o que pode aumentar o consumo de
memória em comparação com uma lista ligada.
Complexidade de implementação: A manipulação dos ponteiros adicionais em uma lista du-
plamente encadeada pode tornar a implementação mais complexa em comparação com uma
lista ligada.

7.5.4 EXEMPLO DE USO EM PYTHON:

# Implementação de uma lista duplamente encadeada em Python

# Definição da classe Node para representar um nó


class Node:
def __init__(self, value):
self.value = value
self.next = None
self.prev = None

# Definição da classe DoublyLinkedList para representar a lista duplamente encadeada


class DoublyLinkedList:
def __init__(self):
self.head = None
self.tail = None

def insert(self, value):


new_node = Node(value)
if self.head is None:

Guia do Ninja Jounin Python 31


7 ESTRUTURAS DE DADOS

self.head = new_node
self.tail = new_node
else:
new_node.prev = self.tail
self.tail.next = new_node
self.tail = new_node

def remove(self, value):


if self.head is None:
return
current = self.head
while current is not None:
if current.value == value:
if current.prev is None:
self.head = current.next
if self.head is not None:
self.head.prev = None
else:
current.prev.next = current.next
if current.next is not None:
current.next.prev = current.prev
if current == self.tail:
self.tail = current.prev
return
current = current.next

def search(self, value):


current = self.head
while current is not None:
if current.value == value:
return True
current = current.next
return False

# Exemplo de uso da lista duplamente encadeada


doubly_linked_list = DoublyLinkedList()
doubly_linked_list.insert(10)
doubly_linked_list.insert(20)

Guia do Ninja Jounin Python 32


7 ESTRUTURAS DE DADOS

doubly_linked_list.insert(30)
doubly_linked_list.insert(40)

print(doubly_linked_list.search(20)) # Saída: True

doubly_linked_list.remove(30)
print(doubly_linked_list.search(30)) # Saída: False

7.6 LISTA CIRCULAR

7.6.1 CONCEITO E IMPLEMENTAÇÃO

A lista circular é uma variação da lista ligada em que o último nó da lista tem uma referência
que aponta para o primeiro nó, formando um ciclo contínuo. Dessa forma, a lista circular não
tem um início ou fim definidos, e é possível percorrer a lista repetidamente.
Cada nó em uma lista circular possui um valor e um ponteiro para o próximo nó na sequên-
cia. O último nó da lista possui um ponteiro que aponta para o primeiro nó, fechando o ciclo.

7.6.2 OPERAÇÕES BÁSICAS

As operações básicas em listas circulares são semelhantes às da lista ligada, mas com a capaci-
dade adicional de percorrer a lista repetidamente. As principais operações incluem:
Inserção: Permite adicionar um novo nó à lista circular.
Remoção: Permite remover um nó existente da lista circular.
Busca: Permite procurar um valor específico na lista circular.
Acesso: Permite acessar o valor de um nó em uma determinada posição na lista circular.
Atualização: Permite alterar o valor de um nó existente na lista circular.

7.6.3 VANTAGENS E DESVANTAGENS

Vantagens:
Complexidade de implementação: A manipulação dos ponteiros em uma lista circular pode
ser mais complexa do que em uma lista ligada simples.
Cuidado com ciclos infinitos: É importante garantir que exista uma condição de parada em
qualquer percurso ou iteração pela lista circular, para evitar loops infinitos.
Desvantagens:

Guia do Ninja Jounin Python 33


7 ESTRUTURAS DE DADOS

Complexidade de implementação: A manipulação dos ponteiros em uma lista circular pode


ser mais complexa do que em uma lista ligada simples.
Cuidado com ciclos infinitos: É importante garantir que exista uma condição de parada em
qualquer percurso ou iteração pela lista circular, para evitar loops infinitos.

7.6.4 EXEMPLO DE USO EM PYTHON:

# Implementação de uma lista circular em Python

# Definição da classe Node para representar um nó


class Node:
def __init__(self, value):
self.value = value
self.next = None

# Definição da classe CircularLinkedList para representar a lista circular


class CircularLinkedList:
def __init__(self):
self.head = None

def insert(self, value):


new_node = Node(value)
if self.head is None:
self.head = new_node
new_node.next = new_node
else:
current = self.head
while current.next != self.head:
current = current.next
current.next = new_node
new_node.next = self.head

def remove(self, value):


if self.head is None:
return
if self.head.value == value:
current = self.head
while current.next != self.head:
current = current.next
Guia do Ninja Jounin Python 34
7 ESTRUTURAS DE DADOS

if self.head == self.head.next:
self.head = None
else:
current.next = self.head.next
self.head = self.head.next
return
current = self.head
prev = None
while current.next != self.head:
prev = current
current = current.next
if current.value == value:
prev.next = current.next
return

def search(self, value):


if self.head is None:
return False
current = self.head
while True:
if current.value == value:
return True
current = current.next
if current == self.head:
break
return False

# Exemplo de uso da lista circular


circular_linked_list = CircularLinkedList()
circular_linked_list.insert(10)
circular_linked_list.insert(20)
circular_linked_list.insert(30)
circular_linked_list.insert(40)

print(circular_linked_list.search(20)) # Saída: True

circular_linked_list.remove(30)
print(circular_linked_list.search(30)) # Saída: False

Guia do Ninja Jounin Python 35


7 ESTRUTURAS DE DADOS

Neste exemplo, uma lista circular simples é criada e alguns nós são inseridos. Em seguida, é
feita uma busca pelo valor 20 e, posteriormente, um nó com valor 30 é removido. As operações
básicas de uma lista circular são demonstradas.

7.7 PILHAS

7.7.1 CONCEITO E IMPLEMENTAÇÃO

Uma pilha, também conhecida como stack, é uma estrutura de dados linear que segue o princí-
pio LIFO (Last In, First Out), ou seja, o último elemento adicionado à pilha é o primeiro a ser
removido. Pense em uma pilha de pratos: o último prato colocado é o primeiro a ser retirado.

7.7.2 IMPLEMENTAÇÃO

Uma pilha pode ser implementada utilizando uma lista encadeada ou um array. Neste capítulo,
iremos implementar uma pilha utilizando uma lista encadeada.

7.7.3 OPERAÇÕES BÁSICAS

Uma pilha oferece três operações básicas:


Push: adiciona um elemento no topo da pilha.
Pop: remove o elemento do topo da pilha e retorna o valor removido.
Top/Peek: retorna o valor do elemento no topo da pilha, sem removê-lo.

7.7.4 VANTAGENS E APLICAÇÕES

Vantagens:
As pilhas são amplamente utilizadas em diversas aplicações, como:
Gerenciamento de chamadas de função em tempo de execução (utilizado na pilha de chamadas
do sistema).
Inversão de sequências ou expressões.
Avaliação de expressões matemáticas.
Desfazer ações em editores de texto ou softwares de desenho.
Backtracking em algoritmos de busca.

7.7.5 EXEMPLO DE USO EM PYTHON:

Guia do Ninja Jounin Python 36


7 ESTRUTURAS DE DADOS

# Implementação de uma pilha utilizando uma lista encadeada

# Definição da classe Node para representar um nó da pilha


class Node:
def __init__(self, value):
self.value = value
self.next = None

# Definição da classe Stack para representar a pilha


class Stack:
def __init__(self):
self.top = None

def is_empty(self):
return self.top is None

def push(self, value):


new_node = Node(value)
if self.is_empty():
self.top = new_node
else:
new_node.next = self.top
self.top = new_node

def pop(self):
if self.is_empty():
return None
else:
popped_value = self.top.value
self.top = self.top.next
return popped_value

def peek(self):
if self.is_empty():
return None
else:
return self.top.value

Guia do Ninja Jounin Python 37


7 ESTRUTURAS DE DADOS

# Exemplo de uso da pilha


stack = Stack()
stack.push(10)
stack.push(20)
stack.push(30)

print(stack.peek()) # Saída: 30

stack.pop()
print(stack.peek()) # Saída: 20

Neste exemplo, uma pilha é criada utilizando uma lista encadeada. Alguns elementos são
inseridos utilizando a operação push(), e em seguida é feita uma verificação do elemento no
topo da pilha utilizando a operação peek(). Por fim, um elemento é removido utilizando a op-
eração pop() e novamente é feita uma verificação do elemento no topo da pilha. As operações
básicas de uma pilha são demonstradas.

7.8 FILAS

7.8.1 CONCEITO

Uma fila, também conhecida como queue, é uma estrutura de dados linear que segue o princípio
FIFO (First In, First Out), ou seja, o primeiro elemento adicionado à fila é o primeiro a ser re-
movido. Pense em uma fila de pessoas aguardando atendimento: a pessoa que chegou primeiro
é a primeira a ser atendida.

7.8.2 IMPLEMENTAÇÃO

Uma fila pode ser implementada utilizando uma lista encadeada ou um array. Neste capítulo,
iremos implementar uma fila utilizando uma lista encadeada.

7.8.3 OPERAÇÕES BÁSICAS

Uma fila oferece três operações básicas:


Enqueue: adiciona um elemento no final da fila.
Dequeue: remove o elemento do início da fila e retorna o valor removido.
Front: retorna o valor do elemento no início da fila, sem removê-lo.

Guia do Ninja Jounin Python 38


7 ESTRUTURAS DE DADOS

7.8.4 VANTAGENS E APLICAÇÕES

As filas são amplamente utilizadas em diversas aplicações, como:


Gerenciamento de tarefas em um sistema operacional (utilizado na fila de processos).
Agendamento de recursos compartilhados.
Sistemas de impressão.
Algoritmos de busca em largura (BFS - Breadth-First Search).
Simulação de eventos discretos.
A principal vantagem das filas é a sua simplicidade e eficiência para inserções no final e re-
moções no início da estrutura.

7.8.5 EXEMPLO DE USO EM PYTHON:

# Implementação de uma fila utilizando uma lista encadeada

# Definição da classe Node para representar um nó da fila


class Node:
def __init__(self, value):
self.value = value
self.next = None

# Definição da classe Queue para representar a fila


class Queue:
def __init__(self):
self.front = None
self.rear = None

def is_empty(self):
return self.front is None

def enqueue(self, value):


new_node = Node(value)
if self.is_empty():
self.front = new_node
self.rear = new_node
else:
self.rear.next = new_node
self.rear = new_node

Guia do Ninja Jounin Python 39


7 ESTRUTURAS DE DADOS

def dequeue(self):
if self.is_empty():
return None
else:
dequeued_value = self.front.value
self.front = self.front.next
if self.front is None:
self.rear = None
return dequeued_value

def get_front(self):
if self.is_empty():
return None
else:
return self.front.value

# Exemplo de uso da fila


queue = Queue()
queue.enqueue(10)
queue.enqueue(20)
queue.enqueue(30)

print(queue.get_front()) # Saída: 10

queue.dequeue()
print(queue.get_front()) # Saída: 20

Neste exemplo, uma fila é criada utilizando uma lista encadeada. Alguns elementos são adi-
cionados utilizando a operação enqueue(), e em seguida é obtido o elemento no início da fila
utilizando a operação get_front(). Após isso, um elemento é removido utilizando a operação
dequeue() e novamente é obtido o elemento no início da fila. As operações básicas de uma fila
são demonstradas.

7.9 ÁRVORE BINÁRIA

7.9.1 CONCEITO

Uma árvore binária é uma estrutura de dados hierárquica em que cada nó pode ter até dois
filhos: um filho à esquerda e um filho à direita. Cada nó em uma árvore binária é chamado de
Guia do Ninja Jounin Python 40
7 ESTRUTURAS DE DADOS

nó pai e pode ter no máximo dois filhos. Essa estrutura é amplamente utilizada em algoritmos
e estruturas de dados, pois permite representar relações hierárquicas e realizar operações de
busca, inserção e remoção de forma eficiente.

7.9.2 IMPLEMENTAÇÃO

Uma árvore binária pode ser implementada utilizando uma classe Node, em que cada objeto
Node representa um nó da árvore. Cada nó contém um valor e referências para o seu filho à
esquerda e para o seu filho à direita.

7.9.3 OPERAÇÕES BÁSICAS

As operações básicas em uma árvore binária incluem:


Inserção: Adiciona um novo nó à árvore binária.
Remoção: Remove um nó existente da árvore binária.
Busca: Procura por um valor específico na árvore binária.
Percursos: Existem diferentes formas de percorrer uma árvore binária, como pré-ordem,
em ordem e pós-ordem.

7.9.4 VANTAGENS E APLICAÇÕES

As árvores binárias são amplamente utilizadas em diversas aplicações, como:


Implementação de dicionários e tabelas de símbolos.
Implementação de algoritmos de pesquisa eficientes, como árvores de busca binária.
Organização de dados hierárquicos, como estruturas de diretórios em um sistema de ar-
quivos.
Implementação de expressões aritméticas e árvores de análise sintática.
A principal vantagem das árvores binárias é a sua capacidade de representar estruturas hi-
erárquicas de forma eficiente e permitir operações de busca e manipulação de dados de forma
otimizada.

7.9.5 IMPLEMENTAÇÃO EM PYTHON

# Implementação de uma árvore binária

# Definição da classe Node para representar um nó da árvore


class Node:
def __init__(self, value):
self.value = value
self.left = None

Guia do Ninja Jounin Python 41


7 ESTRUTURAS DE DADOS

self.right = None

# Definição da classe BinaryTree para representar a árvore binária


class BinaryTree:
def __init__(self):
self.root = None

def insert(self, value):


new_node = Node(value)
if self.root is None:
self.root = new_node
else:
queue = [self.root]
while queue:
current_node = queue.pop(0)
if current_node.left is None:
current_node.left = new_node
break
elif current_node.right is None:
current_node.right = new_node
break
else:
queue.append(current_node.left)
queue.append(current_node.right)

def search(self, value):


if self.root is None:
return False
else:
queue = [self.root]
while queue:
current_node = queue.pop(0)
if current_node.value == value:
return True
if current_node.left is not None:
queue.append(current_node.left)
if current_node.right is not None:
queue.append(current_node.right)

Guia do Ninja Jounin Python 42


7 ESTRUTURAS DE DADOS

return False

# Exemplo de uso da árvore binária


binary_tree = BinaryTree()
binary_tree.insert(10)
binary_tree.insert(20)
binary_tree.insert(30)

print(binary_tree.search(20)) # Saída: True


print(binary_tree.search(40)) # Saída: False

7.10 ÁRVORE DE BUSCA BINÁRIA

7.10.1 CONCEITO

Uma árvore de busca binária, também conhecida como BST (Binary Search Tree), é uma árvore
binária especial em que os nós são organizados de forma que a chave de cada nó seja maior que
todas as chaves em sua subárvore esquerda e menor que todas as chaves em sua subárvore
direita. Essa propriedade permite realizar operações de busca, inserção e remoção de forma
eficiente.

7.10.2 IMPLEMENTAÇÃO

Uma árvore de busca binária pode ser implementada utilizando uma classe Node, semelhante
à implementação de uma árvore binária convencional. Cada nó contém um valor e referências
para seu filho à esquerda e filho à direita.

7.10.3 OPERAÇÕES BÁSICAS

As operações básicas em uma árvore de busca binária incluem:


Inserção: Adiciona um novo nó à árvore de busca binária, mantendo a propriedade de orde-
nação. Remoção: Remove um nó existente da árvore de busca binária, mantendo a propriedade
de ordenação. Busca: Procura por um valor específico na árvore de busca binária. Percursos:
Existem diferentes formas de percorrer uma árvore de busca binária, como pré-ordem, em or-
dem e pós-ordem.

7.10.4 VANTAGENS E APLICAÇÕES

As árvores de busca binária são amplamente utilizadas em diversas aplicações, como:

Guia do Ninja Jounin Python 43


7 ESTRUTURAS DE DADOS

Dicionários e tabelas de símbolos com busca eficiente. Implementação de algoritmos de


pesquisa eficientes, como busca binária. Organização de dados ordenados, permitindo busca
e recuperação rápidas. Implementação de estruturas de dados balanceadas, como AVL e Red-
Black trees. A principal vantagem das árvores de busca binária é a capacidade de realizar op-
erações de busca, inserção e remoção de forma eficiente, com complexidade de tempo O(log
n) em média.

7.10.5 IMPLEMENTAÇÃO EM PYTHON:

# Implementação de uma árvore de busca binária

# Definição da classe Node para representar um nó da árvore


class Node:
def __init__(self, value):
self.value = value
self.left = None
self.right = None

# Definição da classe BinarySearchTree para representar a árvore de busca binária


class BinarySearchTree:
def __init__(self):
self.root = None

def insert(self, value):


new_node = Node(value)
if self.root is None:
self.root = new_node
else:
current_node = self.root
while True:
if value < current_node.value:
if current_node.left is None:
current_node.left = new_node
break
current_node = current_node.left
else:
if current_node.right is None:
current_node.right = new_node
break
Guia do Ninja Jounin Python 44
7 ESTRUTURAS DE DADOS

current_node = current_node.right

def search(self, value):


current_node = self.root
while current_node is not None:
if value == current_node.value:
return True
elif value < current_node.value:
current_node = current_node.left
else:
current_node = current_node.right
return False

# Exemplo de uso da árvore de busca binária


bst = BinarySearchTree()
bst.insert(50)
bst.insert(30)
bst.insert(70)

print(bst.search(30)) # Saída: True


print(bst.search(40)) # Saída: False

Neste exemplo, uma árvore de busca binária é criada e alguns nós são inseridos utilizando
a operação insert(). Em seguida, é realizada uma busca pelos valores 30 e 40 utilizando a oper-
ação search(). As operações básicas de uma árvore de busca binária são demonstradas.

7.11 ÁRVORE AVL

7.11.1 CONCEITO

Uma árvore AVL é uma árvore de busca binária balanceada em que a diferença de altura en-
tre as subárvores esquerda e direita de cada nó (chamada de fator de balanceamento) é no
máximo 1. Essa propriedade garante que a árvore esteja sempre balanceada e mantenha um
desempenho eficiente em operações de busca, inserção e remoção.

Guia do Ninja Jounin Python 45


7 ESTRUTURAS DE DADOS

7.11.2 IMPLEMENTAÇÃO

Uma árvore AVL é implementada utilizando uma classe Node, semelhante à implementação de
uma árvore de busca binária convencional. Cada nó contém um valor, referências para seu filho
à esquerda e filho à direita, além de um fator de balanceamento.

7.11.3 OPERAÇÕES BÁSICAS

As operações básicas em uma árvore AVL incluem:


Inserção: Adiciona um novo nó à árvore AVL, mantendo o fator de balanceamento e real-
izando rotações se necessário.
Remoção: Remove um nó existente da árvore AVL, mantendo o fator de balanceamento e
realizando rotações se necessário.
Busca: Procura por um valor específico na árvore AVL, seguindo a propriedade de orde-
nação.
Percursos: Existem diferentes formas de percorrer uma árvore AVL, como pré-ordem, em
ordem e pós-ordem.

7.11.4 VANTAGENS E APLICAÇÕES

As árvores AVL são amplamente utilizadas em diversas aplicações, como:


Dicionários e tabelas de símbolos com busca eficiente e balanceada.
Implementação de algoritmos de pesquisa eficientes, como a busca AVL.
Organização de dados ordenados com desempenho garantido em operações de busca, in-
serção e remoção.
Implementação de bancos de dados e sistemas de indexação.
A principal vantagem das árvores AVL é a capacidade de manter-se balanceada automatica-
mente, garantindo um desempenho eficiente em todas as operações, mesmo com um número
grande de elementos.

7.11.5 IMPLEMENTAÇÃO EM PYTHON:

# Implementação de uma árvore AVL

# Definição da classe Node para representar um nó da árvore


class Node:
def __init__(self, value):
self.value = value
self.left = None

Guia do Ninja Jounin Python 46


7 ESTRUTURAS DE DADOS

self.right = None
self.height = 1

# Definição da classe AVLTree para representar a árvore AVL


class AVLTree:
def __init__(self):
self.root = None

def insert(self, value):


self.root = self._insert_node(self.root, value)

def _insert_node(self, root, value):


if root is None:
return Node(value)
elif value < root.value:
root.left = self._insert_node(root.left, value)
else:
root.right = self._insert_node(root.right, value)

root.height = 1 + max(self._get_height(root.left), self._get_height(root.right)

balance_factor = self._get_balance_factor(root)

if balance_factor > 1 and value < root.left.value:


return self._rotate_right(root)

if balance_factor < -1 and value > root.right.value:


return self._rotate_left(root)

if balance_factor > 1 and value > root.left.value:


root.left = self._rotate_left(root.left)
return self._rotate_right(root)

if balance_factor < -1 and value < root.right.value:


root.right = self._rotate_right(root.right)
return self._rotate_left(root)

return root

Guia do Ninja Jounin Python 47


7 ESTRUTURAS DE DADOS

def _rotate_right(self, z):


y = z.left
T3 = y.right

y.right = z
z.left = T3

z.height = 1 + max(self._get_height(z.left), self._get_height(z.right))


y.height = 1 + max(self._get_height(y.left), self._get_height(y.right))

return y

def _rotate_left(self, z):


y = z.right
T2 = y.left

y.left = z
z.right = T2

z.height = 1 + max(self._get_height(z.left), self._get_height(z.right))


y.height = 1 + max(self._get_height(y.left), self._get_height(y.right))

return y

def _get_height(self, root):


if root is None:
return 0
return root.height

def _get_balance_factor(self, root):


if root is None:
return 0
return self._get_height(root.left) - self._get_height(root.right)

def search(self, value):


return self._search_node(self.root, value)

def _search_node(self, root, value):

Guia do Ninja Jounin Python 48


7 ESTRUTURAS DE DADOS

if root is None or root.value == value:


return root is not None
elif value < root.value:
return self._search_node(root.left, value)
else:
return self._search_node(root.right, value)

# Exemplo de uso da árvore AVL


avl_tree = AVLTree()
avl_tree.insert(50)
avl_tree.insert(30)
avl_tree.insert(70)

print(avl_tree.search(30)) # Saída: True


print(avl_tree.search(40)) # Saída: False

Neste exemplo, uma árvore AVL é criada e alguns nós são inseridos utilizando a operação
insert(). Em seguida, é realizada uma busca pelos valores 30 e 40 utilizando a operação search().
As operações básicas de uma árvore AVL são demonstradas.

Guia do Ninja Jounin Python 49

Você também pode gostar