vii
Conteúdo Resumido
�����������������������������������������������������������������������������������������������������
v
Tabela de Conteúdo
���������������������������������������������������������������������������������������������������
vii
Lista de Figuras
����������������������������������������������������������������������������������������������������������
xvii
Lista de Tabelas
���������������������������������������������������������������������������������������������������������
xxiii
Lista de Algoritmos
��������������������������������������������������������������������������������������������������
xxv
Prefácio
�����������������������������������������������������������������������������������������������������������������������
xxvii
Objetivos e Público-alvo xxvii
Organização do Livro xxvii
Material Complementar xxxi
Recursos Utilizados xxxi
Agradecimentos xxxi
P
arte1: r
evisão daL
inguagemC
1
Elementos Básicos da Linguagem C
�������������������������������������������������������������
35
1�1 A Linguagem C Padrão 1.1 36
1�2 Identificadores, Tipos Primitivos e Constantes 1.2 36
1�3 Operadores Básicos 1.3 38
1�4 Definições de Variáveis 1.4 40
1�5 Operadores de Atribuição 1.5 40
1�6 Conversões de Tipos 1.6 41
1�8 Comentários 1.8 43
1�9 A Biblioteca Padrão de C 1.9 43
1�10 Escrita de Dados na Tela 1.10 44
1�11 Leitura de Dados via Teclado I: Frágil 1.11 45
1�12 Constantes Simbólicas 1.12 47 1�13 Enumerações 1.13 47 1�14 Instruções 1.14 48 1�15 Estruturas de Controle 1.15 49 1.15.1 Laços de Repetição 49 1.15.2 Desvios Condicionais 52 1.15.3 Desvios Incondicionais 54 1�16 Outros Operadores 1.16 56 1.16.1 Operador Condicional 56 1.16.2 Operador Vírgula 56
1.16.3 O Operador sizeof e o Tipo size_t 57
1�17 Programas Monoarquivo 1.17 57
1�18 Endereços e Ponteiros 1.18 58
1�19 Exercícios de Revisão 1.19 61
1�20 Exercícios de Programação 1.20 68
2
Funções e Programas Multiarquivo
��������������������������������������������������������������
71
2�1 Funções 2.1 72
2�2 Leitura de Dados via Teclado II: Robusta 2.2 77
2�3 Duração de Variáveis 2.3 80 2�4 Escopo 2.4 81 2�5 Diretivas de Pré-processamento 2.5 82 2.5.1 Macros 82 2.5.2 Compilação Condicional 84 2.5.3 Inclusão de Arquivos 85 2�6 Programas Multiarquivo 2.6 86 2.6.1 Variáveis Globais 87
2.6.2 Funções de Arquivo e Globais 87
2.6.3 Módulos 87
2.6.4 Como Construir Programas Multiarquivo 88
2�7 Exemplos de Programação 2.7 93
2.7.1 Um Módulo para Leitura de Dados Robusta 93
2.7.2 Comparando Números Reais 97
2.7.3 Série de Taylor para Cálculo de Seno 97
2.7.4 Raiz Quadrada Usando o Método de Newton e Raphson 99
2�8 Exercícios de Revisão 2.8 100
2�9 Exercícios de Programação 2.9 105
3
Tipos de Dados Estruturados
������������������������������������������������������������������������
111
Tabela de Conteúdo | ix
3�2 Aritmética de Ponteiros 3.2 114
3�3 Relações entre Ponteiros e Arrays 3.3 115
3�4 Uso de const 3.4 116
3�5 Uso de Arrays com Funções 3.5 117
3.5.1 Declarando Arrays como Parâmetros Formais 117
3.5.2 Arrays como Parâmetros Reais 118
3.5.3 Retorno de Arrays e Zumbis 118
3.5.4 Qualificação de Parâmetros com const 119
3�6 Arrays Multidimensionais 3.6 119
3�7 Strings e Caracteres 3.7 121
3�8 Função main() com Parâmetros 3.8 124
3�9 Tipos Definidos pelo Programador 3.9 125
3�10 Estruturas e Uniões 3.10 125
3�11 Operadores de Acesso e Definidores de Tipos 3.11 132
3�12 Exemplos de Programação 3.12 133
3.12.1 Módulo para Leitura Resiliente 133
3.12.2 Ordenação de Arrays pelo Método da Bolha 135
3.12.3 Validando Datas 136
3.12.4 Operações com Vetores Reais 138
3.12.5 Coordenadas Retangulares e Polares 140
3�13 Exercícios de Revisão 3.13 143
3�14 Exercícios de Programação 3.14 151
4
Recursão e Retrocesso
�������������������������������������������������������������������������������������
155
4�1 Funções Recursivas 4.1 156
4�2 Cadeias Recursivas 4.2 158
4�3 Pilha de Execução e Registros de Ativação 4.3 158
4�4 Recursão de Cauda 4.4 162
4�5 Retrocesso (Backtracking) 4.5 165
4.5.1 O Problema das N Rainhas 166
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 184
4�8 Exemplos de Programação 4.8 187
4.8.1 O (Cansativo) Problema das Torres de Hanói 187
4.8.2 Fibonacci + Recursão = Ineficiência I 190
4.8.3 Calculando o Comprimento de um String Recursivamente 192
4.8.4 Removendo Vogais de um String Recursivamente 192
4.8.5 Exponenciação por Quadratura I 193
4.8.6 Invertendo Entradas I 194
4.8.7 Exibindo-se em Frente e Verso 195
4.8.8 Resolvendo Sudoku 196
4�9 Exercícios de Revisão 4.9 199
P
arte2: F
undamentos5
Conceitos Básicos de Estruturas de Dados
�����������������������������������������������
211
5�1 Definições Fundamentais 5.1 212
5�2 Tipos Abstratos e Estruturas de Dados 5.2 213
5�3 Algoritmos 5.3 214
5.3.1 Abordagem de Refinamentos Sucessivos 215
5.3.2 Linguagem Algorítmica (Pseudolinguagem) 215
5.3.3 Como Construir Algoritmos 215
5.3.4 Paradigmas Algorítmicos 216
5�4 Tipos de Dados Transparentes e TADs em C 5.4 217
5�5 Exemplos de Programação 5.5 219
5.5.1 Números Complexos como um Tipo de Dados Transparente 219
5.5.2 Números Complexos como um TAD 221
5�6 Exercícios de Revisão 5.6 223
5�7 Exercícios de Programação 5.7 225
6
Análise de Algoritmos
�������������������������������������������������������������������������������������
229
6�1 Complexidade de Algoritmos 6.1 230
6�2 Análise Assintótica 6.2 231
6�3 Notações Ó, Ômega e Teta (Grandes) 6.3 232
6�4 Casos Melhor, Pior e Mediano 6.4 239
6�5 Funções Comuns em Análise de Algoritmos 6.5 241
6�6 Resultados Teóricos Importantes 6.6 244
6�7 Regras Práticas para Análise Temporal de Algoritmos 6.7 245
6.7.1 Análise Temporal de Instruções Simples 245
6.7.2 Análise Temporal de Sequências de Instruções 246
6.7.3 Análise Temporal de Estruturas de Controle 246
6.7.4 Análise Temporal de Chamadas de Funções 247
6�8 Análise de Custo Espacial de Algoritmos 6.8 248
6�9 Algoritmos Recursivos e Relações de Recorrência 6.9 249
6�10 Exemplos de Programação 6.10 250
6.10.1 Um Algoritmo com Custo Temporal θ(1) 250
6.10.2 Um Algoritmo com Custo Temporal θ(n) 250
6.10.3 Um Algoritmo com Custo Temporal θ(n2) 251
6.10.4 Um Algoritmo com Custo Temporal θ(log n) 252
6.10.5 Um Algoritmo com Custo Temporal θ(n log n) 253
6.10.6 Quando Será o Fim do Mundo? 254
6.10.7 Fibonacci + Recursão = Ineficiência II 256
6.10.8 Exponenciação por Quadratura II 258
6�11 Exercícios de Revisão 6.11 258
Tabela de Conteúdo | xi
P
arte3: e
struturasded
adosB
ásiCas7
Listas Indexadas
������������������������������������������������������������������������������������������������
269
7�1 Listas sem Ordenação 7.1 270
7.1.1 Abstração 270
7.1.2 Implementação de Listas sem Ordenação Usando Arrays Estáticos 271
7.1.3 Busca Sequencial 277
7�2 Listas Ordenadas 7.2 278
7.2.1 Abstração 278
7.2.2 Implementação de Listas Ordenadas Usando Arrays Estáticos 279
7.2.3 Busca Binária 280
7�3 Custos de Operações sobre Listas Indexadas 7.3 282
7�4 Tratamento de Exceções 7.4 283
7�5 Aplicações de Listas 7.5 286
7.5.1 Representação de Polinômios 286
7.5.2 Representação de Matrizes Esparsas 289
7�6 Exemplos de Programação 7.6 292
7.6.1 Gerenciando uma Lista de Compras com Sensibilidade 292
7.6.2 Uma Lista Ordenada de Alunos Armazenada em Arquivo 298
7.6.3 Removendo Duplicatas de uma Lista 306
7�7 Exercícios de Revisão 7.7 307 7�8 Exercícios de Programação 7.8 309
8
Pilhas e Filas
��������������������������������������������������������������������������������������������������������
311
8�1 Pilhas 8.1 312 8.1.1 Conceito 312 8.1.2 Implementação 314 8.1.3 Custos 315 8�2 Filas Lineares 8.2 315 8.2.1 Conceito 315 8.2.2 Implementação 316 8.2.3 Custos 319 8�3 Filas Circulares 8.3 3198�4 Transformando Recursão em Iteração Usando Pilha 8.4 323
8�5 Exemplos de Programação 8.5 328
8.5.1 Invertendo Entradas II 328
8.5.2 Casamento de Parênteses, Colchetes e Chaves 329
8.5.3 Testando Palíndromos 332
8.5.4 Fazendo, Desfazendo e Refazendo 333
8.5.5 Simulação de uma Fila de Banco 342
8�6 Exercícios de Revisão 8.6 346
9
Alocação Dinâmica de Memória
������������������������������������������������������������������
351
9�1 Justificativas para Alocação Dinâmica de Memória 9.1 352
9�2 Funções de Alocação Dinâmica de Memória 9.2 353
9�3 Ponteiros Genéricos e o Tipo void * 9.3 356
9�4 A Partição de Memória Heap 9.4 358
9�5 Testando Alocação Dinâmica de Memória 9.5 359
9�6 Listas Indexadas como TADs Dinâmicos 9.6 360
9.6.1 Listas sem Ordenação Implementadas Usando Arrays Dinâmicos 360
9.6.2 Listas Ordenadas Implementadas Usando Arrays Dinâmicos 365
9�7 Pilhas e Filas Implementadas com Arrays Dinâmicos 9.7 369
9.7.1 TAD Pilha I 369
9.7.2 TAD Fila I 371
9�8 Análise de Implementações com Arrays Dinâmicos 9.8 373
9�9 Exemplos de Programação 9.9 373
9.9.1 Lendo Linhas (Praticamente) Ilimitadas 373
9.9.2 A Urupema de Eratóstenes 379
9.9.3 Concatenação Múltipla de Strings 383
9.9.4 Conversão de Arquivo Binário em Lista e Vice-versa 384
9�10 Exercícios de Revisão 9.10 386
9�11 Exercícios de Programação 9.11 389
10
Listas Encadeadas
����������������������������������������������������������������������������������������
393
10�1 Deficiências de Arrays Dinâmicos 10.1 39410�2 Listas Simplesmente Encadeadas sem Ordenação 10.2 395
10.2.1 Abstração 395
10.2.2 Implementação 395
10�3 Listas Simplesmente Encadeadas com Ordenação 10.3 406
10.3.1 Abstração 406
10.3.2 Implementação 406
10�4 Outros Tipos de Listas Encadeadas 10.4 410
10.4.1 Listas Duplamente Encadeadas Lineares 411
10.4.2 Listas Simplesmente Encadeadas Circulares 415
10.4.3 Listas Duplamente Encadeadas Circulares 418
10.4.4 Listas Encadeadas com Cabeça 421
10�5 Pilhas e Filas Encadeadas 10.5 424
10.5.1 TAD Pilha II 424
10.5.2 TAD Fila II 426
10�6 Custos de Operações sobre Listas Encadeadas 10.5 428
10�7 Exemplos de Programação 10.7 429
10.7.1 Invertendo uma Lista Simplesmente Encadeada 429
10.7.2 Números Felizes 430
10.7.3 Representação de Polinômios Usando Listas Encadeadas 433
Tabela de Conteúdo | xiii
10.7.5 Números Inteiros de Largura Ilimitada 442
10�8 Exercícios de Revisão 10.8 453
10�9 Exercícios de Programação 10.9 458
11
Estruturas de Dados e Algoritmos Genéricos
�������������������������������������
463
11�1 Ponteiros para Funções 11.1 464
11.1.1 Definições de Ponteiros para Funções 464
11.1.2 Atribuição de Valores a um Ponteiro para Função 465
11.1.3 Chamada de Função Mediante Ponteiro 466
11.1.4 Retornando Ponteiros para Funções 466
11.1.5 Ponteiros para Funções como Parâmetros de Funções 467
11�2 Listas Generalizadas 11.2 468
11.2.1 Conceitos 468
11.2.2 Implementação 469
11.2.3 Funções Recursivas para Listas Generalizadas 470 11�3 Estruturas de Dados Genéricas 11.3 472
11�4 Pilhas Genéricas 11.4 473
11.4.1 Implementação de Pilha Genérica 473
11.4.2 Criação de Pilha Genérica 474
11.4.3 Destruição de Pilha Genérica 474
11.4.4 Verificação de Pilha Genérica Vazia 474
11.4.5 Empilhamento em Pilha Genérica 474
11.4.6 Desempilhamento em Pilha Genérica 475
11.4.7 Elemento do Topo de Pilha Genérica 476
11�5 Usando bsearch() e qsort() 11.5 476
11�6 Avaliação de Expressões Aritméticas 11.6 479
11.6.1 Avaliação de Expressões Sufixas 480
11.6.2 Conversão de Forma Infixa para Forma Sufixa 481
11�7 Exemplos de Programação 11.7 484
11.7.1 Ordenação Generalizada de Listas Indexadas 484
11.7.2 Conversão de Expressões Infixas em Sufixas 486
11.7.3 Avaliação de Expressões Sufixas 491
11�8 Exercícios de Revisão 11.8 493
11�9 Exercícios de Programação 11.9 497
12
Árvores
�������������������������������������������������������������������������������������������������������������
499
12�1 Conceitos Fundamentais de Árvores 12.1 50012�2 Árvores Binárias 12.2 502
12.2.1 Árvores Binárias Degeneradas (ou Patológicas) 503
12.2.2 Árvores Estritamente Binárias 503
12.2.3 Árvores Binárias Perfeitas (ou Repletas) 503
12.2.4 Árvores Binárias Completas 504
12�3 Caminhamentos em Árvores Binárias 12.3 506
12.4.1 Definição de Tipo 511 12.4.2 Construção e Inserção de Nós 511 12.4.3 Caminhamentos 512 12.4.4 Profundidade 513 12.4.5 Semelhança 513 12.4.6 Clonagem 514 12.4.7 Número de Nós 514 12.4.8 Destruição 515
12�5 Árvores Binárias Baseadas em Caminhamentos 12.5 515
12�6 Árvores Binárias Costuradas 12.6 518
12�7 Conversões de Árvores e Florestas em Árvores Binárias 12.7 522
12�8 Exemplos de Programação 12.8 525
12.8.1 Problema das Oito Moedas 525
12.8.2 A Codificação de Huffman 527
12�9 Exercícios de Revisão 12.9 540
12�10 Exercícios de Programação 12.10 549
a
PêndiCesA
Precedência e Associatividade de Operadores da Linguagem C
������
555
B
Elementos de Matemática
������������������������������������������������������������������������������
557
B�1 Somatórios B.1 557 B�2 Polinômios B.2 558 B�3 O Método de Horner B.3 559 B�4 Logaritmos B.4 561 B�5 Matrizes B.5 561B�6 Funções Piso e Teto B.6 563
B�7 Análise Combinatória B.7 564
B�8 Indução Matemática Finita B.8 564
B.8.1 Indução Fraca 564
B.8.2 Indução Forte 566
B�9 Relações de Recorrência B.9 566
B.9.1 Conjectura e Indução Matemática 567
B.9.2 Relações de Recorrência Homogêneas 567 B�10 Propriedades de Análise Assintótica B.10 569
B�11 Propriedades de Árvores Binárias B.11 571
C
Guia de Nomenclatura Usada em Identificadores
����������������������������������
575
C�1 Regras Básicas de Escrita de Identificadores C.1 575
C.1.1 Variáveis e Parâmetros Formais 575
C.1.2 Macros e Constantes de Enumeração 576
Tabela de Conteúdo | xv
C.1.4 Tipos 576
C.1.5 Rótulos de Estruturas 576
C�2 Glossário de Sufixos de Identificadores C.2 576