Sunteți pe pagina 1din 69

Departamento de Engenharia

Prof. Airton Jos Sachetim Garcia

Estrutura de Dados

Londrina
2015.2

Estrutura de Dados

Prof. airton jos sachetim garcia

Faculdade
PROGRAMA DE GRADUAO EM ENGENHARIA
DEPARTAMENTO DE ENGENHARIA

Airton Jos Sachetim Garcia

C++

LONDRINA-PR
2015.2

Estrutura de Dados

Prof. airton jos sachetim garcia

SACHETIM GARCIA, Airton Jos.


Software Excel 2010 / SACHETIM GARCIA, Airton Jos.
Londrina:
Coordenador (a):
Matria (Algoritmo e Estrutura de Dados, C++) Faculdade
Referncias: f. 110

Estrutura de Dados

Prof. airton jos sachetim garcia

INTRODUO
Este material apresenta uma coleo de algoritmos sobre uma variedade de estruturas de
dados de memria principal, estudadas na disciplina de Estrutura de Dados Algoritmos e
Estruturas de Dados.

Estrutura de Dados

Prof. airton jos sachetim garcia

1 Aula.
1.1 Uma breve histria do C++
O C++ foi inicialmente desenvolvido por Bjarne Stroustrup dos Bell Labs, durante a dcada de
1980 com o objetivo de implementar uma verso distribuda do ncleo do Unix. Como o Unix
era escrito em C, dever-se-ia manter a compatibilidade, ainda que adicionando novos recursos.
O C foi escolhido como base de desenvolvimento da nova linguagem, pois possua uma
proposta de uso genrico, era rpido e tambm portvel para diversas plataformas. Algumas
outras linguagens que tambm serviram de inspirao para o cientista da computao foram
ALGOL 68, Ada, CLU e ML.
Ainda em 1983 o nome da linguagem foi alterado de C with Classes para C++. Antes
implementada usando um pr-processador, a linguagem passou a exigir um compilador
prprio, escrito pelo prprio Stroustrup.
Novas caractersticas foram adicionadas, como funes virtuais, sobrecarga de operadores e
funes, melhorias na verificao de tipo de dado e estilo de comentrio de cdigo de uma
linha (//).
Em 1985 foi lanada a primeira edio do livro The C++ Programming Language, contendo
referncias para a utilizao da linguagem, j que ainda no era uma norma oficial.
A primeira verso comercial foi lanada em outubro do mesmo ano.
Em 1989 a segunda verso foi lanada, contendo novas caractersticas como herana mltipla,
classes abstratas, mtodos estticos, mtodos constantes e membros protegidos,
incrementando o suporte a orientao a objeto.
Assim como a linguagem, sua biblioteca padro tambm sofreu melhorias ao longo do tempo.
Sua primeira adio foi a biblioteca de E/S, e posteriormente a Standard Template Library
(STL); ambas tornaram-se algumas das principais funcionalidades que distanciaram a
linguagem em relao a C.
Criada primordialmente na HP por Alexander Stepanov no incio da dcada de 1990 para
explorar os potenciais da programao genrica, a STL foi apresentada a um comit unificado
ANSI e ISO em 1993 convite de Andrew Koenig.
Aps uma proposta formal na reunio do ano seguinte, a biblioteca recebe o aval do comit.
Pode-se dizer que C++ foi a nica linguagem entre tantas outras que obteve sucesso como uma
sucessora linguagem C, inclusive servindo de inspirao para outras linguagens como Java, a
IDL de CORBA e C#.

Estrutura de Dados

Prof. airton jos sachetim garcia

1.2 Compiladores
Um compilador um programa de sistema que traduz um programa descrito em uma
linguagem de alto nvel para um programa equivalente em cdigo de mquina para um
processador. Em geral, um compilador no produz diretamente o cdigo de mquina, mas sim
um programa em linguagem simblica (assembly) semanticamente equivalente ao programa
em linguagem de alto nvel. O programa em linguagem simblica ento traduzido para o
programa em linguagem de mquina atravs de montadores.
Para desempenhar suas tarefas, um compilador deve executar dois tipos de atividade. A
primeira atividade a anlise do cdigo fonte, onde a estrutura e significado do programa de
alto nvel so reconhecidos. A segunda atividade a sntese do programa equivalente em
linguagem simblica. Embora conceitualmente seja possvel executar toda a anlise e apenas
ento iniciar a sntese, em geral estas duas atividades ocorrem praticamente em paralelo. Para
apresentar um exemplo das atividades que um compilador deve desempenhar, considere o
seguinte trecho de um programa em C:

Para o compilador, este segmento nada mais do que uma seqncia de caracteres em um
arquivo texto. O primeiro passo da anlise reconhecer que agrupamentos de caracteres tm
significado para o programa, por exemplo, saber que int uma palavra-chave da linguagem e
que a e b sero elementos individuais neste programa. Posteriormente, o compilador deve
reconhecer que a seqncia int a ,corresponde a uma declarao de uma varivel inteira cujo
identificador recebeu o nome a.
As regras de formao de elementos e frases vlidas de uma linguagem so expressas na
gramtica da linguagem. O processo de reconhecer os comandos de uma gramtica
conhecido como reconhecimento de sentenas.

Estrutura de Dados

Prof. airton jos sachetim garcia

1.3 Estrutura Bsica de um programa C++.


Temos abaixo a estrutura de um programa escrito na linguagem C++:

As duas primeiras linhas so o cabealho do programa. Todo programa deve ter um cabealho
desse tipo para definir quais as bibliotecas ele utilizar. Bibliotecas so arquivos que
normalmente so instalados juntos com o compilador e que possuem os comandos e funes
pertencentes linguagem.
#include<>
Serve para indicar ao compilador todas as bibliotecas que este programa utilizar. Na maioria
dos programas que escreveremos durante esta apostila, s utilizaremos o
#include <iostream>
,que serve para incluir a biblioteca iostream em nossos programas.
Esta biblioteca contm as principais funes, comandos e classes de entrada e sada de C++,
necessrias para realizar programas que, por exemplo, recebam dados via teclado e enviem
dados via monitor.
A segunda linha do cabealho,
using namespace std;
, um aviso ao compilador que estaremos utilizando os comandos e funes padro de C++.
Ele necessrio porque em C++ podemos criar vrias bibliotecas para serem utilizveis em
vrios programas.
Cada uma dessas bibliotecas contm comandos, classes e funes prprias, e para evitar
confuses e problemas com os nomes destes comandos, utilizamos o cabealho using
namespace ...; para definir qual o campo de nomes que estamos utilizando.
Num programa normal, que no utiliza outras bibliotecas alm do padro de C++, utilizamos o
namespace std como nosso campo de nomes de comandos e funes. Assim, sempre que
utilizamos um comando prprio de C++, o compilador reconhecer automaticamente este
comando como sendo pertencente biblioteca padro de C++.
Assim como em C++, tudo o que acontece durante a execuo do programa est
contido dentro de uma funo principal, chamada main. Declaramos a funo main com:

Estrutura de Dados

Prof. airton jos sachetim garcia

int main ( )
Todos os comandos executados pelo programa esto contidos entre as chaves { }
da funo main.
O encerramento de um programa geralmente feito da mesma maneira para todos eles. As
duas ltimas linhas antes do fecha-chaves so dois comandos normalmente utilizados ao
fim de um programa.
system(PAUSE > null)
uma chamada de funo prpria de C++.
A funo system( ) recebe argumentos como o PAUSE que na verdade so comandos para o
sistema operacional. Neste caso, ela recebe o comando PAUSE > null para pausar a
execuo do programa at que o usurio aperte uma tecla qualquer. Utilizamos este recurso
para que a tela do programa no seja terminada automaticamente pelo sistema, impedindo
que vejamos os resultados do programa.
Finalmente, o comando
return 0
a resposta da funo main para o sistema.

1.4 Tipos de Variveis


Quando definimos uma varivel em C++, precisamos informar ao compilador o tipo da varivel:
um nmero inteiro, um nmero de ponto flutuante, um caractere, e assim por diante. Essa
informao diz ao compilador quanto espao deve ser reservado na memria para a varivel, e
o tipo de valor que ser armazenado nela. As variveis mais utilizadas, em um curso de C++
bsico so: A tabela abaixo apresenta os tipos para valores numricos inteiros.

A linguagem oferece ainda dois tipos bsicos para a representao de nmeros reais (ponto
flutuante): float e double. A tabela abaixo compara estes dois tipos.

Estrutura de Dados

Prof. airton jos sachetim garcia

1.5 Declarao de variveis.


1.5.1 Varivel.
a maneira pela qual se faz a alocao de memria para armazenarmos um dado (valor) na
memria do computador, deve-se reservar o espao correspondente ao tipo do dado a ser
armazenado.

1.5.2 Declarar varivel.


a associao de um nome (da varivel) a este espao de memria que foi utilizado para
armazenar um dado.

1.5.3 Constantes.
Quando temos que usar valores constantes, que no se alteram durante o processo.
A diferena bsica em relao s variveis, como os nomes dizem (variveis e constantes),
que o valor armazenado numa rea de constante no pode ser alterado.

1.5.4 Restries para as atribuies de variveis.

As constantes so valores que sero mantidos fixos pelo compilador;


O nome das variveis deve comear com uma letra ou um sublinhado _;
Os demais caracteres podem ser letras, nmeros ou sublinhado;
O nome da varivel no pode ser igual a uma palavra reservada e aos nomes das
funes;
Tamanho mximo para o nome de uma varivel 32 caracteres.

1.5.5 Modificador const.


A linguagem C++ introduz um novo modificador chamado const, que tem comportamento
variado dependendo do local onde est sendo declarado. Sua funo, basicamente,
estabelecer um vnculo entre declarao e obrigatoriedade da coerncia no uso do smbolo
declarado. A princpio, quando declaramos uma constante com este modificador fazemos com
que seja obrigatrio o uso do smbolo de forma que o mesmo no possa ter seu valor alterado.
Assim, se fizermos:

Estrutura de Dados

Prof. airton jos sachetim garcia

A constante x no poder deixar de ter valor igual a 4. Qualquer tentativa de modificar o valor
da constante ao longo do programa ser reportada como erro pelo compilador.

1.6 O comando Include e as Bibliotecas.


C++ tem a capacidade de importar bibliotecas.
A importncia da biblioteca em C imensa, pois ela nos poupa de muita programao. Uma
vez que a funo j est pronta dentro da biblioteca, basta importar tal biblioteca e utilizar a
funo que queremos.
Caso quisssemos mostrar uma mensagem na tela, voc no tem que produzir uma funo
inteira ou criar um comando novo, basta importar a biblioteca <iostream.h>, que possui a
finalidade de I/O (entrada e sada) de dandos. Quando o programa for compilado, o
compilador ir buscar nas bibliotecas exigidas pelo usurio tais funes para saber como
utiliz-las no programa.
O papel do pr-processamento indicar, antes mesmo de compilar, os parmetros necessrios
para ser criado o arquivo executvel.
A importao de uma biblioteca dada pelo comando #include (incluir) seguido da biblioteca
entre os sinais de menor (<) e maior (>).
Como importar a biblioteca padro de entrada e sada de C++.

As bibliotecas de C so diferentes das bibliotecas de C++. Apesar de muitos compiladores de


C++ suportarem as bibliotecas de C, nenhum compilador exclusivamente de C suporta
bibliotecas de C++.

1.6.1 Algumas bibliotecas do C++.

<algorithm>
<fstream>
<functional>
<iostream>
<locale>
<map>
<set>
<sstream>
<string>
<vector>
<Math.h>

Estrutura de Dados

Prof. airton jos sachetim garcia

1.7 Biblioteca <Math.h>.


A biblioteca <math.h> nos ajuda nos clculos matemticos, onde podemos encontrar
facilmente funes para calcular potncias, raz quadrada, funes trigonomtricas para
clculos que envolvem seno, co-seno e tangente, alm de constantes para nmeros irracionais
como, por exemplo, PI () e 2.

1.7.1 Trigonomtricas.
sin (): Retorna o valor do seno. Recebe como argumento o valor dos graus em double.
cos (): Retorna o valor do co-seno. Recebe como argumento o valor dos graus em
double.
tan (): Retorna o valor da tangente. Recebe como argumento o valor dos graus em
double.

1.7.2 Logartmicas.
log (): Retorna o valor do logaritmo na base 2. Exige um argumento do tipo double.
log10 (): Retorna o valor do logaritmo na base 10. Exige um argumento do tipo double.

1.7.3 Potncia.
sqrt (): Retorna o valor da raiz quadrada. Recebe como argumento um double do qual
ele deve extrair a raiz.
pow (): Retorna o valor da base elevada ao expoente. Recebe dois argumentos do tipo
double, o primeiro a base e o segundo o expoente. Por exemplo: se quisermos saber
o resultado da operao 210,faramos pow (2, 10).

1.8 Operadores.
A linguagem C++ oferece uma gama variada de operadores, entre binrios e unrios. Os
operadores bsicos so apresentados a seguir.

1.8.1 Operadores Aritmticos.

1.8.1.1 Operadores aritmticos binrios.


adio (+);
subtrao (-);
multiplicao (*);
diviso (/);
operador mdulo (%).

Estrutura de Dados

Prof. airton jos sachetim garcia

A operao feita na preciso dos operandos. Assim, a expresso 5/2 resulta no valor 2, pois a
operao de diviso feita em preciso inteira, j que os dois operandos (5 e 2) so constantes
inteiras. A diviso de inteiros trunca a parte fracionria, pois o valor resultante sempre do
mesmo tipo da expresso. Conseqentemente, a expresso 5.0/2.0 resulta no valor real 2.5,
pois a operao feita na preciso real (double, no caso).
O operador mdulo, %, no se aplica a valores reais, seus operandos devem ser do tipo
inteiro. Este operador produz o resto da diviso do primeiro pelo segundo operando. Como
exemplo de aplicao deste operador, podemos citar o caso em que desejamos saber se o
valor armazenado numa determinada varivel inteira x par ou mpar. Para tanto, basta
analisar o resultado da aplicao do operador %, aplicado varivel e ao valor dois.

1.8.2 Precedncia de operadores.


Os operadores *, / e % tm precedncia maior que os operadores + e -. O operador (-)
unrio tem precedncia maior que ( *, / e %). Operadores com mesma precedncia so
avaliados da esquerda para a direita. Assim, na expresso:
a + b * c /d
executa-se primeiro a multiplicao, seguida da diviso, seguida da soma. Podemos utilizar
parnteses para alterar a ordem de avaliao de uma expresso. Assim, se quisermos avaliar
a soma em primeiro, podemos escrever:
(a + b) * c /d

1.8.3 Precedncia e ordem de avaliao dos operadores.


A tabela abaixo mostra a precedncia, em ordem decrescente, dos principais operadores da
linguagem C++.

1.8.4 Operadores de atribuio (=).


A expresso a = 7, armazena na varivel a o valor sete.

Estrutura de Dados

Prof. airton jos sachetim garcia

A linguagem tambm permite utilizar os chamados operadores de atribuio compostos.


Comandos do tipo:
i = i + 2;
em que a varivel esquerda do sinal de atribuio tambm aparece direita, podem ser
escritas de forma mais compacta:
i += 2.
Usando o operador de atribuio composto +=. Analogamente, existem, entre outros, os
operadores de atribuio: -=, *=, /=, %=. De forma geral, comandos do tipo:
var op= expr;
so equivalentes a:
var = var op (expr);
Salientamos a presena dos parnteses em torno de expr. Assim:
x *= y + 1;
equivale a
x = x * (y + 1)
e no a
x = x * y + 1;

1.8.5 Operadores de incremento e decremento (++, --).


Os dois operadores no convencionais. So os operadores de incremento e decremento, que
possuem precedncia comparada ao - unrio e servem para incrementar e decrementar uma
unidade nos valores armazenados nas variveis. Assim, se n uma varivel que armazena um
valor, o comando:

n++;
incrementa de uma unidade o valor de n (anlogo para o decremento em n--). O aspecto no
usual que ++ e -- podem ser usados tanto como operadores pr-fixados (antes da varivel,
como em ++n) ou ps-fixados (aps a varivel, como em n++). Em ambos os casos, a varivel n
incrementada. Porm, a expresso ++n incrementa n antes de usar seu valor, enquanto n++
incrementa n aps seu valor ser usado. Isto significa que, num contexto onde o valor de n
usado, ++n e n++ so diferentes. Se n armazena o valor cinco, ento:

x = n++;
atribui 5 a x, mas:

x = ++n;
atribuiria 6 a x. Em ambos os casos, n passa a valer 6, pois seu valor foi incrementado em
uma unidade. Os operadores de incremento e decremento podem ser aplicados somente em
variveis; uma expresso do tipo x = (i + 1)++ ilegal.

Estrutura de Dados

Prof. airton jos sachetim garcia

Mesmo para programadores experientes, o uso das formas compactas deve ser feito com
critrio. Por exemplo, os comandos:

a = a + 1;
a += 1;
a++;
++a;
so todos equivalentes e o programador deve escolher o que achar mais adequado e simples.
Em termos de desempenho, qualquer compilador razovel capaz de otimizar todos estes
comandos da mesma forma.

1.8.6 Operadores relacionais e lgicos.

1.8.6.1 Relacionais.

Estes operadores comparam dois valores. O resultado produzido por um operador relacional
zero ou um. Em C++, no existe o tipo booleano (true ou false). O valor zero interpretado
como falso e qualquer valor diferente de zero considerado verdadeiro. Assim, se o resultado
de uma comparao for falso, produz-se o valor 0, caso contrrio, produz-se o valor 1.

1.8.6.2 Lgicos.

Expresses conectadas por && ou || so avaliadas da esquerda para a direita, e a avaliao


pra assim que a veracidade ou falsidade do resultado for conhecida. Recomendamos o uso
de parnteses em expresses que combinam operadores lgicos e relacionais.
Os operadores relacionais e lgicos so normalmente utilizados para tomada de decises.
No entanto, podemos utiliz-los para atribuir valores a variveis. Por exemplo, o trecho de
cdigo abaixo vlido e armazena o valor 1 em a e 0 em b.

Estrutura de Dados

Prof. airton jos sachetim garcia

Na avaliao da expresso atribuda varivel b, a operao (d>c) no chega a ser avaliada,


pois independente do seu resultado a expresso como um todo ter como resultado 0 (falso),
uma vez que a operao (c<20) tem valor falso.
1.8.7

Operador sizeof.

Outro operador fornecido por C, sizeof, resulta no nmero de bytes de um determinado


tipo. Por exemplo:

Armazena o valor 4 na varivel a, pois um float ocupa 4 bytes de memria. Este operador
pode tambm ser aplicado a uma varivel, retornando o nmero de bytes do tipo associado
varivel.

1.9 Converso de tipo.


Na maioria das linguagens, existem converses automticas de valores na avaliao de uma
expresso. Assim, na expresso 3/1.5, o valor da constante 3 (tipo int) promovido
(convertido) para double antes de a expresso ser avaliada, pois o segundo operando do tipo
double (1.5) e a operao feita na preciso do tipo mais representativo.
Quando, numa atribuio, o tipo do valor atribudo diferente do tipo da varivel, tambm
h uma converso automtica de tipo. Por exemplo, se escrevermos:
int a = 3.5; o valor 3.5 convertido para inteiro (isto , passa a valer 3) antes de a atribuio
ser efetuada. Como resultado, como era de se esperar, o valor atribudo varivel 3 (inteiro).
Alguns compiladores exibem advertncias quando a converso de tipo pode significar uma
perda de preciso ( o caso da converso real para inteiro, por exemplo).
O programador pode explicitamente requisitar uma converso de tipo atravs do uso do
operador de molde de tipo (operador cast). Por exemplo, so vlidos (e isentos de qualquer
advertncia por parte dos compiladores) os comandos abaixo.
int a, b;
a = (int) 3.5;
b = (int) 3.5 % 2;

Precedncia e ordem de avaliao dos operadores.


Em ordem decrescente, dos principais operadores da linguagem C++.

Estrutura de Dados

Prof. airton jos sachetim garcia

1.10 Entrada e sada bsicas.


Em C++ tudo feito atravs de funes, inclusive as operaes de entrada e sada. Por isso, j
existe em C uma biblioteca padro que possui as funes bsicas normalmente necessrias. Na
biblioteca padro de C++, podemos, por exemplo, encontrar funes matemticas do tipo raiz
quadrada, seno, cosseno, etc., funes para a manipulao de cadeias de caracteres e funes de
entrada e sada. Nesta seo, sero apresentadas as duas funes bsicas de entrada e sada
disponibilizadas pela biblioteca padro. Para utiliz-las, necessrio incluir o prottipo destas
funes no cdigo. Este assunto foi abordado na seo 1.6.
Por ora, basta saber que preciso escrever:
#include <iostream.h> C++.
#include <stdio.h> C;

1.10.1 Sada.
cout << Exemplo<<endl; C++.
cout o dispositivo de sada padro no C++ (geralmente o monitor), e a frase completa
insere uma seqncia de caracteres no dispositivo de sada. O cout declarado no
arquivo de cabealho <iostream.h>, ento pra que seja possvel utiliza-lo, esse arquivo
precisa ser incluso. Note que a frase termina com um caractere ponto-e-vrgula (Esse
caractere significa o fim da instruo e precisa ser includo aps toda instruo em
qualquer programa em C++ )Um dos erros mais comuns dos programadores de C++
devido ao fato de esquecerem de incluir um ponto-e-vrgula; no final de cada
instruo.
printf (formato, lista de constantes/variveis/expresses...); C;
O primeiro parmetro uma cadeia de caracteres, em geral delimitada com aspas, que
especifica o formato de sada das constantes, variveis e expresses listadas em seguida.
Para cada valor que se deseja imprimir, deve existir um especificador de formato
correspondente na cadeia de caracteres formato. Os especificadores de formato variam
com o tipo do valor e a preciso em que queremos que eles sejam impressos. Estes
especificadores so precedidos pelo caractere % e podem ser, entre outros:

Alguns exemplos em C: printf ("%d %g\n", 33, 5.3);


tem como resultado a impresso da linha:
33 5.3
Ou:
printf ("Inteiro = %d Real = %g\n", 33, 5.3);
com sada:
Inteiro = 33 Real = 5.3
Estrutura de Dados

Prof. airton jos sachetim garcia

isto , alm dos especificadores de formato, podemos incluir textos no formato, que
so mapeados diretamente para a sada. Assim, a sada formada pela cadeia de
caracteres do formato onde os especificadores so substitudos pelos valores
correspondentes.
Existem alguns caracteres de escape que so freqentemente utilizados nos formatos
de sada. So eles:

Ainda, se desejarmos ter como sada um caractere %, devemos, dentro do formato,


escrever %%.
possvel tambm especificarmos o tamanho dos campos:

A funo printf retorna o nmero de campos impressos. Salientamos que para cada
constante, varivel ou expresso listada devemos ter um especificador de formato
apropriado.

1.10.2 Entrada.
cin>>varivel; C++
A entrada padro no C++ feita aplicando-se o operador sobrecarregado de extrao
(>>) no comando cin. Isso precisa ser seguido pela varivel que ir guardar o dado que
ser lido.
Declarando a varivel como desejada, ento espera por uma entrada do cin (teclado)
para que possa guard-la em um espao reservado da memria ROM. O comando cin
s pode processar a entrada do teclado depois que a tecla ENTER for pressionada.
Sendo assim, mesmo que voc pea um nico caractere, o cin no ir processar a
entrada at que o usurio pressione ENTER depois que o caractere tenha sido digitado.
Voc precisa sempre considerar o tipo da varivel que voc est usando para guardar
o valor extrado pelo cin. Se voc pedir um inteiro, voc receber um inteiro, se voc

Estrutura de Dados

Prof. airton jos sachetim garcia

pedir um caractere, voc receber um caractere, e se voc pedir uma string de


caracteres, voc receber uma string de caracteres.
scanf (formato, lista de endereos das variveis...); C.
O formato deve possuir especificadores de tipos similares aos mostrados para a
funo printf. Para a funo scanf, no entanto, existem especificadores diferentes para
o tipo float e o tipo double:

A principal diferena que o formato deve ser seguido por uma lista de endereos de
variveis (na funo printf passamos os valores de constantes, variveis e expresses).
Na seo sobre ponteiros, este assunto ser tratado em detalhes. Por ora, basta saber
que, para ler um valor e atribu-lo a uma varivel, devemos passar o endereo da
varivel para a funo scanf. O operador & retorna o endereo de uma varivel. Assim,
para ler um inteiro, devemos ter:
int n;
scanf ("%d", &n);
Para a funo scanf, os especificadores %f, %e e %g so equivalentes. Aqui, caracteres
diferentes dos especificadores no formato servem para cercar a entrada. Por exemplo:
scanf ("%d:%d", &h, &m);
obriga que os valores (inteiros) fornecidos sejam separados pelo caractere dois pontos
(:).
Um espao em branco dentro do formato faz com que sejam "pulados" eventuais
brancos da entrada. Os especificadores %d, %f, %e e %g automaticamente pulam os
brancos que precederem os valores numricos a serem capturados. A funo scanf
retorna o nmero de campos lidos com sucesso.

1.11 Controle de fluxo.


C++ prov as construes fundamentais de controle de fluxo necessrias para
programas bem estruturados: agrupamentos de comandos, tomadas de deciso (if-else),
laos com teste de encerramento no incio (while, for) ou no fim (do-while), e seleo
de um dentre um conjunto de possveis casos (switch).

Estrutura de Dados

Prof. airton jos sachetim garcia

1.11.1 Deciso.
Os mtodos de tomada de deciso no C++ esto presentes para as tarefas mais corriqueiras
que o programa deve executar.

1.11.1.1

Estrutura IF/ELSE.

Uma ao muito importante que o processador de qualquer computador executa, e que o


torna diferente de qualquer outra mquina, a tomada de deciso definindo o que
verdadeiro e o que falso.

Estrutura de Dados

Prof. airton jos sachetim garcia

possvel observar que podemos criar um programa com quantas condies queremos,
restringindo a cada condio, uma ao ou um conjunto de aes.
Alguns exemplos para serem refeitos.
Elabore um programa que diga qual ao, ou aes foram escolhidas:
a) Ao 1: caso o nmero seja maior ou igual a 2.
b) Ao 2: caso o nmero seja maior que 1.
c) Ao 3: caso no seja satisfeita nenhuma condio.
Observe que o erro encontra-se no uso do else if, com ele, exclumos possibilidades possveis
de respostas. Por exemplo, se digitarmos o nmero 3 no programa acima, o compilador nos
dar como sada apenas a primeira condio ("Ao 1 escolhida), onde na verdade temos
duas respostas, pois satisfaz a ao 1 e 2 simultaneamente. Se substituirmos o if no lugar do
else if, o compilador nos dar as 2 respostas possveis ("Ao 1 escolhida e "Ao 2
escolhida), com isso, corrigiramos o problema da redundncia do nosso exemplo. Com o uso
apenas do if e do else possvel o compilador executar vrias condies que ocorram
simultaneamente.
Exemplos de Aplicao.
1. Dados dois nmeros reais quaisquer, desenvolva um programa que diga se eles so
iguais ou diferentes.
Soluo:

Estrutura de Dados

Prof. airton jos sachetim garcia

2. Dado um nmero qualquer, determinar se este neutro, positivo ou negativo.


Soluo:

3. Elabore um programa que identifique se um nmero inteiro digitado par, impar ou


nulo
Soluo:
#include<iostream>
#include<conio.h>
#include <math.h>
using namespace std;
main()
{int n;
cout<<"digite o numero"<<endl;
cin>>n;
if (n%2==0)
{
if (n==0)
{cout<<" nulo "<<endl;}
else
{cout<<" par "<<endl;}
}
else
{cout<<"impar"<<endl;}
getch();}

Estrutura de Dados

Prof. airton jos sachetim garcia

4. Dado um nmero real qualquer, calcule sua raiz quadrada.


Soluo:

Observe que o comando pow serve para realizar operaes com exponenciais. No nosso caso:
a = pow(n,0.5), estamos atribuindo varivel a, a seguinte expresso exponencial n elevado a
0.5. De forma genrica, no comando pow (A,B), teremos a funo exponencial, onde A a base
e B o expoente.

1.11.2 Repetio.
As estruturas de repeties so muito importantes para a soluo de problemas na
programao, pois muitas vezes os mesmo procedimentos tm que ser executados mais de
uma vez, ou um nmero de vezes varivel.
Em C/C++, basicamente existem trs tipos de estrutura de repetio: for, while e do while.

1.11.2.1

Estrutura FOR.

Para o for, como qualquer iterao (repetio), precisa de uma varivel para controlar os loops
(voltas). No for, essa varivel dever ser iniciada, indicando pelo seu critrio de execuo, e
forma de incremento ou decremento. Ou seja, o for precisa de trs condies. Vale salientar
que essas condies so separadas por ponto-e-vrgula. O comando deve ser inserido no
compilador da seguinte forma:
Um dos exemplos mais utilizados o clculo da potncia de um nmero, ou o fatorial de um
nmero, para a potncia o usurio informa ao programa a base e o expoente. O programa
deve fazer o nmero de interaes iguais o nmero x do expoente. Considerando o nmero do
expoente natural, positivo e maior que zero, temos o seguinte programa:

Estrutura de Dados

Prof. airton jos sachetim garcia

Observe que em for (int i=0; i<x; i++ ), temos as trs condies dentro do parnteses.

Exemplos de Aplicao.
1. Elabore um programa que calcule o fatorial de um nmero dado.
Soluo:

2. Um nmero dito perfeito quando a soma de seus divisores (exceto ele mesmo), ele
prprio. Exemplo 28, divisores = 14+7+4+2+1 =28. Elabore um programa que diga se o
nmero digitado perfeito ou no.
Soluo:

Estrutura de Dados

Prof. airton jos sachetim garcia

1.11.2.2

Estrutura WHILE.

Outra forma de iterao (repetio) em C/C++ o WHILE. O while executa uma comparao
com a varivel. Se a comparao for verdadeira, ele executa o bloco de instrues, quantas
vezes forem necessrias, at a comparao se tornar falsas.

Exemplos de Aplicao.
1. Elabore um programa que imprima os termos de uma progresso aritmtica cujo
primeiro termo 3 e a razo 5. Parar o processamento quando for impresso um termo
maior que 100.
Soluo:

Estrutura de Dados

Prof. airton jos sachetim garcia

2. Elabore um algoritmo que imprima os termos da serie abaixo. Parar o processamento


quando for impresso um termo negativo.
15, 30, 60, 12, 24, 48, 9, 18, 36, 6, 12, 24, ...
Soluo:

Exemplo de Aplicao em C:
muito comum, em programas computacionais, termos procedimentos iterativos, isto
, procedimentos que devem ser executados em vrios passos. Como exemplo, vamos
considerar o clculo do valor do fatorial de um nmero inteiro no negativo. Por
definio:

Enquanto expr for avaliada em verdadeiro, o bloco de comandos executado


repetidamente. Se expr for avaliada em falso, o bloco de comando no executado e a

Estrutura de Dados

Prof. airton jos sachetim garcia

execuo do programa prossegue. Uma possvel implementao do clculo do fatorial


usando while mostrada a seguir.

Mais compacta e amplamente utilizada, atravs de laos for. Faa este mesmo exemplo em
FOR.

1.11.2.3

Estrutura DO/WHILE.

A estrutura de repetio DO/WHILE parte do princpio de que se deve fazer algo primeiro e s
depois comparar uma varivel para saber se o loop ser executado mais uma vez. A estrutura
do/while parecida com a do while, no aspecto de possuir apenas uma condio, e ambas so
estruturas de repetio, porm o do/while, diferentemente do while, informa a condio ao
compilador apensa no final da estrutura.

Estrutura de Dados

Prof. airton jos sachetim garcia

1.11.2.4

Estrutura Switch / Case

Outra forma de estrutura seletiva o switch. Dentro do switch h o case (que significa caso).
Ou seja, quase que um if com vrias possibilidades, mas com algumas diferenas
importantes.
Primeira diferena: Os cases no aceitam operadores lgicos. Portanto, no possvel fazer
uma comparao. Isso limita o case a apenas valores definidos.
Segunda diferena: O switch executa seu bloco em cascata. Ou seja, se a varivel indicar para
o primeiro case e dentro do switch tiver 5 cases, o switch executar todos os outros 4 cases a
no ser que utilizemos o comando para sair do switch. (Nos referimos ao BREAK).
Agora, que conhecemos diferenas importantes, vamos ver como proceder com o switch /
case.
O primeiro comando switch deve-se colocar entre parnteses a varivel na qual est guardado
o valor que ser avaliado pelo case. Ento, abre-se o bloco de dados.
Dentro do bloco de dados colocamos o comando case e logo aps um valor terminando a
linha com dois pontos (:). Preste ateno no tipo de varivel que ser colocado, pois h
diferenas entre um dado e outro. Por exemplo: 1 no a mesma coisa que '1' e 'a' no a
mesma coisa que 'A'. Ento, estruturado o comando que ser executado pelo case.
Estruturalmente, seria isso:

Estrutura de Dados

Prof. airton jos sachetim garcia

Exemplo de Aplicao:
1. Elabore uma simples calculadora que realize as operaes de adio, subtrao,
multiplicao e diviso, utilizando a estrutura switch/case.
Soluo:

Perceba que no final de cada case h um break. Porque se no houvesse, o switch continuaria
executando at o final. Por exemplo, no exerccio anterior, havia 4 casos (case), e escolhemos
a operao 2, caso no houvesse o break, o programa executaria os casos seguintes, no nosso
caso, a operao 3 e 4.

Estrutura de Dados

Prof. airton jos sachetim garcia

Default
Default, do ingls padro, o case que ativado caso no tenha achado nenhum case
definido. Ou seja, o que aconteceria em ltimo caso. Vamos imaginar o seguinte
cenrio: Seu programa pede para que o usurio digite apenas duas opes (S ou N)
para reiniciar o programa. Mas, propositalmente ou por engano, o usurio digita uma
opo totalmente diferente. E agora? O que seu programa deve fazer? aqui que o
default entra. Geralmente o default quando previsto um erro, uma entrada de
dado incorreta ou no de acordo com o contexto. O default tem seu papel parecido
com o else, da estrutura if/else, caso nenhuma condio for feita, far os comandos
definidos no default.

Como podemos ver, h dois casos: S para reiniciar ou N para sair. Se por acaso algum digitar
algo diferente disso, executa-se o default, que informa que a opo escolhida invalida e
repete a pergunta se o usurio deseja sair do programa, at que seja digitada uma opo
valida (S ou N). Como a linguagem C/C++ case sensitive (diferencia maisculas de minsculas)
usamos uma funo para deixar a letra maiscula (toupper da biblioteca ctype). Agora, no
importa o que o usurio digitar, pois o programa est preparado para reagir qualquer
entrada de dado.
Lista de exerccios de fixao lista03

Estrutura de Dados

Prof. airton jos sachetim garcia

1.11.3 Interrupes com break e continue.


A linguagem C/C++ oferece duas formas para a interrupo antecipada de um determinado lao.

1.11.3.1

Break.

Quando utilizado dentro de um lao, interrompe e termina a execuo do mesmo. A execuo


prossegue com os comandos subseqentes ao bloco. O cdigo abaixo, em C, ilustra o efeito de
sua utilizao.
Faa em C++.

A sada deste programa, se executado, ser:


0 1 2 3 4 fim, pois, quando i tiver o valor 5, o lao ser interrompido e finalizado pelo
comando break, passando o controle para o prximo comando aps o lao, no caso
uma chamada final de printf.

1.11.3.2

Continue.

Interrompe a execuo dos comandos de um lao. A diferena bsica em relao ao comando


break que o lao no automaticamente finalizado. O comando continue interrompe a
execuo de um lao passando para a prxima iterao. Assim, o cdigo, em C++:
Faa em C.

gera a sada:
0 1 2 3 4 6 7 8 9 fim

Estrutura de Dados

Prof. airton jos sachetim garcia

1.12 Funes.
As funes dividem grandes tarefas de computao em tarefas menores. Os programas em
C/C++ geralmente consistem de vrias pequenas funes em vez de poucas funes de maior
tamanho. A criao de funes evita a repetio de cdigo, de modo que um procedimento que
repetido deve ser transformado numa funo que, ser chamada diversas vezes. Um
programa bem estruturado deve ser pensado em termos de funes, e estas, por sua vez,
podem (e devem, se possvel) esconder do corpo principal do programa detalhes ou
particularidades de implementao. Em C/C++, tudo feito atravs de funes. Os exemplos
anteriores utilizam as funes da biblioteca padro para realizar entrada e sada. Nesta seo,
discutiremos a codificao de nossas prprias funes.A forma geral para definir uma funo :

Para melhor ilustrar a criao de funes, consideraremos o clculo do fatorial de um nmero,


exemplo que j de nosso conhecimento, em seo anteriores.
Podemos escrever uma funo que, dado um determinado nmero inteiro no negativo n,
imprime o valor de seu fatorial. Um programa, em C, que utiliza esta funo seria:
Faa em C++.

Neste exemplo, que a funo fat recebe como parmetro o nmero cujo fatorial deve ser
impresso. Os parmetros de uma funo devem ser listados, com seus respectivos tipos, entre
os parnteses que seguem o nome da funo. Quando uma funo no tem parmetros,
colocamos a palavra reservada void entre os parnteses. Devemos notar que main tambm
uma funo; sua nica particularidade consiste em ser a funo automaticamente executada
aps o programa ser carregado. Como as funes main que temos apresentado no recebem
parmetros, temos usado a palavra void na lista de parmetros.

Estrutura de Dados

Prof. airton jos sachetim garcia

Alm de receber parmetros, uma funo pode ter um valor de retorno associado. No
exemplo do clculo do fatorial, a funo fat no tem nenhum valor de retorno, portanto
colocamos a palavra void antes do nome da funo, indicando a ausncia de um valor de
retorno.

A funo main obrigatoriamente deve ter um valor inteiro como retorno. Esse valor pode
ser usado pelo sistema operacional para testar a execuo do programa. A conveno
geralmente utilizada faz com que a funo main retorne zero no caso da execuo ser bem
sucedida ou diferente de zero no caso de problemas durante a execuo.
Por fim, salientamos que C exige que se coloque o prottipo da funo antes desta ser
chamada. O prottipo de uma funo consiste na repetio da linha de sua definio
seguida do caractere (;). Temos ento:

A rigor, no prottipo no h necessidade de indicarmos os nomes dos parmetros, apenas os


seus tipos, portanto seria vlido escrever: void fat (int);. Porm, geralmente
mantemos os nomes dos parmetros, pois servem como documentao do significado de
cada parmetro, desde que utilizemos nomes coerentes. O prottipo da funo necessrio
para que o compilador verifique os tipos dos parmetros na chamada da funo. Por
exemplo, se tentssemos chamar a funo com fat(4.5); o compilador provavelmente
indicaria o erro, pois estaramos passando um valor real enquanto a funo espera um valor
inteiro. devido a esta necessidade que se exige a incluso do arquivo stdio.h para a
utilizao das funes de entrada e sada da biblioteca padro. Neste arquivo, encontram-se,
entre outras coisas, os prottipos das funes printf e scanf.
Uma funo pode ter um valor de retorno associado. Para ilustrar a discusso, vamos
reescrever o cdigo acima, fazendo com que a funo fat retorne o valor do fatorial. A
funo main fica ento responsvel pela impresso do valor.

Estrutura de Dados

Prof. airton jos sachetim garcia

1.13 Pilha de execuo.


Apresentada a forma bsica para a definio de funes, discutiremos agora, em detalhe,
como funciona a comunicao entre a funo que chama e a funo que chamada. J
mencionamos na introduo deste curso que as funes so independentes entre si. As
variveis locais definidas dentro do corpo de uma funo (e isto inclui os parmetros das
funes) no existem fora da funo. Cada vez que a funo executada, as variveis locais
so criadas, e, quando a execuo da funo termina, estas variveis deixam de existir.
A transferncia de dados entre funes feita atravs dos parmetros e do valor de retorno
da funo chamada. Conforme mencionado, uma funo pode retornar um valor para a funo
que a chamou e isto feito atravs do comando return. Quando uma funo tem um valor de
retorno, a chamada da funo uma expresso cujo valor resultante o valor retornado pela
funo. Por isso, foi vlido escrevermos na funo main acima a expresso r = fat(n); que
chama a funo fat armazenando seu valor de retorno na varivel r.

Estrutura de Dados

Prof. airton jos sachetim garcia

Sada do programa Fatorial de 5 = 120


Vamos considerar um esquema representativo da memria do computador. Salientamos que
este esquema apenas uma maneira didtica de explicar o que ocorre na memria do
computador. Suponhamos que as variveis so armazenadas na memria como ilustrado
abaixo. Os nmeros direita representam endereos (posies) fictcios de memria e os
nomes esquerda indicam os nomes das variveis. A figura abaixo ilustra este esquema
representativo da memria que adotaremos.

Ento, podemos analisar passo a passo a evoluo do programa mostrado acima, ilustrando
o funcionamento da pilha de execuo.

Estrutura de Dados

Prof. airton jos sachetim garcia

Isto ilustra por que o valor da varivel passada nunca ser alterado dentro da funo.
A seguir, discutiremos uma forma para podermos alterar valores por passagem de
parmetros, o que ser realizado passando o endereo de memria onde a varivel est
armazenada.

1.14 Ponteiros de variveis.


A linguagem C permite o armazenamento e a manipulao de valores de endereos de
memria. Para cada tipo existente, h um tipo ponteiro que pode armazenar endereos de
memria onde existem valores do tipo correspondente armazenados. Por exemplo, quando
escrevemos:

int a
Declaramos uma varivel com nome a que pode armazenar valores inteiros.
Automaticamente, reserva-se um espao na memria suficiente para armazenar valores
inteiros (geralmente 4 bytes).
Da mesma forma que declaramos variveis para armazenar inteiros, podemos declarar
variveis que, em vez de servirem para armazenar valores inteiros, servem para armazenar
valores de endereos de memria onde h variveis inteiras armazenadas. C/C++ no reserva
uma palavra especial para a declarao de ponteiros; usamos a mesma palavra do tipo com
os nomes das variveis precedidas pelo caractere *. Assim, podemos escrever:

int *p
Neste caso, declaramos uma varivel com nome p que pode armazenar endereos de
memria onde existe um inteiro armazenado. Para atribuir e acessar endereos de memria,
a linguagem oferece dois operadores unrios ainda no discutidos. O operador unrio &
(endereo de), aplicado a variveis, resulta no endereo da posio da memria reservada
para a varivel. O operador unrio * (contedo de), aplicado as variveis do tipo ponteiro,
acessa o contedo do endereo de memria armazenado pela varivel ponteiro. Para

Estrutura de Dados

Prof. airton jos sachetim garcia

exemplificar, vamos ilustrar esquematicamente, atravs de um exemplo simples, o que


ocorre na pilha de execuo. Consideremos o trecho de cdigo mostrado na figura abaixo.

Aps as declaraes, ambas as variveis, a e p, tem armazenadas como valores "lixo", pois
no foram inicializadas. Podemos fazer atribuies como exemplificado nos fragmentos de
cdigo da figura a seguir:

Nas atribuies ilustradas na figura acima, a varivel a recebe, indiretamente, ou seja, o


endereo da varivel a recebe o valor o valor 6, pois estamos atribuindo para *p que aponta
para o endereo de a.
Dizemos que p aponta para a, da o nome ponteiro. Em vez de criarmos valores fictcios para
os endereos de memria no nosso esquema ilustrativo da memria, podemos desenhar setas
graficamente, sinalizando que um ponteiro aponta para uma determinada varivel.

Estrutura de Dados

Prof. airton jos sachetim garcia

Alguns exemplos.

imprime o valor 2.

1.14.1 Passando ponteiros para funes.


Os ponteiros oferecem meios de alterarmos valores de variveis acessando-as indiretamente.
J discutimos que as funes no podem alterar diretamente valores de variveis da funo
que fez a chamada.
No entanto, se passarmos para uma funo os valores dos endereos de memria onde suas
variveis esto armazenadas, a funo pode alterar, indiretamente, os valores das variveis da
funo que a chamou.
Uma funo projetada para trocar os valores entre duas variveis. O cdigo abaixo:

No funciona como esperado (sero impressos 5 e 7), pois os valores de a e b da funo


main no so alterados. Alterados so os valores de x e y dentro da funo troca, mas
eles no representam as variveis da funo main, apenas so inicializados com os valores
de a e b. A alternativa fazer com que a funo receba os endereos das variveis e, assim,
alterar seus valores indiretamente. Reescrevendo:

Estrutura de Dados

Prof. airton jos sachetim garcia

Mostrando graficamente.

1.15 Recursividade.
As funes podem ser chamadas recursivamente, isto , dentro do corpo de uma funo
podemos chamar novamente a prpria funo. Se uma funo A chama a prpria funo A,
dizemos que ocorre uma recurso direta. Se uma funo A chama uma funo B que, por
sua vez, chama A, temos uma recurso indireta. Diversas implementaes ficam muito mais
fceis usando recursividade. Por outro lado, implementaes no recursivas tendem a ser
mais eficientes em relao ao tempo.
Para cada chamada de uma funo, recursiva ou no, os parmetros e as variveis locais so
empilhados na pilha de execuo. Assim, mesmo quando uma funo chamada
recursivamente, cria-se um ambiente local para cada chamada. As variveis locais de
chamadas recursivas so independentes entre si, como se estivssemos chamando funes
diferentes.
Estrutura de Dados

Prof. airton jos sachetim garcia

As implementaes recursivas devem ser pensadas considerando-se a definio recursiva


do problema que desejamos resolver. Por exemplo, o valor do fatorial de um nmero pode
ser definido de forma recursiva:

Considerando a definio acima, fica muito simples pensar na implementao recursiva de


uma funo que calcula e retorna o fatorial de um nmero.

1.16 Pr-processador e macros.


Um cdigo C/C++, antes de ser compilado, passa por um pr-processador. O pr-processador
de C/C++ reconhece determinadas diretivas e altera o cdigo para, ento, envi-lo ao
compilador.

1.16.1 #include.
Uma das diretivas reconhecidas pelo pr-processador, e j utilizada nos nossos exemplos,
#include. Ela seguida por um nome de arquivo e o pr-processador a substitui pelo
corpo do arquivo especificado. como se o texto do arquivo includo fizesse parte do
cdigo fonte.
Uma observao: quando o nome do arquivo a ser includo envolto por aspas
("arquivo"), o pr-processador procura primeiro o arquivo no diretrio atual e, caso no o
encontre, o procura nos diretrios de include especificados para compilao. Se o arquivo
colocado entre os sinais de menor e maior (<arquivo>), o pr-processador procura somente no
no diretrio de include.

Estrutura de Dados

Prof. airton jos sachetim garcia

1.16.2 #define.
muito utilizada e que ser agora discutida a diretiva de definio. Por exemplo, uma funo
para calcular a rea de um crculo pode ser escrita da seguinte forma:

Neste caso, antes da compilao, toda ocorrncia da palavra PI (desde que no envolvida
por aspas) ser trocada pelo nmero 3.14159.
C permite ainda a utilizao da diretiva de definio com parmetros. vlido escrever, por
exemplo:

aps esta definio existir uma linha de cdigo com o trecho:

ser entendido pelo compilador ver:

Estas definies com parmetros recebem o nome de macros. Devemos ter muito cuidado
na definio de macros. Mesmo um erro de sintaxe pode ser difcil de ser detectado, pois
ocompilador indicar um erro na linha em que se utiliza a macro e no na linha de definio
da macro (onde efetivamente encontra-se o erro).
Outros efeitos colaterais de macros mal definidas podem ser ainda piores. Por exemplo, no
cdigo abaixo:

o resultado impresso 17 e no 8, como poderia ser esperado. Por qu?

Estrutura de Dados

Prof. airton jos sachetim garcia

Neste outro exemplo que envolve a macro com parnteses:

o resultado 11 e no 14. A macro corretamente definida seria:

Portanto, conclumos que, na regra bsica para a definio de macros, devemos envolver cada
parmetro, e a macro como um todo, com parnteses.

1.17 Vetores.
A forma mais simples de estruturarmos um conjunto de dados por meio de vetores. Como
a maioria das linguagens de programao, C/C++ permite a definio de vetores. Definimos um
vetor em C/C++ da seguinte forma:

int v[10]
A declarao acima diz que v um vetor de inteiros dimensionado com 10 elementos, isto
, reservamos um espao de memria contnuo para armazenar 10 valores inteiros. Assim,
se cada int ocupa 4 bytes, a declarao acima reserva um espao de memria de 40 bytes,
como ilustra a figura abaixo.

Estrutura de Dados

Prof. airton jos sachetim garcia

O acesso a cada elemento do vetor feito atravs de uma indexao da varivel v.


Observamos que, em C, a indexao de um vetor varia de zero a n-1, onde n representa a
dimenso do vetor. Assim:

Para exemplificar o uso de vetores, vamos considerar um programa que l 10 nmeros


reais, fornecidos via teclado, e calcula a destes nmeros. A mdia dada por:

A implementao, uma delas, apresentada a seguir.

Ateno todo programa aqui apresentado ser escrito em C, para que o aluno
refaa o mesmo em C++. Pois as quetes em prova sro em C e/ou C++.
Devemos observar que passamos para a funo scanf o endereo de cada elemento do
vetor (&v[i]), pois desejamos que os valores capturados sejam armazenados nos
elementos do vetor. Se v[i] representa o (i+1)-simo elemento do vetor, &v[i] representa
o endereo de memria onde esse elemento est armazenado.

Estrutura de Dados

Prof. airton jos sachetim garcia

Os vetores tambm podem ser inicializados na declarao:

Neste caso, a linguagem dimensiona o vetor pelo nmero de elementos inicializados.

1.17.1 Passagem de vetores para funes.


Passar um vetor para uma funo consiste em passar o endereo da primeira posio do vetor.
Quando passado um valor de endereo, a funo chamada deve ter um parmetro do tipo
ponteiro para armazenar este valor.
Assim, se passarmos para uma funo um vetor de int, devemos ter um parmetro do tipo
int*, capaz de armazenar endereos de inteiros.
Quando utilizamos a expresso passar um vetor para uma funo deve ser interpretada
como passar o endereo inicial do vetor. Os elementos do vetor no so copiados para a
funo, o argumento copiado apenas o endereo do primeiro elemento.
Modificando o cdigo do exemplo acima, para usar funes separadas para o clculo da mdia.
(Usando os operadores de atribuio += para acumular as somas.).

Estrutura de Dados

Prof. airton jos sachetim garcia

Note que, ao ser passado para a funo o endereo do primeiro elemento do vetor (e no os
elementos propriamente ditos), podem alterar os valores dos elementos do vetor dentro da
funo. O exemplo abaixo ilustra:
A sada sera 2 4 6, pois os elementos do vetor sero incrementados dentro da funo.

1.17.2 Alocao dinmica.


At aqui, na declarao de um vetor, foi preciso dimension-lo. Isto nos obrigava, a saber,
de antemo, quanto espao seria necessrio.
necessrio saber o nmero mximo de elementos no vetor na sua declarao.
Este pr-dimensionamento do vetor torna-se um fator limitante.
C/C++ oferece meios de requisitarmos espaos de memria em tempo de execuo. Dizemos
que podemos alocar memria dinamicamente. Com este recurso, nosso programa para o
clculo da mdia e agora com varincia discutido acima pode, em tempo de execuo,
consultar o nmero de alunos da turma e ento fazer a alocao do vetor dinamicamente, sem
desperdcio de memria.

Estrutura de Dados

Prof. airton jos sachetim garcia

1.17.3 Uso da memria.


Informalmente, podemos dizer que existem trs maneiras de reservarmos espao de memria
para o armazenamento de informaes.
A primeira delas atravs do uso de variveis globais (e estticas). O espao reservado
para uma varivel global existe enquanto o programa estiver sendo executado.

A segunda maneira atravs do uso de variveis locais. Neste caso, como j


discutimos, o espao existe apenas enquanto a funo que declarou a varivel est
sendo executada, sendo liberado para outros usos quando a execuo da funo
termina. Por este motivo, a funo que chama no pode fazer referncia ao espao
local da funo chamada.

As variveis globais ou locais podem ser simples ou vetores. Para os vetores,


precisamos informar o nmero mximo de elementos, caso contrrio o compilador
no saberia o tamanho do espao a ser reservado.
A terceira maneira de reservarmos memria requisitando ao sistema, em tempo de
execuo, um espao de um determinado tamanho. Este espao alocado
dinamicamente permanece reservado at que explicitamente seja liberado pelo
programa. Por isso, podemos alocar dinamicamente um espao de memria numa
funo e acess-lo em outra.
A partir do momento que liberarmos o espao, ele estar disponibilizado para outros
usos e no podemos mais acess-lo. Se o programa no liberar um espao alocado,
este ser automaticamente liberado quando a execuo do programa terminar.
Apresentamos abaixo um esquema didtico que ilustra de maneira fictcia a distribuio do
uso da memria pelo sistema operacional.

Estrutura de Dados

Prof. airton jos sachetim garcia

Quando requisitamos ao sistema operacional para executar um determinado programa, o


cdigo em linguagem de mquina do programa deve ser carregado na memria. O sistema
operacional reserva tambm os espaos necessrios para armazenarmos as variveis globais (e
estticas) existentes no programa. O restante da memria livre utilizado pelas variveis
locais e pelas variveis alocadas dinamicamente. Cada vez que uma determinada funo
chamada, o sistema reserva o espao necessrio para as variveis locais da funo. Este espao
pertence pilha de execuo e, quando a funo termina, desempilhado. A parte da
memria no ocupada pela pilha de execuo pode ser requisitada dinamicamente. Se a pilha
tentar crescer mais do que o espao disponvel existente, dizemos que ela estourou e o
programa abortado com erro. Similarmente, se o espao de memria livre for menor que o
espao requisitado dinamicamente, a alocao no feita e o programa pode prever um
tratamento de erro adequado (por exemplo, podemos imprimir a mensagem Memria
insuficiente e interromper a execuo do programa).

1.17.4 Funes da biblioteca padro.


Na biblioteca padro stdlib, temos funes que nos permitem alocar e liberar memria
dinamicamente.

1.17.4.1

malloc.

a funo bsica para alocar memria, recebe como parmetro o nmero de bytes que se
deseja alocar e retorna o endereo inicial da rea de memria alocada.
Exemplificando, consideremos a alocao dinmica do vetor de inteiros com 10
elementos. Como a funo malloc retorna o endereo da rea alocada e, desejamos
armazenar valores inteiros nessa rea, temos que declarar um ponteiro de inteiro para receber
o endereo inicial do espao alocado. O trecho de cdigo ento seria:

int *v;
v = malloc(10*4);
Feito isso, v armazenar o endereo inicial de uma rea contnua de memria suficiente para
armazenar 10 valores inteiros. Deve-se tratar v como tratamos um vetor declarado
estaticamente, pois, se v aponta para o inicio de uma rea alocada, pode-se dizer que v[0]
acessa o endereo do primeiro elemento que armazenaremos, e
segundo, at

v[1] aponta para o

v[9].

Na exemplificao acima, trabalhamos com um inteiro, que ocupa 4 bytes. Devemos ficar
independentes de compiladores e mquinas, usando o operador sizeof(

).

v = malloc(10*sizeof(int));
Segue ilustrao de maneira esquemtica o que ocorre na memria:

Estrutura de Dados

Prof. airton jos sachetim garcia

Caso no houver espao livre suficiente para realizao da alocao, ser retornado um
endereo nulo (representado pelo smbolo NULL, definido em stdlib.h). Devemos prevenir
o erro na alocao do programa verificando o valor de retorno da funo malloc. Deve-se
imprimir uma mensagem e abortar o programa usando a funo exit, tambm definida na
stdlib.

v = (int*) malloc(10*sizeof(int));
if (v==NULL)
{
printf("Memoria insuficiente.\n");
exit(1); /* aborta o programa e retorna 1 para o sist. operacional */
}

Para liberao da memria alocada dinamicamente, usa-se a funo free. Esta funo recebe
como parmetro o ponteiro da memria a ser liberada. Assim, para liberar o vetor v, fazemos:
free (v);
Devemos passar para a funo free um endereo de memria que tenha sido alocado
dinamicamente. Deve-se lembrar de que no podemos acessar o espao na memria
depois que o liberamos.
Como exemplo do uso da alocao dinmica, usaremos o programa para o clculo da
mdia e da varincia. Agora, o programa l o nmero de valores que sero fornecidos, aloca
um vetor dinamicamente e faz os clculos. Somente a funo principal precisa ser alterada,
pois as funes para calcular a mdia e a varincia anteriormente apresentadas independem
do fato de o vetor ter sido alocado esttica ou dinamicamente.

Estrutura de Dados

Prof. airton jos sachetim garcia

1.18 Cadeia de caracteres.


1.18.1 Caracteres
A linguagem C/C++ permite a escrita de constantes caracteres. Uma constante caractere
escrita envolvendo o caractere com aspas simples. Assim, a expresso 'a' representa uma
constante caracter.

Estrutura de Dados

Prof. airton jos sachetim garcia

Exemplo: Suponhamos que queremos escrever uma funo para testar se uma
varivel caractere c um dgito (um dos caracteres entre '0' e '9'). Esta funo pode ter
o prottipo:
int digito(char c);
e ter como resultado 1 (verdadeiro) se c for um dgito, e 0 (falso) se no for.
A implementao desta funo pode ser dada por:

1.18.2 String.
Cadeias de caracteres (strings), em C/C++, so representadas por vetores do tipo char
terminadas, obrigatoriamente, pelo caractere nulo ('\0'). Portanto, para armazenarmos uma
cadeia de caracteres, devemos reservar uma posio adicional para o caractere de fim da
cadeia. Todas as funes que manipulam cadeias de caracteres (e a biblioteca padro de C/C++
oferece vrias delas) recebem como parmetro um vetor de char, isto , um ponteiro para o
primeiro elemento do vetor que representa a cadeia, e processam caractere por caractere, at
encontrarem o caractere nulo, que sinaliza o final da cadeia.
O prximo passo entender as strings. Strings em C/C++ so tratados como vetores de
tamanho determinado que podem armazenar qualquer caracter. Diferentemente de declarar
apenas uma varivel do tipo char (que armazena apenas um caracter) a string uma cadeia de
caracteres, ou seja, pode guardar quantos caracteres ns determinarmos.
Portanto, para declararmos uma string, basta ns criarmos um vetor de caracteres dessa
forma:
char minhaString [50];
O nico problema das strings so o seu consumo de recursos. Por exemplo, se levarmos em
conta o vetor de caracteres que acabamos de criar, apesar dele conter 50 posies, ns s
poderemos digitar at 49 letras. Isso ocorre porque toda string deve ter um caracter terminal,
que geralmente indicado pelo NULL (nulo). Isso quer dizer que um vetor de caracteres
(string) de 50 posies ter 49 caracteres efetivos e um NULL indicando seu final.

1.18.2.1

Entrada de String.

Para entrarmos com uma String no sistema usamos a mesma funo de entrada padro - cin.
Ou seja, se quisermos que o usurio digite seu nome faramos da seguinte forma:

Estrutura de Dados

Prof. airton jos sachetim garcia

Agora, outro problema ao tratarmos de strings em C/C++. Embora a funo cin consiga obter a
string, ela sempre termina assim que pressionarmos o espao a primeira vez, ou seja, ele s
consegue pegar uma palavra por vez.
Ento, como vamos obter uma linha inteira?
Bem, para obtermos uma linha inteira ns devemos fazer uso de um dos mtodos encontrados
dentro de cin - o mtodo getline.
O mtodo getline obtm uma linha de acordo com o tamanho definido no mtodo. Ento, o
mtodo getline utiliza dois parmetros: 1. O nome da string; 2. O tamanho mximo que ser
preenchido.
Ento, usando o mesmo exemplo, apenas mudaramos a 6 linha. Vejamos:

1.18.3 Funes de String.


Podemos fazer muitas coisas com Strings, como por exemplo, ver ser tamanho, juntar mais de
uma palavra, comparar duas palavras diferentes, etc. Para isso, basta incluirmos uma
biblioteca para tratamento de strings em C/C++ chamado - string.h.

1.18.3.1

Obter o tamanho de uma String.

Para obter o tamanho de uma string usamos a funo strlen (que a juno do
ingls String Length, que quer dizer, largura de string). Essa funo retorna o nmero de
caracteres utilizados (incluindo os espaos se houver). Ela recebe como argumento apenas a
string que deve ser verificada e retorna o nmero de caracteres encontrados.

Estrutura de Dados

Prof. airton jos sachetim garcia

1.18.3.2

Comparar duas strings.

H tambm uma forma de compararmos duas strings para ver ser ambas so iguais. A funo
que determina isso strcmp. Embora C/C++ case sensitive, ou seja, diferencia maisculas de
minsculas, isso no ir influenciar nessa funo. Essa funo retorna 0 se h igualdade entre
as strings ou um nmero diferente de zero se no houver igualdade. Portanto, se quisermos
fazer uma comparao de duas strings, procedemos da seguinte forma: strcmp (string1,
string2). Vejamos o exemplo:

1.18.3.3

Copiar uma String.

Para copiar uma string para outra string usamos strcpy (que vem de String copy). Essa funo
recebe dois argumentos: 1. a string para onde ser armazenada a cpia; 2. a string que ser
copiada. Resumidamente, ele copia a segunda string para a primeira. Exemplo:

Estrutura de Dados

Prof. airton jos sachetim garcia

1.18.3.4

Concatenar uma String.

Concatenar uma String que dizer juntar. De uma forma mais simplria, como se dissssemos
que a juno da palavra passa mais a palavra tempo igual a passatempo. Ou seja, essa funo
- strcat - pega duas strings e junta o que tiver na primeira com o que tiver na segunda.
Tome cuidado: Se concatenarmos duas strings e uma delas ou ambas forem vazias ocorrer
um erro.
No exemplo abaixo, faremos o seguinte: vamos obter o valor de duas strings e concaten-las
formando uma nova string.
Lidar com strings extremamente importante para a programao, pois a string a base de
qualquer arquivo e principalmente controles de rotina (por exemplo: rotinas e procedimentos
de banco de dados, o SQL; endereamento de arquivos; modificao de configuraes...).
Abaixo esta um exemplo com todas as funes bsicas de manipulao de string vistas at
aqui.

Estrutura de Dados

Prof. airton jos sachetim garcia

1.19 Estrutura de Dados STRUCT.


As estruturas de dados consistem em criar apenas um dado que contm vrios membros, que
nada mais so do que outras variveis. De uma forma mais simples, como se uma varivel
tivesse outras variveis dentro dela. A vantagem em se usar estruturas de dados que
podemos agrupar de forma organizada vrios tipos de dados diferentes, por exemplo, dentro
de uma estrutura de dados podemos ter juntos tanto um tipo float, um inteiro, um char ou
um double.
As variveis que ficam dentro da estrutura de dados so chamadas de membros.

1.19.1 Criando uma estrutura de dados com STRUCT.


Para criar uma estrutura de dados usamos a palavra reservada struct. Toda estrutura deve ser
criada antes de qualquer funo ou mesmo da funo principal main. Toda estrutura tem
nome e seus membros so declarados dentro de um bloco de dados. Aps a definio de seus
membros no bloco de dados, terminamos a linha com um ponto-e-vrgula (;). Portanto:
struct nome_da_estrutura { tipo_de_dado nome_do_membro; };
Por exemplo, se fossemos criar uma estrutura de dados para uma data faramos:

Estrutura de Dados

Prof. airton jos sachetim garcia

struct data {
int dia;
int mes;
int ano;
};

1.19.2 Declarando um struct e acessando seus membros.


Ainda utilizando o exemplo acima, vamos declarar uma varivel do tipo estrututa de dados
data e acessar seus membros.
Aps criarmos uma estrutura de dados com struct, poderemos utiliz-la como um tipo de dado
comum (ex.: float, int, char). E para acessar seus membros utilizamos a varivel declarada mais
um ponto (.) e o nome do membro. Veja este exemplo abaixo:

Portanto, a varivel hoje declarada como sendo um tipo de dado data. Data uma estrutura
de dados que tem trs caractersticas (ou trs membros) inteiras: dia, mes e ano. Como hoje
um tipo de dado data, ele obtm os mesmos trs membros. Para acessar cada membro,
usamos a varivel e depois o nome do membro que queremos acessar separados por ponto (.).

1.19.3 Ponteiro de Struct.


Vimos a pouco como criar uma estrutura de dados agrupado (struct), como definir um nome
essa estrutura com typedef e como criar um ponteiro para indicar um endereo de memria.
Agora, vamos nos aprofundar um pouco mais nesse assunto vendo como procedemos com um
ponteiro de struct.
Como vimos anteriormente, um struct consiste em vrios dados agrupados em apenas um.
Para acessarmos cada um desses dados, usamos um ponto (.) para indicar que o nome
seguinte o nome do membro.
Um ponteiro guarda o endereo de memria que pode ser acessado diretamente.

Estrutura de Dados

Prof. airton jos sachetim garcia

O problema aqui est no seguinte, como acessaremos um membro de uma estrutura de dados
usando um ponteiro? Pois simples. Para isso, basta usarmos o que chamamos de "seta". A
"seta" consiste de um sinal de menos e um maior (->).
Portanto, podemos criar nosso struct do mesmo jeito de sempre e nosso ponteiro tambm.
Mas, quando formos acessar um membro dessa estrutura usando um ponteiro ns no
usaremos um ponto, mas uma seta.
Vejamos:

Agora, h mais uma maneira de acessarmos um membro da estrutura usando um ponteiro.


Esta outra forma consiste em indicar de qual ponteiro nos referimos colocando o diferenciador
entre parnteses, assim (*hoje). Dessa forma podemos acessar diretamente usando um ponto
(.).
No exemplo abaixo usamos apenas ponteiros com diferenciador para escrever no struct data.

Estrutura de Dados

Prof. airton jos sachetim garcia

Concluindo, podemos acessar um membro de um tipo de dado estrutura de dado usando


ponteiro de duas formas:
1. Usando um diferenciador entre parnteses e um ponto (.) para indicar o membro.
2. Usando o prprio ponteiro e uma seta (->) para indicar o membro.

1.20 Vetores bidimensionais Matrizes.


A linguagem C permite a criao de vetores bidimensionais, declarados estaticamente. Por
exemplo, para declararmos uma matriz de valores reais com 4 linhas e 3 colunas, fazemos:

float mat[4][3];

Estrutura de Dados

Prof. airton jos sachetim garcia

Esta declarao reserva um espao de memria necessrio para armazenar os 12 elementos


da matriz, que so armazenados de maneira contnua, organizados linha a linha.
Os elementos da matriz so acessados com indexao dupla: mat[i][j]. O primeiro
ndice, i, acessa a linha e o segundo, j, acessa a coluna. Como em C/C++ a indexao comea
em zero, o elemento da primeira linha e primeira coluna acessado por mat[0][0]. Aps
a declarao esttica de uma matriz, a varivel que representa a matriz, mat no exemplo
acima, representa um ponteiro para o primeiro vetor-linha, composto por 3 elementos.
Com isto, mat[1] aponta para o primeiro elemento do segundo vetor-linha, e assim por
diante.
As matrizes tambm podem ser inicializadas na declarao:

Ou podemos inicializar seqencialmente:

O nmero de elementos da linha pode ser omitido numa inicializao, mas o nmero de
colunas deve, obrigatoriamente, ser fornecido:

1.20.1 Passagem de matrizes para funes.


A matriz criada estaticamente representada por um ponteiro para um vetor-linha com o
nmero de elementos da linha. Quando passamos uma matriz para uma funo, o parmetro
da funo deve ser deste tipo. O prottipo de uma funo que recebe a matriz declarada
acima seria:

Uma segunda opo declarar o parmetro como matriz, podendo omitir o nmero de linhas.

Em diversas aplicaes, as matrizes tm dimenses


fixas e no justificam a criao de estratgias para trabalhar com alocao dinmica. Em
aplicaes da rea de Computao Grfica, por exemplo, comum trabalharmos com
matrizes de 4 por 4 para representar transformaes geomtricas e projees. Nestes casos,
muito mais simples definirmos as matrizes estaticamente (float mat[4][4];), uma vez que
sabemos de antemo as dimenses a serem usadas. Nestes casos, vale a pena
definirmos um tipo prprio, pois nos livramos das construes sintticas confusas
explicitadas acima. Por exemplo, podemos definir o tipo Matrix4.

Com esta definio podemos declarar variveis e parmetros deste tipo:

Estrutura de Dados

Prof. airton jos sachetim garcia

1.21 Listas Encadeadas.


Para representarmos um grupo de dados, j vimos que podemos usar um vetor em C. O vetor
a forma mais primitiva de representar diversos elementos agrupados. Para simplificar a
discusso dos conceitos que sero apresentados agora, vamos supor que temos que
desenvolver uma aplicao que deve representar um grupo de valores inteiros. Para tanto,
podemos declarar um vetor escolhendo um nmero mximo de elementos.

Ao declararmos um vetor, reservamos um espao contguo de memria para armazenar


seus elementos, conforme ilustra a figura abaixo.

No entanto o vetor no uma estrutura de dados muito flexvel, pois precisamos dimensionlo com um nmero mximo de elementos. Se o nmero de elementos que precisarmos
armazenar exceder a dimenso do vetor, teremos um problema, pois no existe uma maneira
simples e barata (computacionalmente) para alterarmos a dimenso do vetor em tempo de
execuo. Por outro lado, se o nmero de elementos que precisarmos armazenar no vetor for
muito inferior sua dimenso, estar subutilizando o espao de memria reservado.
A soluo para esses problemas utilizar estruturas de dados que cresam medida que
precisarmos armazenar novos elementos (e diminuam medida que precisarmos retirar
elementos armazenados anteriormente). Tais estruturas so chamadas dinmicas e
armazenam cada um dos seus elementos usando alocao dinmica.
Ento, discutiremos a estrutura de dados conhecida como lista encadeada.
As listas encadeadas so amplamente usadas para implementar diversas outras estruturas de
dados com semnticas prprias, que sero tratadas nos captulos seguintes.
Numa lista encadeada, para cada novo elemento inserido na estrutura, alocamos um
espao de memria para armazen-lo. Desta forma, o espao total de memria gasto
pela estrutura proporcional ao nmero de elementos nela armazenado. No entanto, no
podemos garantir que os elementos armazenados na lista ocuparo um espao de
memria contguo, portanto no temos acesso direto aos elementos da lista. Para que
seja possvel percorrer todos os elementos da lista, devemos explicitamente guardar o
encadeamento dos elementos, o que feito armazenando-se, junto com a informao de
cada elemento, um ponteiro para o prximo elemento da lista. A Figura abaixo ilustra o
arranjo da memria de uma lista encadeada.

Estrutura de Dados

Prof. airton jos sachetim garcia

A estrutura consiste numa seqncia encadeada de elementos, em geral chamados de ns da


lista. A lista representada por um ponteiro para o primeiro elemento (ou n).
Do primeiro elemento, podemos alcanar o segundo seguindo o encadeamento, e assim por
diante. O ltimo elemento da lista aponta para NULL, sinalizando que no existe um prximo
elemento.
Para exemplificar a implementao de listas encadeadas em C/C++, vamos considerar um
exemplo simples em que queremos armazenar valores inteiros numa lista encadeada. O
n da lista pode ser representado pela estrutura abaixo:

Nota-se que se trata de uma estrutura de auto-referencia, pois, alm do campo que armazena
a informao (no caso, um nmero inteiro, info), h um campo que um ponteiro,(prox) para
uma prxima estrutura do mesmo tipo. Tambm uma boa estratgia definirmos o tipo Lista
como sinnimo de struct lista. O tipo Lista representa um n da lista e a estrutura da lista
encadeada representada pelo ponteiro para seu primeiro elemento (tipo Lista*).

1.21.1 Funo de inicializao.


A funo que inicializa uma lista deve criar uma lista vazia, sem nenhum elemento.
Como a lista representada pelo ponteiro para o primeiro elemento, uma lista vazia
representada pelo ponteiro NULL, pois no existem elementos na lista. A funo tem como
valor de retorno a lista vazia inicializada, isto , o valor de retorno NULL. Uma possvel
implementao da funo de inicializao mostrada a seguir:

1.21.2 Funo de insero.


Uma vez criada lista vazia, podemos inserir novos elementos nela. Para cada elemento
inserido na lista, devemos alocar dinamicamente a memria necessria para armazenar
o elemento e encade-lo na lista existente. A funo de insero mais simples insere o
novo elemento no incio da lista.

Estrutura de Dados

Prof. airton jos sachetim garcia

Uma das implementaes dessa funo mostrada a seguir. Devemos notar que o ponteiro que
representa a lista deve ter seu valor atualizado, pois a lista ser representada pelo ponteiro para o
novo primeiro elemento. Por esta razo, a funo de insero recebe como parmetros de
entrada a lista onde ser inserido o novo elemento e a informao do novo elemento, e tem
como valor de retorno a nova lista, representada pelo ponteiro para o novo elemento.

Esta funo aloca dinamicamente o espao para armazenar o novo n da lista, guarda a
informao no novo n e faz este n apontar para (isto , ter como prximo elemento) o
elemento que era o primeiro da lista. A funo ento retorna o novo valor que representa a
lista, que o ponteiro para o novo primeiro elemento. A Figura abaixo ilustra a operao de
insero de um novo elemento no incio da lista.

Um trecho de cdigo que cria uma lista inicialmente vazia e insere nela dois novos elementos.

Observe que no podemos deixar de atualizar a varivel que representa a lista a cada
insero de um novo elemento.

1.21.3 Funo que percorre os elementos da lista.


Para mostrarmos a implementao de uma funo que percorre todos os elementos da lista,
vamos considerar a criao de uma funo que imprima os valores dos elementos
armazenados numa lista.

Estrutura de Dados

Prof. airton jos sachetim garcia

1.21.4 Funo que verifica se lista est vazia.


til implementarmos uma funo que verifique se uma lista est vazia.
A funo recebe a lista e retorna 1 se estiver vazia ou 0 se no estiver vazia. Como
sabemos, uma lista est vazia se seu valor NULL.

Essa funo pode ser reescrita de forma mais compacta, conforme mostrado abaixo:

1.21.5 Funo de busca.


Outra funo til, verificar se um determinado elemento est presente na lista. A funo
recebe a informao referente ao elemento que queremos buscar e fornece como valor de
retorno o ponteiro do n da lista que representa o elemento. Caso o elemento no seja
encontrado na lista, o valor retornado NULL.

1.21.6 Funo que exclui um elemento da lista.


A funo para retirar um elemento da lista mais complexa. Se descobrirmos que o elemento
a ser retirado o primeiro da lista, devemos fazer com que o novo valor da lista passe a ser o
ponteiro para o segundo elemento, e ento podemos liberar o espao alocado para o
elemento que queremos retirar. Se o elemento a ser removido estiver no meio da lista,
devemos fazer com que o elemento anterior a ele passe a apontar para o
Estrutura de Dados

Prof. airton jos sachetim garcia

elemento seguinte, e ento podemos liberar o elemento que queremos retirar. Devemos
notar que, no segundo caso, precisamos do ponteiro para o elemento anterior para
podermos acertar o encadeamento da lista. As Figuras a seguir ilustram as operaes de
remoo.

Uma implementao da funo para retirar um elemento da lista mostrada a seguir.


Inicialmente, busca-se o elemento que se deseja retirar, guardando uma referncia para o
elemento anterior.
O caso de retirar o ltimo elemento da lista recai no caso de retirar um elemento no
meio da lista, conforme pode ser observado na implementao acima. Mais adiante,
estudaremos a implementao de filas com listas encadeadas. Numa fila, devemos
armazenar, alm do ponteiro para o primeiro elemento, um ponteiro para o ltimo
elemento. Nesse caso, se for removido o ltimo elemento, veremos que ser necessrio
atualizar a fila.

1.21.7 Funo para liberar a lista.


Uma outra funo til que devemos considerar destri a lista, liberando todos os elementos
alocados. Uma implementao dessa funo mostrada abaixo. A funo percorre elemento a
elemento, liberando-os. importante observar que devemos guardar a referncia para o
prximo elemento antes de liberar o elemento corrente (se liberssemos o elemento e depois
tentssemos acessar o encadeamento, estaramos acessando um espao de memria que no
estaria mais reservado para nosso uso).

1.21.8 Um programa completo.


Um programa que ilustra a utilizao dessas funes mostrado a seguir.

Estrutura de Dados

Prof. airton jos sachetim garcia

Mais uma vez, observe que no podemos deixar de atualizar a varivel que representa a
lista a cada insero e a cada remoo de um elemento. Esquecer-se de atribuir o valor de
retorno varivel que representa a lista pode gerar erros graves. Se, por exemplo, a
funo retirar o primeiro elemento da lista, e varivel que representa a lista, no fosse
atualizada, estaria apontando para um n j liberado. Como alternativa, poderamos
fazer com que as funes insere e retira recebessem o endereo da varivel que
representa a lista. Nesse caso, os parmetros das funes seriam do tipo ponteiro para
lista (Lista** l) e seu contedo poderia ser acessado/atualizado de dentro da funo
usando o operador contedo (*lst).

1.22 Pilha.
Uma das estruturas de dados mais simples a pilha. Possivelmente por essa razo, a
estrutura de dados mais utilizada em programao, sendo inclusive implementada
diretamente pelo hardware da maioria das mquinas modernas. A idia fundamental da pilha
que todo o acesso a seus elementos feito atravs do seu topo. Assim, quando um elemento
novo introduzido na pilha, passa a ser o elemento do topo, e o nico elemento que pode ser
removido da pilha o do topo. Isto faz com que os elementos da pilha sejam retirados na
ordem inversa ordem em que foram introduzidos: o primeiro que sai o ltimo que entrou
(a sigla LIFO last in, first out usada para descrever esta estratgia).
Existem duas operaes bsicas que devem ser implementadas numa estrutura de pilha: a
operao para empilhar um novo elemento, inserindo-o no topo, e a operao para
desempilhar um elemento, removendo-o do topo. comum nos referirmos a essas duas
operaes pelos termos em ingls push (empilhar) e pop (desempilhar).

Estrutura de Dados

Prof. airton jos sachetim garcia

O exemplo de utilizao de pilha mais prximo a prpria pilha de execuo da linguagem


C/C++. As variveis locais das funes so dispostas numa pilha e uma funo s tem acesso s
variveis que esto no topo (no possvel acessar as variveis da funo locais s outras
funes).
Consideraremos duas implementaes de pilha: usando vetor e usando lista encadeada. Para
simplificar a exemplo, consideraremos uma pilha que armazena valores reais. Independente da
estratgia de implementao, podemos definir a interface do tipo abstrato que representa uma
estrutura de pilha. A interface composta pelas operaes que estaro disponibilizadas para
manipular e acessar as informaes da pilha. Neste exemplo, vamos considerar a implementao
de cinco operaes:
1.
2.
3.
4.
5.

criar uma estrutura de pilha;


inserir um elemento no topo (push);
remover o elemento do topo (pop);
verificar se a pilha est vazia;
liberar a estrutura de pilha.

A funo cria aloca dinamicamente a estrutura da pilha, inicializa seus campos e


retorna seu ponteiro;
as funes push e pop inserem e retiram, respectivamente, um valor real na pilha;
a funo vazia informa se a pilha est ou no vazia; e
a funo libera destri a pilha, liberando toda a memria usada pela estrutura.

1.22.1 Implementao de pilha com vetor.


Em aplicaes computacionais que precisam de uma estrutura de pilha, comum sabermos de
antemo o nmero mximo de elementos que podem estar armazenados simultaneamente na
pilha, isto , a estrutura da pilha tem um limite conhecido. Nestes casos, a implementao da
pilha pode ser feita usando um vetor. A implementao com vetor bastante simples.
Devemos ter um vetor (vet) para armazenar os elementos da pilha. Os elementos inseridos
ocupam as primeiras posies do vetor. Desta forma, se temos n elementos armazenados na
pilha, o elemento vet[n-1] representa o elemento do topo.
A estrutura que representa o tipo pilha deve, portanto, ser composta pelo vetor e pelo
nmero de elementos armazenados.

Estrutura de Dados

Prof. airton jos sachetim garcia

A funo para criar a pilha aloca dinamicamente essa estrutura e inicializa a pilha como
sendo vazia, isto , com o nmero de elementos igual a zero.

Para inserir um elemento na pilha, usamos a prxima posio livre do vetor. Devemos
ainda assegurar que exista espao para a insero do novo elemento, tendo em vista
que
trata-se de um vetor com dimenso fixa.

A funo pop retira o elemento do topo da pilha, fornecendo seu valor como retorno.
Podemos tambm verificar se a pilha est ou no vazia.

A funo que verifica se a pilha est vazia pode ser dada por:

Estrutura de Dados

Prof. airton jos sachetim garcia

Finalmente, a funo para liberar a memria alocada pela pilha pode ser:

1.22.2 Implementao de pilha com Lista.


Quando o nmero mximo de elementos que sero armazenados na pilha no conhecido,
devemos implementar a pilha usando uma estrutura de dados dinmica, no caso, empregando
uma lista encadeada. Os elementos so armazenados na lista e a pilha pode ser representada
simplesmente por um ponteiro para o primeiro n da lista.
O n da lista para armazenar valores reais pode ser dado por:

A estrutura da pilha ento simplesmente:

A funo cria aloca a estrutura da pilha e inicializa a lista como sendo vazia.

O primeiro elemento da lista representa o topo da pilha. Cada novo elemento inserido no
incio da lista e, conseqentemente, sempre que solicitado, retiramos o elemento tambm do
incio da lista. Desta forma, precisamos de duas funes auxiliares da lista:
para inserir no incio e
para remover do incio.
Ambas as funes retornam o novo primeiro n da lista.

Estrutura de Dados

Prof. airton jos sachetim garcia

As funes que manipulam a pilha, (Inserir e excluir) fazem uso dessas funes de lista:

A pilha estar vazia se a lista estiver vazia:

Por fim, a funo que libera a pilha deve antes liberar todos os elementos da lista.

Estrutura de Dados

Prof. airton jos sachetim garcia

A rigor, pela definio da estrutura de pilha, s temos acesso ao elemento do topo. No


entanto, para testar o cdigo, pode ser til implementarmos uma funo que imprima os
valores armazenados na pilha. Os cdigos abaixo ilustram a implementao dessa funo nas
duas verses de pilha (vetor e lista). A ordem de impresso adotada do topo para a base.

1.23 Filas.

Estrutura de Dados

Prof. airton jos sachetim garcia

Referncias Bibliogrficas.
1. http://www.gsmfans.com.br/index.php?topic=67407.0;
2. http://pt.wikipedia.org/wiki/C%2B%2B;
3. Lista de exerccio Prof. Alexandre Ribeiro FEIS;
4. Lista de exerccio Prof. Anirio Salles Filho FEIS;
5. Lista de exerccio Profa. Erica Regina Marani Daruichi Machado FEIS;
6. Apostila: Introduo Cincia da Computao e Teoria e Desenvolvimento de
Algoritmos, Profa. Erica M. Daruichi Machado FEIS;
7. Curso Bsico de Lgica de Programao, Unicamp - Centro de Computao DSC,
Autor: Paulo Srgio de Moraes;
8. http://www.dca.fee.unicamp.br/cursos/EA876/apostila/HTML/node37.html;
9. http://www.linhadecodigo.com.br/Artigo.aspx?id=1114;
10. http://www.vivaolinux.com.br/artigo/Substituindo-a-biblioteca-conio.h-no-Linuxusando-ncursescurses.h/;
11. http://allanlima.wordpress.com/;
12. http://pt.wikipedia.org/wiki/C_(linguagem_de_programao);
13. http://www.apostilando.com/download.php?cod=3149&categoria=C%20e%20C++;
14. http://pt.wikibooks.org/wiki/Programar_em_C%2B%2B;
15. http://www.tiexpert.net/programacao;
16. http://pt.wikibooks.org/wiki/Programar_em_C/Vetores;
17. http://pt.wikipedia.org/wiki/C%2B%2B;
18.

Estrutura de Dados

Prof. airton jos sachetim garcia

S-ar putea să vă placă și