Sie sind auf Seite 1von 45

Ementrio

Noes de hardware e software.


Conceitos Fundamentais.
Vetores, cadeia de caracteres e registros.
Definio e manipulao de arquivos externos.
Subprogramao.
Alocao dinmica de memria.
Estruturas de dados bsicas: listas lineares, pilha e
fila. rvores e grafos.
Mtodos de ordenao.
Aplicaes prticas utilizando uma linguagem
estruturada de alto nvel
(Linguagem C).
Noes de Programao Orientada a Objetos com
a Linguagem C++.

Memria Disponvel no Computador


PROGRAMA

REA LIVRE

Memria livre, gerenciada


pelo sistema operacional
Cdigo executvel:
- instrues (compilador)
- armazenamento do dados (estrutura dos dados)

Alocao de Memria (1/2)


Esttica
Quantidade total de memria utilizada pelos
dados previamente conhecida e definida de
modo imutvel, no prprio cdigo-fonte do
programa.
Durante toda a execuo, a quantidade de
memria utilizada pelo programa no varia.
Lista de variveis declaradas.

Alocao de Memria (2/2)


Dinmica
Quanto o programa capaz de criar novas
variveis enquanto est sendo executado.
Alocao de memria para componentes
individuais no instante em que eles comeam a
existir durante a execuo do programa.
malloc: alocar memria.
free: liberar reas da memria ocupadas.

Alocao Esttica
x
Alocao Dinmica

Alocao Esttica (1/3)


implementao simples: vetores (array)
vantagem:
acesso indexado (vi)- todos os elementos da
estrutura so igualmente acessveis

desvantagens:
tamanho fixo (const maxTam = 1000;)
tempo de compilao
alocados em memria de forma esttica

Alocao Esttica (2/3)


const maxTam = 1000;
struct rgCliente {
char nome[40];
char sexo;
int idade;
};
struct rgCliente Cliente[maxTam];
Neste exemplo so reservadas, durante toda a execuo do
programa, 1.000 posies para o vetor Cliente.
Ser que um sistema de cadastro de clientes, que usa um vetor
com 1.000 posies o suficiente ?
Ser que nunca ir acontecer a necessidade de se cadastrar o
cliente de nmero 1.001 ?
E o que acontece quando os clientes cadastrados nunca passarem
de 100 ? As 900 posies de memria restantes, no podero ser
utilizadas por outras variveis, pois j esto reservadas.

Alocao Esttica (3/3)


Ao se determinar o mximo de elementos
que o vetor ir conter, pode-se ocorrer um
dos seguintes casos:
subdimensionamento: haver mais elementos a
serem armazenados do que o vetor capaz de
conter;
superdimensionamento: na maior parte do
tempo, somente uma pequena poro do vetor
ser realmente utilizada.

Alocao Dinmica
implementao eficiente: ponteiros ou
apontadores
vantagens:
tamanho varivel
tempo de execuo
alocados em memria de forma dinmica

desvantagem, ou restrio:
capacidade da memria, acesso sequencial

Varivel = endereo de memria


rea de memria onde dados so armazenados:
varivel esttica (lista de variveis)
existncia prevista no cdigo do programa
(tempo de compilao)
quantidade de memria utilizada pelo programa
no varia

varivel dinmica (malloc, free)


passam a existir durante a execuo do programa

Variveis Dinmicas (ponteiros)


ponteiros, ou apontadores, ou indicadores,
ou referncias
variveis especiais que armazenam
endereos de memria, isto , endereos de
outras variveis na memria
armazenam um endereo e no um valor
em C, o ponteiro mais um tipo permitido
como qualquer outro

Variveis Ponteiros
Para declarar um ponteiro de um certo tipo, usa-se a seguinte sintaxe:

TipoBase *nome;
Onde:
TipoBase o tipo da informao que ser apontada pelo ponteiro
(informa o total de bytes ocupados pela informao)
o smbolo * serve para indicar que se trata da definio de um ponteiro
nome corresponde ao nome da varivel ponteiro

Definio de Variveis do Tipo Ponteiro:


1. Ponteiros p/tipos pr-definidos (bsicos):
int *ptInt;
float *ptFloat;
char *ptChar; // definio de string
2. Ponteiros p/tipos definidos pelo programador:
struct rgFunc {
char nome[40];
char sexo;
float salario;
};
struct rgFunc *ptFunc;

Os Operadores de Ponteiros: * e & (1/2)


O operador & devolve o endereo na memria do
seu operando. Por exemplo:
int x = 10;
int *p = &x;
coloca em p o endereo da memria que contm a
varivel x. Esse endereo a posio interna
ao computador da varivel. O endereo no tem
relao alguma com o valor de x. O operador
& pode ser imaginado como retornando o endereo
de, ou seja, p recebe o endereo de x.

Os Operadores de Ponteiros: * e & (2/2)


O operador * o complemento de &, ele devolve o
valor da varivel localizada no endereo que o segue.
Por exemplo, se p contm o endereo da varivel x,
int x = 10;
int *p = &x;
int y = *p;
printf("%x %d\n", &x, x);
printf("%x %x %d\n", &p, p, *p);
printf("%x %d", &y, y);

coloca o valor de x em y. O operador * pode ser


imaginado como no endereo, ou seja, y recebe
o valor que est no endereo armazenado em p.

Usando os operadores de ponteiros (* e &)


void main() {
int x, *p;
x = 10;
p = &x;
printf("%d", *p);
}

o operador & usado para obter o


endereo de uma varivel esttica
o operador * usado para obter o
valor de um endereo de memria

Obs. quando um ponteiro contm o endereo de uma


varivel, diz-se que o ponteiro est "apontando" para
essa varivel. Se uma varivel ponteiro p armazena
um endereo de memria qualquer, ento *p
apresenta o valor armazenado naquele endereo.
Neste caso, *p corresponde ao nmero inteiro 10.

Representao Interna de Variveis do Tipo


Ponteiro:
As variveis dinmicas no so explicitamente
declaradas como as estticas, diretamente por
apelidos ou identificadores.
So referenciadas por seus endereos de memria,
armazenados em variveis (estticas) especiais
chamadas de ponteiros ou apontadores.

Trabalhando com a memria apontada pelo


ponteiro:
Para trabalhar a memria que o ponteiro p est apontando, utiliza-se o
operador *, com a sintaxe: *p.
Naturamente p dever ter um endereo vlido, isto , p deve estar
apontando para uma varivel ou para uma memria de tipo
compatvel. Para tanto, dois outros tipos de atribuies podem ser
feitos com variveis do tipo ponteiro:
a) um ponteiro pode receber o contedo de outro ponteiro compatvel
(apontar para um endereo que contm um valor do mesmo tipo);
b) um ponteiro pode receber um endereo especial, chamado NULL
(nulo), que serve para dizer que um endereo nulo e que no haver
nenhuma varivel neste endereo de memria.

Alocao Dinmica de Memria em C:


A rea de memria que no utilizada por um programa organizada e
gerenciada pelo sistema operacional, podendo ser alocada atravs de
comandos padronizados oferecidos pela prpria linguagem C.
Para alocar uma poro da rea livre, basta utilizar o comando malloc,
sendo p uma varivel ponteiro: p = (int *) malloc(sizeof(int)); aloca
uma rea de memria suficiente para armazenar um nmero inteiro e
guarda o endereo ocupado em p, j o comando: free(p); serve para
liberar a rea de memria cujo endereo est em p. Uma rea de
memria, que foi alocada pelo comando malloc, somente volta a ficar
disponvel se for explicitamente liberada pelo comando free, caso
contrrio, a liberao da rea s ocorrer quando o programa que fez a
alocao terminar de executar.
Para completar, p = NULL; marca p como um endereo nulo. Este
endereo til para dizer que o ponteiro ainda no tem nenhum

Representao Interna da Varivel do Tipo


Ponteiro:
aloca a varivel estaticamente
void main() {
int *p; I

aloca a varivel dinamicamente

p = (int *) malloc(sizeof(int)); II
III

*p = 10;
...
IV
free(p);
}

memria usada
pelo programa

endereo
1FFA
Lixo
10

1FFA
p: Lixo

memria livre
no sistema

Entendendo o cdigo:
int *p;
a varivel p um ponteiro para um nmero inteiro, ou seja, aponta
para um endereo de memria que ser alocado para armazenar um
nmero inteiro (2 bytes)
p = (int *) malloc(sizeof(int));
solicita ao sistema operacional 2 bytes da memria livre e o endereo
do espao alocado colocado na varivel ponteiro p
*p = 10;
no endereo apontado por p armazena o nmero inteiro 10
free(p);
libera o espao de memria ocupado cujo endereo est em p
(devolve o recurso ao sistema operacional)

Operadores ponto (.) e seta (->):


Os operadores ponto e seta so usados para especificar elementos individuais de
estruturas (struct) e unies. O operador ponto usado para especificar diretamente o
elemento e o operador seta para especificar o elemento atravs de um ponteiro.
#include <stdio.h>
#include <string.h>
struct rgPessoa {
char nome[35];
char apelido[20];
};
int main() {
struct rgPessoa pessoa;
struct rgPessoa *pontPessoa = &pessoa;
strcpy(pessoa.nome, "Omero Francisco Bertol");
strcpy(pessoa.apelido, "Chico");
printf("Resultado:\n");
printf("Nome...: %s\n", pontPessoa->nome);
printf("Apelido: %s\n", pontPessoa->apelido);
}

Listas Encadeadas com Vetor (1/2)


A forma mais simples de armazenar uma lista dentro do computador
consiste em colocar os seus elementos em clulas de memria
consecutivas (ou contguas), um aps o outro- utilizando o tipo
estruturado homogneo vetor.
A maior vantagem no uso de uma rea seqencial de memria para
armazenar uma lista linear que, todos os elementos da estrutura so
igualmente acessveis, isto , o tempo e o tipo de procedimentos para
acessar qualquer um dos elementos do vetor so iguais.
O ponto fraco desta forma de armazenamento aparece quando
necessrio inserir ou retirar elementos do meio da lista, quando ento
um certo esforo ser necessrio para movimentar os elementos, de
modo a abrir espao para insero, ou de modo a ocupar o espao
liberado por um elemento que foi removido.

Lista Encadeada com Vetor (2/2)


struct TipoItem {
char nome[30];
};

* * * ALOCAO ESTTICA * * *

// cada item da lista corresponde a um registro


// (TipoItem) composto apenas do campo nome

void estatica(void) {
fflush(stdin);
const maxTam = 100;
// maxTam = tamanho mximo da lista
int n = 0, i;
// n = quantidade efetiva de itens na lista
TipoItem lista[maxTam], x;
while (1) {
clrscr();
printf("Lista de nomes (Alocao Esttica)\n");
for (i=0; i<n; i++)
printf("%d- %s\n", i, lista[i].nome);
printf("\nInforme um nome, (FIM) para encerrar:\n");
gets(x.nome);
if (strcmp(x.nome, "FIM") == 0)
break;
if (n == maxTam) {
printf("\nErro: lista cheia !");
printf("Pressione [algo] para prosseguir.\n"); getch();
}
else {
lista[n] = x;
// coloca o item "x" na n-sima posio da lista
n = n + 1;
// o prximo item ser colocado na posio n + 1
}
}
}

Listas Encadeadas com Ponteiros (1/4)


Os tipos ponteiros ou apontadores so teis para criar estruturas de
dados encadeadas, do tipo listas (pilha e fila), rvores e grafos. Um
apontador uma varivel que referencia uma outra varivel alocada
dinamicamente. Em geral a varivel referenciada definida como um
registro que inclui tambm um apontador para outro elemento do
mesmo tipo. Por Exemplo:
struct Celula {
TipoItem Item;
Celula *prox;
};
Celula *primeiro, *ultimo, *p;
Sendo a varivel primeiro um endereo para um registro Celula que
contm o Item armazenado e o endereo (prox) da prxima clula da
lista- possvel criar uma lista encadeada atravs de ponteiros.

Listas Encadeadas com Ponteiros (2/4)


Celula

primeiro

ultimo

Item prox
Joo

Clula
Cabea

Maria

...

Ana

NULL

Ponteiro ou Apontador

Na alocao encadeada, os elementos so armazenados em blocos de


memria denominados clulas, ou nodos, sendo que cada clula
composta por dois campos: um para armazenar os dados (Item) e outro
para armazenar o endereo do prximo elemento da lista (prox)- para
manter a relao de ordem linear. So endereos especiais da lista
encadeada com ponteiros: a) primeiro: endereo do primeiro elemento
da lista (clula cabea), e, b) ultimo: endereo do ltimo elemento da
lista (o endereo do elemento nulo (NULL) segue o ltimo elemento
da lista.

Listas Encadeadas (3/4)


Vantagem de Listas Encadeadas com ponteiros ou apontadores:
- Facilidade de inserir ou remover elementos do meio da lista.
Como os elementos no precisam estar armazenados em posies
consecutivas de memria, nenhum dado precisa ser movimentado,
bastando atualizar o campo de ligao (prox) do elemento que
precede aquele inserido ou removido.
Desvantagem de Listas Encadeadas com ponteiros ou apontadores:
- Acessar uma posio especfica dentro da lista.
Como apenas o primeiro elemento acessvel diretamente atravs do
endereo primeiro, deve-se partir do primeiro e ir seguindo os campos
de ligao (prox), um a um, at atingir a posio desejada. Obviamente,
para listas extensas, esta operao pode ter um alto custo em relao a
tempo.

Lista Encadeada com Ponteiro (4/4)


* * * ALOCAO DINMICA * * *
void dinamica(void) {
fflush(stdin);
struct Celula {
TipoItem Item;
Celula *prox;
};
TipoItem x;
Celula *primeiro, *ultimo, *p;
// cria a clula cabea
primeiro = (Celula *) malloc(sizeof(Celula));
primeiro->prox = NULL;
ultimo = primeiro;
while (1) {
clrscr(); printf("Lista de nomes (Alocao Dinmica)\n");
p = primeiro->prox;
while (p != NULL) {
printf("%s\n", p->Item.nome);
p = p->prox;
}
printf("\nInforme um nome, (FIM) para encerrar:\n"); gets(x.nome);
if (strcmp(x.nome, "FIM") == 0)
break;
// coloca o novo item no final da lista
ultimo->prox = (Celula *) malloc(sizeof(Celula));
ultimo = ultimo->prox;
ultimo->Item = x;
ultimo->prox = NULL;
}
p = primeiro;
// elimina (libera) todos os espaos de memria alocados
while (p != NULL) {
primeiro = primeiro->prox;
free(p);
p = primeiro;
}
}

Criando a Clula Cabea da Lista


Clula especial, que no armazena itens, mas que usada para
indicar o primeiro elemento da lista. Obs. quando a lista est vazia a
nica clula existente a clula cabea, portanto, antes de qualquer
operao com a lista deve-se criar a clula cabea.
Celula *primeiro, *ultimo;
...
1. primeiro = (Celula *) malloc(sizeof(Celula));
2. primeiro->prox = NULL;
3. ultimo = primeiro;

Celula
Item prox

2
NULL

1
primeiro

3
ultimo

Entendendo o Cdigo (1/2):


primeiro = (Celula *) malloc(sizeof(Celula));
chama a funo malloc para
alocar a memria dinamicamente,
sero alocados sizeof(Celula) bytes
indica o valor retornado pela funo malloc, ou seja, o
endereo do espao alocado pelo sistema operacional
para armazenar uma clula da lista

primeiro->prox = NULL;

o operador -> (seta) usando para referenciar elementos individuais


(ou campos) de estruturas (ou registros) apontadas por varivies
ponteiros

Entendendo o Cdigo (2/2):


Celula *primeiro, *ultimo;

as variveis primeiro e ultimo so ponteiros para um registro Celula,


ou seja, apontam para endereos de memria que sero usados para
armazenar os itens (ou clulas) da lista
primeiro = (Celula *) malloc(sizeof(Celula));

solicita ao sistema operacional sizeof(Celula) bytes da memria


livre e o endereo do espao alocado colocado na varivel
ponteiro primeiro
primeiro->prox = NULL;

no campo prox da clula apontada pelo ponteiro primeiro armazena


o endereo NULL, ou seja, o endereo de ningum
ultimo = primeiro;

o ponteiro ultimo aponta para o mesmo endereo armazenado no


ponteiro primeiro

Colocando o Novo Item no Final da Lista


1.
2.
3.
4.

ultimo->prox = (Celula *) malloc(sizeof(Celula));


ultimo = ultimo->prox;
ultimo->Item = x;
ultimo->prox = NULL;

primeiro

Celula

ultimo
prox

Item prox
Omero

Maria

NULL
2

Juca

1
x
Ana

4
3

Ana

Item prox

NULL

Percorrendo uma Lista Encadeada


O algoritmo para percorrer uma lista do primeiro elemento at o ltimo,
se resume, na utilizao de um apontador auxiliar p que deve
inicialmente receber o endereo da primeira clula da Lista
(p = primeiro->prox;). A seguir, um processo repetitivo que faz p
pular, atravs do campo de ligao (prox), do nodo atual para o nodo
sucessor (p = p->prox;) at que p passe pelo ltimo nodo da lista
(NULL, o ltimo nodo da lista aponta para o vazio).
Resumindo em termos de programa, o processo para percorrer uma lista
encadeada pode ser descrito como segue:
Celula *p;
...
// endereo da primeira clula da lista
p = primeiro->prox;
while (p != NULL) {
printf("%s\n", p->Item.nome);
// endereo do nodo sucessor (prximo)
p = p->prox;
}

Liberando os Espaos Alocados na Criao


da Lista Encadeada
O algoritmo para liberar os endereos de memria alocados na criao
da lista deve percorrer, a partir da clula cabea, todas as clulas da
lista liberando o espao de memria ocupado pela clula atravs da
funo free. Por exemplo:
Celula *primeiro, *p;
...
// endereo da clula cabea
p = primeiro;
while (p != NULL) {
// endereo do nodo sucessor (prximo)
primeiro = primeiro->prox;
// libera a rea de memria cujo endereo est em p
free(p);
// prxima clula a ser liberada
p = primeiro;
}

Inserindo uma Nova Clula na Lista (1/4)


Dada uma cadeia de clulas (ou nodos), necessrio expandir
esta cadeia com novos blocos. Para entender como isto pode
ser feito, basta considerar a situao esquematizada, na
Figura abaixo, onde um nodo de endereo novo deve ser
inserido em uma Lista, aps a posio indicada pelo
ponteiro p:
primeiro

Celula

ultimo

Carlos

Luana

Item prox
Ana

novo

Daniel

NULL

Inserindo uma Nova Clula na Lista (2/4)


Como o novo nodo ser inserido logo aps aquele que
armazena o elemento "Carlos", seu sucessor ser aquele
nodo que armazena o elemento "Luana". Para isto, basta
atualizar o campo de ligao (prox) do novo nodo com o
endereo daquele que guarda o elemento "Luana".
primeiro

Celula

ultimo

Carlos

Luana

Item prox
Ana

novo

Daniel

novo->prox = p->prox;

NULL

Inserindo uma Nova Clula na Lista (3/4)


Na prxima etapa, faz-se o sucessor do nodo apontado por p
("Carlos") ser aquele apontado por novo ("Daniel").

primeiro

Celula

ultimo

Carlos

Luana

Item prox
Ana

p->prox = novo;
novo

Daniel

NULL

Inserindo uma Nova Clula na Lista (4/4)


Resumindo em termos de programa, o processo de insero pode ser
descrito como segue:
1. novo->prox = p->prox;
2. p->prox = novo;

primeiro

Celula

ultimo

Carlos

Luana

Item prox
Ana

NULL

2
novo

Daniel

Removendo uma Clula da Lista (1/5)


Considerando agora a situao esquematizada, na Figura
abaixo, onde o nodo ("Daniel") sucessor do nodo indicado
pelo ponteiro p ("Carlos") deve ser removido, ou excludo.
Situao antes da remoo.
Celula

ultimo

Item prox
Ana

primeiro

Carlos

Daniel

Luana

NULL

Removendo uma Clula da Lista (2/5)


Antes de isolar o nodo "Daniel" a ser removido, o que
tornaria o nodo inacessvel, deve-se copiar o seu endereo
para um ponteiro auxiliar q. Deste modo ser possvel
acessar o nodo q para posteriormente devolv-lo ao sistema
gerenciador de memria, atravs da funo free.
Celula

ultimo

Item prox
Ana

Carlos

Daniel

primeiro

Luana

q = p->prox;
q

NULL

Removendo uma Clula da Lista (3/5)


Como o nodo que armazena o elemento "Daniel" deve ser
removido, o seu sucessor (Luana") passa a ser o sucessor do
nodo que o precede ("Carlos"); em outras palavras, o nodo
que armazena o elemento "Luana" passa a ser o sucessor
do nodo apontado por p.
Celula

p->prox = q->prox;

Item prox
Ana

Carlos

Daniel

Luana

ultimo

primeiro

NULL

Removendo uma Clula da Lista (4/5)


Finalmente, o nodo apontado por q pode ser liberado e a
remoo concluda.

free(q);
Celula

Item prox
Ana

Carlos

Daniel

Luana

ultimo

primeiro

NULL

Removendo uma Clula da Lista (5/5)


Resumindo em termos de programa, o processo de remoo
pode ser descrito como segue:
1. q = p->prox;
2. p->prox = q->prox;
3. free(q);
Celula

Item prox
Ana

primeiro

Carlos

Daniel

Luana

1
q

ultimo

NULL

Referncias (Ponteiros em Pascal)


Estrutura de Dados Fundamentais: conceitos e
aplicaes.
Silvio do Lago Pereira.
2 ed. - So Paulo: rica, 1996.

Instituto de Computao da UNICAMP


Flvio K. Miyazawa & Tomasz Kowaltowski
http://olimpiada.ic.unicamp.br/apostila.html

Das könnte Ihnen auch gefallen