You are on page 1of 72

Livro Projeto de Algoritmos Nvio Ziviani

Captulo 3 Seo 3.1


http://www2.dcc.ufmg.br/livros/algoritmos/

Listas Lineares

Algoritmos e Estrutura de Dados II

Itens podem ser acessados, inseridos ou retirados de


uma lista.

Podem crescer ou diminuir de tamanho durante a


execuo de um programa, de acordo com a
demanda.

Estrutura em que as opera inserir, retirar e localizar


so definidas.

Uma das formas mais simples de interligar os


elementos de um conjunto.

Listas Lineares

Algoritmos e Estrutura de Dados II

So teis em aplicaes tais como manipulao


simblica, gerncia de memria, simulaes e
compiladores.

Adequadas quando no possvel prever a demanda


por memria, permitindo a manipulao de
quantidades imprevisveis de dados, de formato
tambm imprevisvel.

Duas listas podem ser concatenadas para formar uma


lista nica, ou uma pode ser partida em duas ou mais
listas.

Listas Lineares

x1 ,x2 ,,xn , na qual xi de um determinado tipo e n representa o


tamanho da lista linear.

Algoritmos e Estrutura de Dados II

Sua principal propriedade estrutural envolve as posies


relativas dos itens em uma dimenso.
 Assumindo n 1, x1 o primeiro item da lista e x o ltimo item
n
da lista.
 xi precede xi+1 para i = 1,2,,n 1
 xi sucede xi-1 para i = 2,3,,n
 o elemento xi dito estar na i-sima posio da lista.

Seqncia de zero ou mais itens

Definio de Listas Lineares

O conjunto de operaes a ser definido depende de cada aplicao.


Um conjunto de operaes necessrio a uma maioria de aplicaes
:
1) Criar uma lista linear vazia.
2) Inserir um novo item imediatamente aps o i-simo item.
3) Retirar o i-simo item.
4) Localizar o i-simo item para examinar e/ou alterar o contedo de seus
componentes.
5) Combinar duas ou mais listas lineares em uma lista nica.
6) Partir uma lista linear em duas ou mais listas.
7) Fazer uma cpia da lista linear.
8) Ordenar os itens da lista em ordem ascendente ou descendente, de
acordo com alguns de seus componentes.
9) Pesquisar a ocorrncia de um item com um valor particular em algum
componente.
Algoritmos e Estrutura de Dados II

TAD Listas Lineares

Algoritmos e Estrutura de Dados II

As duas representaes mais utilizadas so as


implementaes por meio de arranjos e de apontadores.

Vrias estruturas de dados podem ser usadas para


representar listas lineares, cada uma com vantagens e
desvantagens particulares.

Implementaes de Listas Lineares

Insere(x, Lista). Insere x aps o ltimo item da lista.

Retira(p, Lista, x). Retorna o item x que est na posio p da lista,


retirando-o da lista e deslocando os itens a partir da posio p+1 para
as posies anteriores.

Vazia(Lista). Esta funo retorna true se lista vazia; seno retorna


false.

Imprime(Lista). Imprime os itens da lista na ordem de ocorrncia.

2)

3)

4)

5)

Algoritmos e Estrutura de Dados II

FLVazia(Lista). Faz a lista ficar vazia.

1)

Exemplo de Conjunto de Operaes:

Implementaes de Listas Lineares

Retirar um item do incio da lista requer


um deslocamento de itens para preencher
o espao deixado vazio.
Algoritmos e Estrutura de Dados II

A insero de um novo item no meio da


lista requer um deslocamento de todos os
itens localizados aps o ponto de
insero.

A insero de um novo item pode ser


realizada aps o ltimo item com custo
constante.

A lista pode ser percorrida em qualquer


direo.

Os itens da lista so armazenados em


posies contguas de memria.

Implementao de Listas
por meio de arranjos

Algoritmos e Estrutura de Dados II

A constante MaxTam define o tamanho mximo permitido


para a lista.

O i-simo item da lista est armazenado na i-sima


posio do array, 1 i < ltimo.

O campo ltimo aponta para a posio seguinte a do


ltimo elemento da lista.

Os itens so armazenados em um array de tamanho


suficiente para armazenar a lista.

Estrutura da Lista Usando Arranjo

1
1000

typedef struct {
TipoItem Item[MaxTam];
Apontador Primeiro, Ultimo;
} TipoLista;

typedef struct {
TipoChave Chave;
/* outros componentes */
} TipoItem;

typedef int Apontador;

typedef int TipoChave;

#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#define InicioArranjo
#define MaxTam

Algoritmos e Estrutura de Dados II

Estrutura da Lista Usando Arranjo

Algoritmos e Estrutura de Dados II

void Insere(TipoItem x, TipoLista *Lista)


{
if (Lista->Ultimo > MaxTam)
printf("Lista esta cheia\n");
else {
Lista->Item[Lista->Ultimo - 1] = x;
Lista->Ultimo++;
}
} /* Insere */

int Vazia(TipoLista Lista)


{
return (Lista.Primeiro == Lista.Ultimo);
} /* Vazia */

void FLVazia(TipoLista *Lista)


{
Lista->Primeiro = InicioArranjo;
Lista->Ultimo = Lista->Primeiro;
} /* FLVazia */

Operaes sobre Lista Usando Arranjo

/* Retira */
Algoritmos e Estrutura de Dados II

if (Vazia(*Lista) || p >= Lista->Ultimo)


{
printf(" Erro
Posicao nao existe\n");
return;
}
*Item = Lista->Item[p - 1];
Lista->Ultimo--;
for (Aux = p; Aux < Lista->Ultimo; Aux++)
Lista->Item[Aux - 1] = Lista->Item[Aux];

void Retira(Apontador p, TipoLista *Lista,


TipoItem *Item)
{
int Aux;

Operaes sobre Lista Usando Arranjo

Algoritmos e Estrutura de Dados II

for (Aux = Lista.Primeiro - 1;


Aux <= (Lista.Ultimo - 2); Aux++)
printf("%d\n", Lista.Item[Aux].Chave);
} /* Imprime */

void Imprime(TipoLista Lista)


{
int Aux;

Operaes sobre Lista Usando Arranjo

economia de memria (os apontadores so implcitos nesta


estrutura).

Algoritmos e Estrutura de Dados II

custo para inserir ou retirar itens da lista, que pode causar um


deslocamento de todos os itens, no pior caso;
em aplicaes em que no existe previso sobre o crescimento
da lista, a utilizao de arranjos em linguagens como o Pascal
pode ser problemtica porque neste caso o tamanho mximo da
lista tem de ser definido em tempo de compilao.

Desvantagens:

Vantagem:

Lista Usando Arranjo - Vantagens e


Desvantagens

Algoritmos e Estrutura de Dados II

NULL

H uma clula cabea para simplificar as operaes sobre


a lista.

possvel inserir e retirar elementos sem necessidade de


deslocar os itens seguintes da lista.

Permite utilizar posies no contguas de memria.

Cada item encadeado com o seguinte mediante uma


varivel do tipo Apontador.

Implementao de Listas por meio de


Apontadores

Algoritmos e Estrutura de Dados II

O registro TipoLista contm um apontador para a clula


cabea e um apontador para a ltima clula da lista.

Cada clula contm um item da lista e um apontador


para a clula seguinte.

A lista constituda de clulas.

Estrutura da Lista Usando Apontadores

typedef struct {
Apontador Primeiro, Ultimo;
} TipoLista;

typedef struct Celula_str {


TipoItem Item;
Apontador Prox;
} Celula;

Algoritmos e Estrutura de Dados II

typedef struct Celula_str *Apontador;

typedef struct {
int Chave;
/* outros componentes */
} TipoItem;

typedef int TipoChave;

Estrutura da Lista Usando Apontadores

Algoritmos e Estrutura de Dados II

void Insere(TipoItem x, TipoLista *Lista)


{
Lista->Ultimo->Prox = (Apontador) malloc(sizeof(Celula));
Lista->Ultimo = Lista->Ultimo->Prox;
Lista->Ultimo->Item = x;
Lista->Ultimo->Prox = NULL;
}

int Vazia(TipoLista Lista)


{
return (Lista.Primeiro == Lista.Ultimo);
}

void FLVazia(TipoLista *Lista)


{
Lista->Primeiro = (Apontador) malloc(sizeof(Celula));
Lista->Ultimo = Lista->Primeiro;
Lista->Primeiro->Prox = NULL;
}

Operaes sobre Lista Usando


Apontadores

Algoritmos e Estrutura de Dados II

void Imprime(TipoLista Lista)


{
Apontador Aux;
Aux = Lista.Primeiro->Prox;
while (Aux != NULL) {
printf("%d\n", Aux->Item.Chave);
Aux = Aux->Prox;
}
}

Operaes sobre Lista Usando


Apontadores

Bom para aplicaes em que no existe previso sobre o crescimento


da lista (o tamanho mximo da lista no precisa ser definido a priori).

Permite inserir ou retirar itens do meio da lista a um custo constante


(importante quando a lista tem de ser mantida em ordem).

Algoritmos e Estrutura de Dados II

Utilizao de memria extra para armazenar os apontadores.

Desvantagem:

Vantagens:

Operaes sobre Lista Usando


Apontadores

Algoritmos e Estrutura de Dados II

Opo: vetor contendo a primeira, a segunda e a terceira opes de


curso do candidato.

NotaFinal: mdia das notas do candidato.

Chave: nmero de inscrio do candidato.

Num vestibular, cada candidato tem direito a trs opes


para tentar uma vaga em um dos sete cursos oferecidos.
Para cada candidato lido um registro:

Chave : 1..999;
NotaFinal : 0..10;
Opcao : array[1. .3] of 1. .7;

Exemplo de Uso Listas - Vestibular

Algoritmos e Estrutura de Dados II

Em caso de empate, os candidatos sero atendidos na


ordem de inscrio para os exames.

Problema: distribuir os candidatos entre os cursos,


segundo a nota final e as opes apresentadas por
candidato.

Exemplo de Uso Listas - Vestibular

Algoritmos e Estrutura de Dados II

Para um conjunto de mesma NotaFinal tenta-se encaixar


cada registro desse conjunto em um dos cursos, na
primeira das trs opes em que houver vaga (se
houver).

Percorrer cada conjunto de registros com mesma


NotaFinal, comeando pelo conjunto de NotaFinal 10,
seguido pelo de NotaFinal 9, e assim por diante.

Ordenar registros pelo campo NotaFinal, respeitando a


ordem de inscrio;

Vestibular - Possvel Soluo

Primeiro refinamento:

Algoritmos e Estrutura de Dados II

/* programa Vestibular */
void main()
{
int Nota;
ordena os registros pelo campo NotaFinal ;
for (Nota := 10; Nota >=0; Nota--) {
while (houver registro com mesma nota) {
if (existe vaga em um dos cursos de opcao do
candidato)
insere registro no conjunto de aprovados
else insere registro no conjunto de reprovados;
}
}
imprime aprovados por curso ;
imprime reprovados;
}

Vestibular - Possvel Soluo

Algoritmos e Estrutura de Dados II

Uma boa maneira de representar um conjunto de


registros com o uso de listas.
Ao serem lidos, os registros so armazenados em listas
para cada nota.
Aps a leitura do ltimo registro os candidatos esto
automaticamente ordenados por NotaFinal.

Vestibular - Classificao dos Alunos

NULL

Algoritmos e Estrutura de Dados II

NULL

Dentro de cada lista, os registros esto ordenados por


ordem de inscrio, desde que os registros sejam lidos
na ordem de inscrio de cada candidato e inseridos
nesta ordem.

Vestibular - Classificao dos Alunos

Algoritmos e Estrutura de Dados II

As listas de registros so percorridas, iniciando-se pela


de NotaFinal 10, seguida pela de NotaFinal 9, e assim
sucessivamente.
Cada registro retirado e colocado em uma das listas
abaixo, na primeira das trs opes em que houver vaga.
Aps a leitura do ltimo registro os candidatos esto
automaticamente ordenados por NotaFinal.

Vestibular - Classificao dos Alunos

Algoritmos e Estrutura de Dados II

Ao final a estrutura acima conter a relao de


candidatos aprovados em cada curso.

Se no houver vaga, o registro colocado em uma lista


de reprovados.

Vestibular - Classificao dos Alunos

le numero de vagas para cada curso;


inicializa listas de classificacao, aprovados e de reprovados;
le registro;
while (Chave != 0) {
insere registro nas listas de classificacao, conforme NotaFinal;
le registro;
}
for (Nota = 10; Nota >= 0; Nota-- ) {
while (houver proximo registro com mesma NotaFinal) {
retira registro da lista;
if (existe vaga em um dos cursos de opcao do candidato) {
insere registro na lista de aprovados;
decrementa o numero de vagas para aquele curso;
}
else insere registro na lista de reprovados;
obtem proximo registro;
}
}
imprime aprovados por curso;
imprime reprovados;
Algoritmos e Estrutura de Dados II

/* programa Vestibular */
Void main()
{
int Nota;
TipoChave Chave;

Vestibular - Segundo Refinamento

NOpcoes
NCursos
FALSE
TRUE

3
7
0
1

typedef struct TipoLista {


Celula *Primeiro, *Ultimo;
} TipoLista;

typedef struct Celula {


TipoItem Item;
struct Celula *Prox;
} Celula;

typedef struct TipoItem {


TipoChave Chave;
char NotaFinal;
char Opcao[NOpcoes];
} TipoItem;

typedef short TipoChave;

#define
#define
#define
#define

Algoritmos e Estrutura de Dados II

Vestibular - Estrutura Final da Lista

NOpcoes
NCursos
FALSE
TRUE

3
7
0
1

long Vagas[NCursos];
short Passou;
long i, Nota;

TipoItem Registro;
TipoLista Classificacao[11];
TipoLista Aprovados[NCursos];
TipoLista Reprovados;

#define
#define
#define
#define

Algoritmos e Estrutura de Dados II

Vestibular - Estrutura Final da Lista

for (i = 0; i < NOpcoes; i++)


{
scanf("%d", &(Registro->Opcao[i]));

Algoritmos e Estrutura de Dados II

scanf("%d %d", &(Registro->Chave), &(Registro->NotaFinal));

{ /*---os valores lidos devem estar separados por brancos---*/


int i;

void LeRegistro(TipoItem *Registro)

Observe que o programa completamente independente


da implementao do tipo abstrato de dados Lista.

Vestibular - Refinamento Final

FLVazia(&Aprovados[i-1]);

Algoritmos e Estrutura de Dados II

LeRegistro(&Registro);
while (Registro.Chave != 0)
{
Insere(Registro, &Classificacao[Registro.NotaFinal]);
LeRegistro(&Registro);
}

FLVazia(&Reprovados);

for (i = 1; i <= NCursos; i++)

for (i = 0; i <= 10; i++) FLVazia(&Classificacao[i]);

getchar();

int main(int argc, char *argv[])


{ /*---Programa principal---*/
for (i = 1; i <= NCursos; i++)scanf("%ld ", &Vagas[i-1]);

Vestibular - Refinamento Final

for (Nota = 10; Nota >= 0; Nota--) {


while (!Vazia(Classificacao[Nota])) {
Retira(Classificacao[Nota].Primeiro, &Classificacao[Nota],
&Registro);
i = 1;
Passou = FALSE;
while (i <= NOpcoes && !Passou) {
if (Vagas[Registro.Opcao[i-1] - 1] > 0)
{
Insere(Registro, &Aprovados[Registro.Opcao[i-1] - 1]);
Vagas[Registro.Opcao[i-1] - 1]--;
Passou = TRUE;
}
i++;
}
if (!Passou) Insere(Registro, &Reprovados);
}
}
for (i = 1; i <= NCursos; i++) {
printf("Relacao dos aprovados no Curso%ld\n", i);
Imprime(Aprovados[i-1]);
}
printf("Relacao dos reprovados\n");
Imprime(Reprovados);
return 0;
Algoritmos e Estrutura de Dados II
}

Vestibular - Refinamento Final

Algoritmos e Estrutura de Dados II

Este aspecto particularmente importante em programas


de grande porte.

Altera-se a implementao rapidamente. No


necessrio procurar as referncias diretas s estruturas
de dados por todo o cdigo.

O exemplo mostra a importncia de utilizar tipos


abstratos de dados para escrever programas, em vez de
utilizar detalhes particulares de implementao.

Vestibular - Refinamento Final

Algoritmos e Estrutura de Dados II

O modelo intuitivo o de um monte de pratos em uma


prateleira, sendo conveniente retirar ou adicionar pratos
na parte superior.

Os itens so colocados um sobre o outro. O item inserido


mais recentemente est no topo e o inserido menos
recentemente no fundo.

uma lista linear em que todas as inseres, retiradas e,


geralmente, todos os acessos so feitos em apenas um
extremo da lista.

Pilha

Algoritmos e Estrutura de Dados II

Uma pilha contm uma seqncia de obrigaes adiadas.


A ordem de remoo garante que as estruturas mais
internas sero processadas antes das mais externas.

ideal para processamento de estruturas aninhadas de


profundidade imprevisvel.

Existe uma ordem linear para pilhas, do mais recente


para o menos recente.

So chamadas listas lifo (last-in, first-out).

Propriedade: o ltimo item inserido o primeiro item que


pode ser retirado da lista.

Propriedade e Aplicaes das Pilhas

A sintaxe de expresses aritmticas.

Algoritmos e Estrutura de Dados II

As pilhas ocorrem em estruturas de natureza recursiva


(como rvores). Elas so utilizadas para implementar a
recursividade.

O controle de seqncias de chamadas de subprogramas.

Quando necessrio caminhar em um conjunto de dados e guardar


uma lista de coisas a fazer posteriormente.

Aplicaes em estruturas aninhadas:

Propriedade e Aplicaes das Pilhas

FPVazia(Pilha). Faz a pilha ficar vazia.


Vazia(Pilha). Retorna true se a pilha est vazia;
caso contrrio, retorna false.
Empilha(x, Pilha). Insere o item x no topo da pilha.
Desempilha(Pilha, x). Retorna o item x no topo da
pilha, retirando-o da pilha.
Tamanho(Pilha). Esta funo retorna o nmero de
itens da pilha.

Algoritmos e Estrutura de Dados II

Existem vrias opes de estruturas de dados que


podem ser usadas para representar pilhas.
As duas representaes mais utilizadas so as
implementaes por meio de arranjos e de apontadores.

5)

4)

3)

2)

1)

Conjunto de operaes:

TAD Pilhas

Algoritmos e Estrutura de Dados II

Os itens da pilha so armazenados em posies


contguas de memria.
Como as inseres e as retiradas ocorrem no topo da
pilha, um cursor chamado Topo utilizado para controlar
a posio do item no topo da pilha.

Implementao de Pilhas por


meio de Arranjos

typedef struct {
TipoItem Item[MaxTam];
Apontador Topo;
} TipoPilha;

typedef int Apontador;


typedef int TipoChave;
typedef struct {
TipoChave Chave;
/* --- outros componentes --- */
} TipoItem;

#define MaxTam 1000

Algoritmos e Estrutura de Dados II

Os itens so armazenados em um array de tamanho


suficiente para conter a pilha.
O outro campo do mesmo registro contm um apontador
para o item no topo da pilha.
A constante MaxTam define o tamanho mximo permitido
para a pilha.

Estrutura da Pilha Usando Arranjo

void Empilha(TipoItem x, TipoPilha *Pilha)


{
if (Pilha->Topo == MaxTam)
printf(" Erro
pilha esta cheia\n");
else { Pilha->Topo++;
Pilha->Item[Pilha->Topo - 1] = x;
}
} /* Empilha */

int Vazia(TipoPilha Pilha)


{
return (Pilha.Topo == 0);
} /* Vazia */

void FPVazia(TipoPilha *Pilha)


{
Pilha->Topo = 0;
} /* FPVazia */

Algoritmos e Estrutura de Dados II

Operaes sobre Pilhas Usando


Arranjos

int Tamanho(TipoPilha Pilha)


{
return (Pilha.Topo);
} /* Tamanho */

Algoritmos e Estrutura de Dados II

void Desempilha(TipoPilha *Pilha, TipoItem *Item)


{
if (Vazia(*Pilha))
printf(" Erro
pilha esta vazia\n");
else { *Item = Pilha->Item[Pilha->Topo - 1];
Pilha->Topo--;
}
} /* Desempilha */

Operaes sobre Pilhas Usando


Arranjos

Algoritmos e Estrutura de Dados II

H uma clula cabea no topo para


facilitar
a
implementao
das
operaes empilha e desempilha
quando a pilha est vazia.
Para desempilhar o item xn basta
desligar a clula cabea da lista e a
clula que contm xn passa a ser a
clula cabea.
Para empilhar um novo item, basta fazer
a operao contrria, criando uma nova
clula cabea e colocando o novo item
na antiga.

Implementao de Pilhas por meio de


Apontadores

Algoritmos e Estrutura de Dados II

O registro TipoPilha contm um apontador para o topo da


pilha (clula cabea) e um apontador para o fundo da
pilha.

Cada clula de uma pilha contm um item da pilha e um


apontador para outra clula.

O campo Tamanho evita a contagem do nmero de itens


na funo Tamanho.

Estrutura da Pilha Usando


Apontadores

typedef struct {
Apontador Fundo, Topo;
int Tamanho;
} TipoPilha;

typedef struct Celula_str {


TipoItem Item;
Apontador Prox;
} Celula;

typedef struct Celula_str *Apontador;

typedef int TipoChave;


typedef struct {
int Chave;
/* --- outros componentes --- */
} TipoItem;

#define max 10

Algoritmos e Estrutura de Dados II

Estrutura da Pilha Usando


Apontadores

Algoritmos e Estrutura de Dados II

Aux = (Apontador) malloc(sizeof(Celula));


Pilha->Topo->Item = x;
Aux->Prox = Pilha->Topo;
Pilha->Topo = Aux;
Pilha->Tamanho++;
} /* Empilha */

void Empilha(TipoItem x, TipoPilha *Pilha)


{
Apontador Aux;

int Vazia(TipoPilha Pilha)


{
return (Pilha.Topo == Pilha.Fundo);
} /* Vazia */

void FPVazia(TipoPilha *Pilha)


{
Pilha->Topo = (Apontador) malloc(sizeof(Celula));
Pilha->Fundo = Pilha->Topo;
Pilha->Topo->Prox = NULL;
Pilha->Tamanho = 0;
} /* FPVazia */

Operaes sobre Pilhas Usando


Apontadores

int Tamanho(TipoPilha Pilha)


{
return (Pilha.Tamanho);
} /* Tamanho */

if (Vazia(*Pilha))
{ printf(" Erro
lista vazia\n");
return;
}
q = Pilha->Topo;
Pilha->Topo = q->Prox;
*Item = q->Prox->Item;
free(q);
Pilha->Tamanho--;
} /* Desempilha */

Algoritmos e Estrutura de Dados II

void Desempilha(TipoPilha *Pilha, TipoItem *Item)


{
Apontador q;

Operaes sobre Pilhas Usando


Apontadores

UFMG.

DCC

Algoritmos e Estrutura de Dados II

*: salta a linha. Imprime os caracteres que pertencem


linha sendo editada, iniciando uma nova linha de
impresso a partir do caractere imediatamente seguinte
ao caractere salta-linha. Ex: DCC*UFMG.* !

\: cancela todos os caracteres anteriores na linha


sendo editada.

#: cancelar caractere anterior na linha sendo editada.


Ex.: UEM##FMB#G ! UFMG.

Exemplo de Uso Pilhas - Editor de


Textos (ET)

Algoritmos e Estrutura de Dados II

O ET dever utilizar o tipo abstrato de dados Pilha


definido anteriormente, implementado por meio de
arranjo.

O ET dever ler um caractere de cada vez do texto de


entrada e produzir a impresso linha a linha, cada linha
contendo no mximo 70 caracteres de impresso.

Vamos escrever um Editor de Texto (ET) que aceite os


trs comandos descritos acima.

Exemplo de Uso Pilhas - Editor de


Textos (ET)

que este funciona\\\? O sinal? no### deve ficar! ~

nn#x#ele!\ Sera

n#nt#ao### r#ess#tt#ar mb#aa#triz#cull#ado

cuu#rsh#o #x# x?*!#?!#+.* Como et# bom

et# h#um

caracteres.)*O k#cut#rso dh#e Estruturas de Dados

70

a capacidade mxima da linha de impresso, que de

vamos estourar

utilizando seus poderes extras (cuidado, pois agora

saltar de linha,

PASCAL.*Acabamos de testar a capacidade de o ET

Este et# um teste para o ET, o extraterrestre em

Algoritmos e Estrutura de Dados II

Sugesto de Texto para Testar o ET

Algoritmos e Estrutura de Dados II

A implementao do TAD Pilha que utiliza arranjo pode


ser substituda pela implementao que utiliza
apontadores sem causar impacto no programa.

Este programa utiliza um tipo abstrato de dados sem


conhecer detalhes de sua implementao.

ET - Implementao

'#'
'\\'
'*'
'~'

#define
#define
#define
#define

typedef struct {
TipoItem Item[MaxTam];
Apontador Topo;
} TipoPilha;

typedef struct {
/* --- outros componentes --- */
TipoChave Chave;
} TipoItem;

typedef int Apontador;

typedef char TipoChave;

CancelaCarater
CancelaLinha
SaltaLinha
MarcaEof

70

#define MaxTam

#include <stdio.h>

Algoritmos e Estrutura de Dados II

ET - Implementao

void Empilha(TipoItem x, TipoPilha *Pilha)


{
if (Pilha->Topo == MaxTam)
printf(" Erro
pilha est a cheia\n");
else { Pilha->Topo++;
Pilha->Item[Pilha->Topo - 1] = x;
}
} /* Empilha */

int Vazia(TipoPilha Pilha)


{
return (Pilha.Topo == 0);
} /* Vazia */

void FPVazia(TipoPilha *Pilha)


{
Pilha->Topo = 0;
} /* FPVazia */

Algoritmos e Estrutura de Dados II

ET - Implementao

int Tamanho(TipoPilha Pilha)


{
return (Pilha.Topo);
} /* Tamanho */

Algoritmos e Estrutura de Dados II

void Desempilha(TipoPilha *Pilha, TipoItem *Item)


{
if (Vazia(*Pilha))
printf(" Erro
pilha est a vazia\n");
else { *Item = Pilha->Item[Pilha->Topo - 1];
Pilha->Topo--;
}
} /* Desempilha */

ET - Implementao

int main(int argc, char *argv[])


{
TipoPilha Pilha;
TipoItem x;
FPVazia(&Pilha);
x.Chave = getchar();
while (x.Chave != MarcaEof) {
if (x.Chave == CancelaCarater) {
if (!Vazia(Pilha)) Desempilha(&Pilha, &x);
}
else if (x.Chave == CancelaLinha)
FPVazia(&Pilha);
else if (x.Chave == SaltaLinha)
Imprime(&Pilha);
else if (Tamanho(Pilha) == MaxTam) {
Imprime(&Pilha);
Empilha(x, &Pilha);
}
x.Chave = getchar();
}
if (!Vazia(Pilha)) Imprime(&Pilha);
return 0;
Algoritmos e Estrutura de Dados II
} /* ET */

ET - Implementao

Algoritmos e Estrutura de Dados II

FPVazia(&Pilhaux);
while (!Vazia(*Pilha))
{
Desempilha(Pilha, &x); Empilha(x, &Pilhaux);
}
while (!Vazia(Pilhaux))
{
Desempilha(&Pilhaux, &x); putchar(x.Chave);
}
putchar('\n');
} /* Imprime */

void Imprime(TipoPilha *Pilha)


{
TipoPilha Pilhaux;
TipoItem x;

ET - Implementao

Algoritmos e Estrutura de Dados II

So chamadas listas fifo (first-in, first-out).

O modelo intuitivo de uma fila o de uma fila de espera


em que as pessoas no incio da fila so servidas primeiro
e as pessoas que chegam entram no fim da fila.

uma lista linear em que todas as inseres so


realizadas em um extremo da lista, e todas as retiradas e,
geralmente, os acessos so realizados no outro extremo
da lista.

Fila

Algoritmos e Estrutura de Dados II

Sistemas operacionais utilizam filas para regular a ordem


na qual tarefas devem receber processamento e recursos
devem ser alocados a processos.

So utilizadas quando desejamos processar itens de


acordo com a ordem primeiro-que-chega, primeiroatendido.

Existe uma ordem linear para filas que a ordem de


chegada.

Fila

Algoritmos e Estrutura de Dados II

1) FFVazia(Fila). Faz a fila ficar vazia.


2) Enfileira(x, Fila). Insere o item x no final da fila.
3) Desenfileira(Fila, x). Retorna o item x no incio da
fila, retirando-o da fila.
4) Vazia(Fila). Esta funo retorna true se a fila est
vazia; seno retorna false.

Conjunto de operaes:

TAD Filas

Algoritmos e Estrutura de Dados II

A fila tende a caminhar pela memria do computador,


ocupando espao na parte de trs e descartando espao
na parte da frente.

A operao Desenfileira faz a parte da frente da fila


contrair-se.

A operao Enfileira faz a parte de trs da fila expandirse.

Os itens so armazenados em posies contguas de


memria.

Implementao de Filas por meio de


Arranjos

Algoritmos e Estrutura de Dados II

Soluo: imaginar o array como um crculo. A primeira


posio segue a ltima.

Com poucas inseres e retiradas, a fila vai ao encontro


do limite do espao da memria alocado para ela.

Implementao de Filas por meio de


Arranjos

Algoritmos e Estrutura de Dados II

Para desenfileirar, basta mover o apontador Frente uma


posio no sentido horrio.

Para enfileirar, basta mover o apontador Trs uma


posio no sentido horrio.

A fila se encontra em posies contguas de memria,


em alguma posio do crculo, delimitada pelos
apontadores Frente e Trs.

Implementao de Filas por meio de


Arranjos

typedef struct {
TipoItem Item[MaxTam];
Apontador Frente, Tras;
} TipoFila;

typedef int Apontador;


typedef int TipoChave;
typedef struct {
TipoChave Chave;
/* outros componentes */
} TipoItem;

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#define MaxTam 1000

Algoritmos e Estrutura de Dados II

O tamanho mximo do array circular definido pela


constante MaxTam.
Os outros campos do registro TipoPilha contm
apontadores para a parte da frente e de trs da fila.

Estrutura da Fila Usando Arranjo

int Vazia(TipoFila Fila)


{
return (Fila.Frente == Fila.Tras);
} /* Vazia */

void FFVazia(TipoFila *Fila)


{
Fila->Frente = 1;
Fila->Tras = Fila->Frente;
} /* FFVazia */

Algoritmos e Estrutura de Dados II

Nos casos de fila cheia e fila vazia, os apontadores


Frente e Trs apontam para a mesma posio do crculo.
Uma sada para distinguir as duas situaes deixar uma
posio vazia no array.
Neste caso, a fila est cheia quando Trs+1 for igual a
Frente.

Operaes sobre Filas Usando


Posies Contguas de Memria

Algoritmos e Estrutura de Dados II

void Desenfileira(TipoFila *Fila, TipoItem *Item)


{
if (Vazia(*Fila))
printf(" Erro
fila est a vazia\n");
else { *Item = Fila->Item[Fila->Frente - 1];
Fila->Frente = Fila->Frente % MaxTam + 1;
}
} /* Desenfileira */

void Enfileira(TipoItem x, TipoFila *Fila)


{
if (Fila->Tras % MaxTam + 1 == Fila->Frente)
printf(" Erro
fila est a cheia\n");
else { Fila->Item[Fila->Tras - 1] = x;
Fila->Tras = Fila->Tras % MaxTam + 1;
}
} /* Enfileira */

Operaes sobre Filas Usando


Posies Contguas de Memria

Algoritmos e Estrutura de Dados II

H uma clula cabea para facilitar a implementao


das operaes Enfileira e Desenfileira quando a fila est
vazia.
Quando a fila est vazia, os apontadores Frente e Trs
apontam para a clula cabea.
Para enfileirar um novo item, basta criar uma clula nova,
lig-la aps a clula que contm xn e colocar nela o novo
item.
Para desenfileirar o item x1, basta desligar a clula
cabea da lista e a clula que contm x1 passa a ser a
clula cabea.

Implementao de Filas por meio de


Apontadores

Algoritmos e Estrutura de Dados II

A estrutura TipoFila contm um apontador para a frente


da fila (clula cabea) e um apontador para a parte de
trs da fila.

Cada clula contm um item da fila e um apontador para


outra clula.

A fila implementada por meio de clulas.

Estrutura da Fila Usando Apontadores

typedef struct TipoFila {


Apontador Frente, Tras;
} TipoFila;

typedef struct Celula_str {


TipoItem Item;
Apontador Prox;
} Celula;

typedef struct TipoItem {


TipoChave Chave;
/* outros componentes */
} TipoItem;

typedef int TipoChave;

typedef struct Celula_str *Apontador;

#include <stdlib.h>
#include <sys/time.h>
#include <stdio.h>
#define max 10

Algoritmos e Estrutura de Dados II

Estrutura da Fila Usando Apontadores

Algoritmos e Estrutura de Dados II

void Enfileira(TipoItem x, TipoFila *Fila)


{
Fila->Tras->Prox = (Apontador) malloc(sizeof(Celula));
Fila->Tras = Fila->Tras->Prox;
Fila->Tras->Item = x;
Fila->Tras->Prox = NULL;
} /* Enfileira */

int Vazia(TipoFila Fila)


{
return (Fila.Frente == Fila.Tras);
} /* Vazia */

void FFVazia(TipoFila *Fila)


{
Fila->Frente = (Apontador) malloc(sizeof(Celula));
Fila->Tras = Fila->Frente;
Fila->Frente->Prox = NULL;
} /* FFVazia */

Operaes sobre Filas Usando


Apontadores

Algoritmos e Estrutura de Dados II

void Desenfileira(TipoFila *Fila, TipoItem *Item)


{
Apontador q;
if (Vazia(*Fila))
{ printf(" Erro
fila est a vazia\n");
return;
}
q = Fila->Frente;
Fila->Frente = Fila->Frente->Prox;
*Item = Fila->Frente->Item;
free(q);
} /* Desenfileira */

Operaes sobre Filas Usando


Apontadores

Um problema que pode surgr na manipulacao de listas lineares simples e


o de voltar atras na lista, ou seja, percorre-la no sentido inverso ao dos
apontadores. A solucao geralmente adotada e a incorporacao a celula de
um apontador para o seu antecessor. Listas deste tipo sao chamadas de
duplamente encadeadas. Faca:

4)

5)

Implemente as operacoes Empilha e Desempilha, usando duas Filas

3)

Estenda o TAD lista (por apontadores) com um procedimento para trocar


de posicao dois elementos. Este procedimento deve receber como
parametro, alem da lista, os apontadores p e q. Ele deve tratar os casos
especiais (apontadores para NULL, etc).

Declare os tipos necessarios para a manipulacao da lista


Escreva um procedimento para retirar da lista a celula apontada por p.
Nao deixe de considerar eventuais casos especiais

Implemente um procedimento que, utilizando os TADs Lista e Pilha,


retorne os elementos da Lista em ordem invertida (em uma outra lista)

2)

a)
b)

Estenda o TAD Lista, implementado por apontadores, para incluir um


procedimento que remova TODOS os elementos pares da lista.

1)

Exercicios

You might also like