ix
Prefácio v
Ao Leitor v
Objetivos v
Público Alvo e Requisitos v
Organização do Livro v Partes v Capítulos v Apêndices vi Análise de Algoritmos vi Exemplos de Programação vi Exercícios vii
Material Complementar vii
Códigos-fonte vii
Site Dedicado ao Livro viii
Críticas, Sugestões e Comentários viii
Agradecimentos viii
Conteúdo ix
P
arteI: r
evIsãodaL
InguagemC
1 Elementos Básicos da Linguagem C 19
1.1 A Linguagem C Padrão 1.1 19
1.2 Identificadores, Tipos Primitivos e Constantes 1.2 19
1.3 Operadores Básicos 1.3 21 1.4 Definições de Variáveis 1.4 24 1.5 Operadores de Atribuição 1.5 24 1.6 Conversões de Tipos 1.6 25 1.7 Incremento e Decremento 1.7 26 1.8 Comentários 1.8 27 1.9 A Biblioteca Padrão de C 1.9 27
1.10 Escrita de Dados na Tela 1.10 29
1.11 Leitura de Dados via Teclado I: Frágil 1.11 29
1.12 Constantes Simbólicas 1.12 31 1.13 Enumerações 1.13 32 1.14 Instruções 1.14 32 1.15 Estruturas de Controle 1.15 33 1.15.1 Laços de Repetição 33 1.15.2 Desvios Condicionais 37 1.15.3 Desvios Incondicionais 40
C
onteúdo
1.16 Outros Operadores 1.16 42
1.16.1 Operador Condicional 42
1.16.2 Operador Vírgula 42
1.16.3 O Operador sizeof e o Tipo size_t 42
1.17 Programas Monoarquivo 1.17 43
1.18 Endereços e Ponteiros 1.18 44
1.19 Exercícios de Revisão 1.19 47
1.20 Exercícios de Programação 1.20 55
2 Funções e Programas Multiarquivo 57
2.1 Funções 2.1 57
2.2 Leitura de Dados via Teclado II: Robusta 2.2 63
2.3 Duração de Variáveis 2.3 66 2.4 Escopo 2.4 67 2.5 Diretivas de Preprocessamento 2.5 68 2.5.1 Macros 69 2.5.2 Compilação Condicional 71 2.5.3 Inclusão de Arquivos 72 2.6 Programas Multiarquivo 2.6 74 2.6.1 Variáveis Globais 74
2.6.2 Funções de Arquivo e Globais 75
2.6.3 Módulos 75
2.6.4 Como Construir Programas Multiarquivo 76
2.7 Exemplos de Programação 2.7 81
2.7.1 Um Módulo para Leitura de Dados Robusta 81 2.7.2 Comparando Números Reais 86 2.7.3 Série de Taylor para Cálculo de Seno 87 2.7.4 Raiz Quadrada Usando o Método de Newton e Raphson 89
2.8 Exercícios de Revisão 2.8 90
2.9 Exercícios de Programação 2.9 97
3 Tipos de Dados Estruturados 103
3.1 Arrays 3.1 103
3.2 Aritmética de Ponteiros 3.2 105
3.3 Relações entre Ponteiros e Arrays 3.3 106
3.4 Uso de const 3.4 107
3.5 Uso de Arrays com Funções 3.5 108
3.6 Arrays Multidimensionais 3.6 111
3.7 Strings e Caracteres 3.7 113
3.8 Função main() com Parâmetros 3.8 116
3.9 Tipos Definidos pelo Programador 3.9 117
3.10 Estruturas e Uniões 3.10 118
3.11 Operadores de Acesso e Definidores de Tipos 3.11 124
3.12 Exemplos de Programação 3.12 125
3.12.2 Ordenação de Arrays pelo Método da Bolha 128
3.12.3 Validando Datas 129
3.12.4 Operações com Vetores Reais 131 3.12.5 Coordenadas Retangulares e Polares 136
3.13 Exercícios de Revisão 3.13 140
3.14 Exercícios de Programação 3.14 148
4 Recursão e Retrocesso 153
4.1 Funções Recursivas 4.1 153
4.2 Cadeias Recursivas 4.2 155
4.3 Pilha de Execução e Registros de Ativação 4.3 156
4.4 Recursão de Cauda 4.4 161
4.5 Retrocesso (Backtracking) 4.5 164
4.5.1 O Problema das Oito Rainhas 164 4.5.2 Outros Problemas Propícios ao Uso de Retrocesso 182
4.6 Como Pensar Recursivamente 4.6 182
4.7 Quando Usar (e Não Usar) Recursão 4.7 185
4.8 Exemplos de Programação 4.8 188
4.8.1 O (Cansativo) Problema das Torres de Hanói 188 4.8.2 Fibonacci + Recursão = Ineficiência I 192 4.8.3 Calculando o Comprimento de um String Recursivamente 193 4.8.4 Removendo Vogais de um String Recursivamente 194 4.8.5 Exponenciação por Quadratura I 195 4.8.6 Invertendo Entradas I 196 4.8.7 Exibindo-se em Frente e Verso 197
4.8.8 Resolvendo Sudoku 199
4.9 Exercícios de Revisão 4.9 203
4.10 Exercícios de Programação 4.10 209
P
arteII: F
undamentos5 Conceitos Básicos de Estruturas de Dados 215
5.1 Definições Fundamentais 5.1 215
5.2 Tipos Abstratos e Estruturas de Dados 5.2 216
5.3 Algoritmos 5.3 217
5.3.1 Abordagem de Refinamentos Sucessivos 219 5.3.2 Linguagem Algorítmica (Pseudolinguagem) 219 5.3.3 Como Construir Algoritmos 219 5.3.4 Paradigmas Algorítmicos 220
5.4 Tipos de Dados Transparentes e TADs em C 5.4 221
5.5 Exemplos de Programação 5.5 223
5.5.1 Números Complexos como um Tipo de Dados Transparente 223 5.5.2 Números Complexos como um TAD 226
5.6 Exercícios de Revisão 5.6 228
6 Análise de Algoritmos 235
6.1 Complexidade de Algoritmos 6.1 235
6.2 Análise Assintótica 6.1 236
6.3 Notações Ó, Ômega e Teta (Grandes) 6.3 238
6.4 Casos Melhor, Pior e Mediano 6.4 245
6.5 Funções Comuns em Análise de Algoritmos 6.5 248
6.6 Resultados Teóricos Importantes 6.6 251
6.7 Regras Práticas para Análise Temporal de Algoritmos 6.7 253
6.7.1 Avaliação Temporal de Instruções Simples 253 6.7.2 Avaliação Temporal de Estruturas de Controle 253 6.7.3 Avaliação Temporal de Chamadas de Funções 255
6.8 Análise de Complexidade Espacial de Algoritmos 6.8 256
6.9 Algoritmos Recursivos e Relações de Recorrência 6.9 256
6.10 Problemas Intratáveis e Insolúveis 6.10 258
6.11 Exemplos de Programação 6.11 260
6.11.1 Um Algoritmo com Estimativa O(1) 260 6.11.2 Um Algoritmo com Estimativa O(n) 260 6.11.3 Um Algoritmo com Estimativa O(n2) 260 6.11.4 Um Algoritmo com Estimativa O(log n) 261 6.11.5 Um Algoritmo com Estimativa O(n log n) 262 6.11.6 Quando Será o Fim do Mundo? 263 6.11.7 Fibonacci + Recursão = Ineficiência II 266 6.11.8 Exponenciação por Quadratura II 268
6.12 Exercícios de Revisão 6.12 268
6.13 Exercícios de Programação 6.13 279
P
arteIII: e
struturasded
adosB
ásICas7 Listas Indexadas 283
7.1 Listas sem Ordenação 7.1 283
7.1.1 Abstração 283
7.1.2 Implementação de Listas sem Ordenação Usando Arrays Estáticos 285
7.1.3 Busca Sequencial 291
7.2 Listas Ordenadas 7.2 292
7.2.1 Abstração 292
7.2.2 Implementação de Listas Ordenadas Usando Arrays Estáticos 293
7.2.3 Busca Binária 294
7.3 Complexidade de Operações sobre Listas Indexadas 7.3 297
7.4 Tratamento de Exceções 7.4 298
7.5 Aplicações de Listas 7.5 302
7.5.1 Representação de Polinômios 302 7.5.2 Representação de Matrizes Esparsas 305
7.6 Exemplos de Programação 7.6 308
7.6.2 Uma Lista Ordenada de Alunos Armazenada em Arquivo 315 7.6.3 Removendo Duplicatas de uma Lista 324
7.7 Exercícios de Revisão 7.7 325 7.8 Exercícios de Programação 7.8 328 8 Pilhas e Filas 331 8.1 Pilhas 8.1 331 8.1.1 Conceito 331 8.1.2 Implementação 333 8.1.3 Complexidade 334 8.2 Filas Lineares 8.2 335 8.2.1 Conceito 335 8.2.2 Implementação 336 8.2.3 Complexidade 339 8.3 Filas Circulares 8.3 339
8.4 Transformando Recursão em Iteração Usando Pilha 8.4 343
8.5 Exemplos de Programação 8.5 349
8.5.1 Invertendo Entradas II 349 8.5.2 Casamento de Parênteses, Colchetes e Chaves 350 8.5.3 Testando Palíndromos 353 8.5.4 Fazendo, Desfazendo e Refazendo 354 8.5.5 Simulação de uma Fila de Banco 365
8.6 Exercícios de Revisão 8.6 369
8.7 Exercícios de Programação 8.7 373
9 Alocação Dinâmica de Memória 375
9.1 Justificativas para Alocação Dinâmica de Memória 9.1 375
9.2 Funções de Alocação Dinâmica de Memória 9.2 376
9.3 Ponteiros Genéricos e o Tipo void * 9.3 380
9.4 A Partição de Memória Heap 9.4 382
9.5 Testando Alocação Dinâmica de Memória 9.5 383
9.6 Listas Indexadas como TADs Dinâmicos 9.6 384
9.6.1 Listas sem Ordenação Implementadas Usando Arrays Dinâmicos 384 9.6.2 Listas Ordenadas Implementadas Usando Arrays Dinâmicos 389
9.7 Pilhas e Filas Implementadas Usando Arrays Dinâmicos 9.7 393
9.7.1 TAD Pilha I 393
9.7.2 TAD Fila I 395
9.8 Análise de Implementações com Arrays Dinâmicos 9.8 397
9.9 Exemplos de Programação 9.9 398
9.9.1 Lendo Linhas (Praticamente) Ilimitadas 398 9.9.2 A Urupema de Eratóstenes 405 9.9.3 Concatenação Múltipla de Strings 409 9.9.4 Conversão de Arquivo Binário em Lista e Vice-versa 411
9.10 Exercícios de Revisão 9.10 412
10 Listas Encadeadas 419
10.1 Deficiências de Arrays Dinâmicos 10.1 419
10.2 Listas Simplesmente Encadeadas sem Ordenação 10.2 420
10.2.1 Abstração 420
10.2.2 Implementação 421
10.3 Listas Simplesmente Encadeadas com Ordenação 10.3 433
10.3.1 Abstração 433
10.3.2 Implementação 434
10.4 Outros Tipos de Listas Encadeadas 10.4 438
10.4.1 Listas Duplamente Encadeadas Lineares 438 10.4.2 Listas Simplesmente Encadeadas Circulares 445 10.4.3 Listas Duplamente Encadeadas Circulares 452 10.4.4 Listas Encadeadas com Cabeça 460
10.5 Pilhas e Filas Encadeadas 10.5 466
10.5.1 TAD Pilha II 466
10.5.2 TAD Fila II 468
10.6 Complexidade de Operações sobre Listas Encadeadas 10.5 471
10.7 Exemplos de Programação 10.7 472
10.7.1 Invertendo uma Lista Simplesmente Encadeada 472
10.7.2 Números Felizes 473
10.7.3 Representação de Polinômios Usando Listas Encadeadas 476 10.7.4 A História de Josephus 483 10.7.5 Números Inteiros de Largura Ilimitada 486
10.8 Exercícios de Revisão 10.8 498
10.9 Exercícios de Programação 10.9 505
11 Estruturas de Dados e Algoritmos Genéricos 509
11.1 Ponteiros para Funções 11.1 509
11.1.1 Definições de Ponteiros para Funções 509 11.1.2 Atribuição de Valores a um Ponteiro para Função 510 11.1.3 Chamada de Função Mediante Ponteiro 511 11.1.4 Retornando Ponteiros para Funções 512 11.1.5 Ponteiros para Funções como Parâmetros de Funções 512
11.2 Listas Generalizadas 11.2 513
11.2.1 Conceitos 513
11.2.2 Implementação 514
11.2.3 Funções Recursivas para Listas Generalizadas 516
11.3 Estruturas de Dados Genéricas 11.3 518
11.4 Pilhas Genéricas 11.4 519
11.4.1 Implementação de Pilha Genérica 519 11.4.2 Criação de Pilha Genérica 519 11.4.3 Destruição de Pilha Genérica 520 11.4.4 Verificação de Pilha Genérica Vazia 520 11.4.5 Empilhamento em Pilha Genérica 520
11.4.6 Desempilhamento em Pilha Genérica 521 11.4.7 Elemento do Topo de Pilha Genérica 522
11.5 Usando bsearch() e qsort() 11.5 522
11.6 Avaliação de Expressões Aritméticas 11.6 525
11.6.1 Avaliação de Expressões Sufixas 527 11.6.2 Conversão de Forma Infixa para Forma Sufixa 528
11.7 Exemplos de Programação 11.7 531
11.7.1 Ordenação Generalizada de Listas 531 11.7.2 Conversão de Expressões Infixas em Sufixas 533 11.7.3 Avaliação de Expressões Sufixas 539
11.8 Exercícios de Revisão 11.8 542
11.9 Exercícios de Programação 11.9 546
12 Árvores 549
12.1 Conceitos Fundamentais de Árvores 12.1 549
12.2 Árvores Binárias 12.2 551
12.2.1 Árvores Binárias Degeneradas (ou Patológicas) 553 12.2.2 Árvores Estritamente Binárias 554 12.2.3 Árvores Binárias Perfeitas (ou Repletas) 554 12.2.4 Árvores Binárias Completas 555
12.3 Caminhamentos em Árvores Binárias 12.3 558
12.4 Implementação de Árvores Binárias 12.4 563
12.4.1 Definição de Tipo 563 12.4.2 Construção e Inserção de Nós 564 12.4.3 Caminhamentos 565 12.4.4 Profundidade 565 12.4.5 Semelhança 566 12.4.6 Clonagem 567 12.4.7 Número de Nós 568 12.4.8 Destruição 568
12.5 Árvores Binárias Baseadas em Caminhamentos 12.5 568
12.6 Árvores Binárias Costuradas 12.6 572
12.7 Complexidade de Operações sobre Árvores Binárias 12.7 577
12.8 Conversões de Árvores Ordinárias e Florestas em Árvores Binárias 12.7 577
12.9 Árvores de Jogos e Método Minimax 580
12.10 Exemplos de Programação 12.9 581
12.10.1 Problema das Oito Moedas 581
12.10.2 Jogo da Velha 583
12.10.3 A Codificação de Huffman 592
12.11 Exercícios de Revisão 12.11 607
12.12 Exercícios de Programação 12.12 622
A Precedência e Associatividade de Operadores da Linguagem C 631
B Elementos de Matemática 633
B.2 Polinômios B.2 633
B.3 Logaritmos B.3 634
B.4 Matrizes B.4 634
B.5 Funções Piso e Teto B.5 634
B.6 Análise Combinatória B.6 635
B.7 Indução Finita B.7 636
B.8 Relações de Recorrência B.8 637
B.8.1 Conjectura e Indução Matemática 637 B.8.2 Relações de Recorrência Homogêneas 637 B.8.3 Relações de Recorrência Não Homogêneas 637
B.9 Análise Assintótica B.9 637
C Respostas e Sugestões para os Exercícios de Revisão 639 Bibliografia 643
Conteúdo Resumido 649
Lista de Figuras 651