ed 1

Upload: danilo

Post on 08-Jul-2015

414 views

Category:

Documents


0 download

TRANSCRIPT

Estrutura de Dados

Docente: Dikiefu Fabiano, Msc

Sumrio1. Elementos bsicos de programao em C 1.1 Conceitos bsicos 1.2 Ponteiros 1.3 Funes 1.4 Estruturas e tipos de dados definidos pelo programador Listas Lineares 2. 1 Listas Sequenciais 2.2 Listas ligadas 2.3 Listas Circulares 2.4 Listas duplamente ligadas 2.5 Pilhas 2.5.1 Implementao sequencial da pilha 2.5.2 Implementao dinmica da pilha 2.6 Filas 2.6.1 Implementao sequencial da fila 2.6.2 Implementao dinmica da fila 2.6.3 Fila circular

2.

3.

rvores 3.1 Introduo 3.2 Representao de rvores 3.2 Definio 3.3 Terminologia 3.4 rvores binrias 3.5 rvores balanceadas 3.6 Definio da estrutura de dados 4. Ordenao 4.1 Ordenao por Seleco 4.2 Ordenao por Insero 4.3 Shellsort 4.4 Quicksort 4.5 Heapsort 5. Pesquisa 5.1 Pesquisa Sequencial 5.2 Pesquisa Binria 5.3 rvores de Pesquisa

Capitulo I: Elementos bsicos de programao em CSumrio:1.1 Conceitos bsicos 1.2 Ponteiros 1.3 Funes 1.4 Estruturas 1.5 Tipos de dados definidos pelo programador

1.1 Conceitos bsicos Tipos de Dados Tipo de dados de uma variveis define o conjunto de valores que a varivel pode assumir. Especifica a quantidade de bytes que deve ser reservadas a ela. Tipos de dados podem ser vistos como mtodos para interpretar o contedo da memria do computador Podemos ver o conceito de tipo de dados de uma outra perspectiva: no em termos do que um computador pode fazer (interpretar os bits ) mas em termos do que o utilizador desejam fazer (somar dois inteiros)

1.1 Conceitos bsicos Tipos Abstractos de Dados Agrupa a estrutura de dados juntamente com as operaes que podem ser feitas sobre esses dados O TAD encapsula a estrutura de dados. Os usurios do TAD s tem acesso a algumas operaes disponibilizadas sobre esses dados Usurio do TAD x Programador do TAD Usurio s enxerga a interface, no a implementao Dessa forma, o usurio pode abstrair da implementao especfica. Qualquer modificao nessa implementao fica restrita ao TAD A escolha de uma representao especfica fortemente influenciada pelas operaes a serem executadas

1.1 Conceitos bsicos Estrutura de Dados - ED um mtodo particular de se implementar um TAD Cada ED construda dos tipos primitivos (inteiro, real, char, ) ou dos tipos compostos (array, registo, ) de uma linguagem de programao. Algumas operaes realizadas em um TAD so: criao, incluso, busca e remoo de dados.

Exemplos de TAD Lineares: Listas ligadas Pilhas Filas Deques No Lineares: . rvores . Grafos

1.2 Apontadores O objectivo: Armazenar o endereo de outra varivel, o qual , por sua vez, um nmero.

Sintaxetipo * ptr ptr - o nome da varivel do tipo apontador tipo o tipo da varivel para qual apontar. * - indica que uma varivel do tipo apontador

Exemplo 1:char a, b, *p, c, *q; int idade, *p_idade;

1.2 Apontadores 1.2.1 Inicializao automtica de apontadores Um bom hbito para evitar problemas de programao a inicializao sempre dos apontadores A constante simblica NULL, quando colocada num apontador, indica que este no aponta para nenhuma varivel.int x = 5; float pi = 3.1415; int px = &x; float * ppi =

1.2 Apontadores 1.2.2 Exemplo Exemplo 1

1.3 Funes Conceito: uma unidade autnoma de cdigo do programa e desenhada para cumprir um tarefa particular.

Sintaxetipo nome_da_funo (parametros){ comandos; }

1.3 Funes Quando uma funo no retorna um valor para funo que a chamou ela declarada como void. Ex:#includevoid linha (char ch, int size){ int i; for (i=1; i size; i++) putchar(ch); } main(){ char lin; int tamanho; printf(Introduza o tipo de linha); scanf(%c, &lin); printf(Introduza o tamanho da linha); scanf(%d, &tamanho);

linha(lin, tamanho); getchar();}

1.3 Funes1.3.3 Funo com retorno

O tipo de retorno tem que ser declarada. Ex1 : int potencia (int base, int expoente){ int i; If (expoentenome=Joana; //muda o valor do campo nome para Joana estud ->idade =22; //muda o valor do campo idade para 22 estud ->sexo =F; //muda o valor do campo sexo para F docente.Nome=Pedro; //Referncias usam a notao de ponto }

Estruturas Estruturas podem ser recursivas, i.e., podem conter ponteiros para si mesmas. Esta peculiaridade ajuda a definir estruturas do tipo lista.struct lista{ struct lista *prox; int dado; }

Capitulo II: ListasSumrio2. Listas Lineares 2. 1 Listas Sequenciais 2.2 Listas ligadas 2.3 Listas Circulares 2.4 Listas duplamente ligadas 2.5 Pilhas 2.5.1 Implementao sequencial da pilha 2.5.2 Implementao dinmica da pilha 2.6 Filas 2.6.1 Implementao sequencial da fila 2.6.2 Implementao dinmica da fila 2.6.3 Fila circular

Listas Listas so uma coleco de objectos, onde os itens podem ser adicionados em qualquer posio arbitrria.

ListasPropriedades Uma lista pode ter zero ou mais elementos Um novo item pode ser adicionado a lista em qualquer ponto Qualquer item da lista pode ser eliminado Qualquer item da lista pode ser acessado

Listas - Formas de Representao Sequencial Explora a sequencialidade da memria do computador, de tal forma que os ns de uma lista sejam armazenados em endereo sequencias. Podem ser representado por um vector na memria principal ou um arquivo sequencial em disco.L

Ado0

Adelina1

Bastos2

Daniel3

Josefina4 5

MAX-1

Ligada Esta estrutura tida como uma sequencia de elementos ligados por ponteiros, ou seja, cada elemento deve conter, alm do dado propriamente dito, uma referencia para o prximo elemento da lista.Ado Adelina Bastos Daniel Josefina

L

Listas sequenciais Uma lista representada de forma sequencial um conjunto de registos onde esto estabelecidas regras de precedncia entre seus elementos. Implementao de operaes pode ser feita utilizando array e registo, associando o elemento a[i] com o ndice i. Caractersticas Os elementos na lista esto armazenados fisicamente em posies consecutivas A insero de um elemento na posio a[i] causa o deslocamento a direita do elemento a[i] ao ltimo. A eliminao do elemento a[i] requer o deslocamento esquerda do a[i+1] ao ltimo.

Listas Sequenciais Vantagens Acesso directo a qualquer dos elementos da lista. Tempo constante para acessar o elemento i - (depende somente de ndice) Desvantagens Para inserir ou remover elementos temos que deslocar muitos outros elementos Tamanho mximo pr-estimado Quando usar Listas pequenas Insero e remoo no fim da lista Tamanho mximo bem definido

Listas sequenciaisOperaes bsicas

Definio#define MAX 50 typedef char elem[20]; typedef struct tlista{ elem v[MAX]; int n; }; //tamanho mximo da lista // tipo base dos elementos da lista //vector que contm a lista //posio do ltimo elemento da lista

Tlista n=5

v

Ado

Alberto

Ana

Daniela

Carmen

0

1

2

3

4

5

6

MAX 1

1.Criar uma lista vaziavoid criar(tlista *L) { L -> n = 0; }

2. Verificar se uma lista est vaziaint vazia(tlista L) { return (L .n == 0); }

Listas sequenciaisOperaes bsicas3. Verificar se uma lista est cheiaint cheia( tlista L) { return (L .n == MAX); }

4. Obter o tamanho de uma listaint tamanho ( tlista L){ return (L.n); }

5. Obter o i-simo elemento de uma listaint elemento( tlista L, int pos, elem *dado ) { if ((pos > L.n) || (pos L->n + 1 )) return (0); for (i = L->n; i >= pos; i--) L->v[i] = L->v [i-1]; L->v[pos-1] = dado; (L->n)++; return (1); }

int remover( tlista *L, int pos, elem *dado ) { int i; if ( ( pos > L->n) || (pos v[pos-1]; for (i = pos; i n) - 1; i++) L->v[i-1] = L->v [i]; (L->n)--; return (1); }

Listas Ligadas Uma lista ligada ou lista encadeada uma estrutura de dados linear e dinmica. Ela composta por clulas que apontam para o prximo elemento da lista. Para "ter" uma lista ligada/encadeada, basta guardar seu primeiro elemento, e seu ltimo elemento aponta para uma clula nula. Vantagens A insero ou a retirada de um elemento na lista no implica na mudana de lugar de outros elementos; No necessrio saber, anteriormente, o nmero mximo de elementos que uma lista pode ter, o que implica em no desperdiar espao na Memria Principal (Memria RAM) do computador. manipulao torna-se mais "perigosa" uma vez que, se o encadeamento (ligao) entre elementos da lista for mal feito, toda a lista pode ser perdida; Para acessar o elemento na posio n da lista, deve-se percorrer os n - 1 anteriores.

Desvantagens

Listas ligadas As listas ligadas so conjunto de elementos ligados, onde cada elemento contem uma ligao com um ou mais elementos da lista. Uma lista ligada tem necessariamente uma varivel ponteiro apontando para o seu primeiro elemento. Essa varivel ser utilizada sempre, mesmo que esteja vazia, e dever apontar sempre para o incio da lista. Cada elemento da lista ligada ser composta por duas/trs partes principais: uma parte conter informaes e a(s) outra(s) as conexes com elementos.

Listas Ligadas - Propriedades Uma lista pode ter zero ou mais elementos Um novo item pode ser adicionado a lista em qualquer ponto Qualquer item da lista pode ser eliminado Qualquer item da lista pode ser acessado.

Listas Ligadas Uma lista ligada composta por elementos alocadas em memria. Utiliza-se duas funes para alocar (desalocar) memria dinamicamente: malloc() free()

Ex:L = (lista) malloc(sizeof(lista)); free(L);

Lista Simplesmente Ligada Cada elemento da lista possui uma nica conexo. Assim, cada elemento ser formado por um bloco de dados e um ponteiro para prximo elemento. Chamaremos cada elemento n. Um n um conjunto de informaes de tipos diferentes, portanto ela uma estrutura definida pelo programador: struct no{ int dado; struct no *prox; //ponteiro para o prximo n }

Listas Simplesmente Ligadas Sendo que uma memria alocada dinamicamente no possui o nome como no caso das variveis declaradas no programa, toda lista dever ter uma varivel que apontar para o seu primeiro elemento.struct no *head; //cabea da lista head=null; //inicia a lista com nulo

Listas Simplesmente Ligadas Podemos nos referenciar a uma lista ligada atravs do seu primeiro n. Entretanto, toda vez que realizarmos uma insero no incio da lista teremos que garantir que todas as partes do programa que referenciam a lista tenha suas referencias actualizadas. Para evitar este problema, comum usar um n especial chamado n cabea, e um ponteiro para o primeiro elemento da lista.

Listas Simplesmente Ligadas A implementao em C de uma lista simplesmente ligada com n cabea. Precisamos de dois tipos de dados: Um tipo n, representa cada elemento da lista. e um tipo lista que contm um ponteiro para n cabea.

Listas Simplesmente Ligadastypedef struct no{ int dado; // o dado poderia ser de qualquer tipo struct no *prox; // ponteiro para prximo elemento } NO typedef struct lista{ NO *head; }LISTA

Listas Simplesmente Ligadas As operaes bsicas sobre a estrutura so: criao da lista e de n. 1. Criao de lista LISTA *criaLista(){ LISTA *L; L=(LISTA *)malloc(sizeof(LISTA)); L->head = NULL; return L; } 2. Criao de n NO *criaNo(int dado){ NO *no; no = (NO *)malloc(sizeof(NO)); no->dado = dado; no->prox = NULL; return no; }

Listas Simplesmente Ligadas Ao contrrio dos vectores, onde acessamos qualquer elemento usando um ndice numrico, com uma lista ligada temos apenas acesso sequencial, por exemplo, para chegar ao decimo elemento temos que passar por todos nove elementos anteriores. Para percorrer uma lista, precisamos obter seu primeiro elemento e ento obtemos os elementos subsequentes seguindo os ponteiros de prximo elemento em cada n.

NO *primeiro(LISTA *L){ return (L->head); } NO *proximo(NO *no){ return (no->prox); }

Listas Simplesmente Ligadas Andar para trs em uma lista simplesmente ligada no to simples, requer que a lista seja percorrida desde o incio verificado se, para cada elemento x, proximo(x) o elemento do qual procuramos o elemento anterior.

NO *anterior(LISTA *L, NO *no){ NO *p; if(no==L->head) return NULL; p = primeiro(L); while(proximo(p)!=NULL){ if(proximo(p) == no) return p; p = proximo(p); } return NULL; }

Listas Simplesmente Ligadas Obter o ltimo elemento tambm requer que toda a lista seja percorrida.

NO *ultimo(LISTA *L){ NO *p; p = primeiro(L); if (p == NULL) return NULL; while(proximo(p)!=NULL) p = proximo(p); return p; }

Listas Simplesmente Ligadas Podemos querer 3 tipos de inseres em uma lista: no incio, no fim, ou em uma posio arbitrria.

Na lista simplesmente ligada a insero no incio trivial: Fazemos o prximo do novo elemento apontar para o primeiro elemento da lista e fazemos com que o novo elemento seja o primeiro elemento (cabea) da lista. A insero em posio arbitrria pode ser feito em tempo constante se tivermos um ponteiro para o elemento que ser o elemento anterior ao novo elemento: void insere_apos(NO *novo, NO *anterior){ novo->prox = anterior->prox; antrior->prox = novo; }

A insero no final da lista exige que encontremos seu ltimo elemento.

Listas Simplesmente Ligadas Remoo de um elemento arbitrrio requer que encontremos o elemento anterior ao removido.

void remove(LISTA *lista, NO *no){ NO *ant; if(no == lista->head){ lista->head = no->prox; } else{ ant = anterior(lista, no) if(ant!=NULL) ant->prox = no->prox; } free(no); }

Listas duplamente ligadas Na presena de um problema que exija uma movimentao eficiente desde um n quer para o seu antecessor, quer para o seu sucessor, podemos utilizar aquilo que se chama uma lista duplamente ligada.frente NULL valor valor valor NULL Atrs

Listas duplamente ligadas Uma das virtudes de listas duplamente ligadas, o facto de nos podemos deslocar para o n anterior ou para n seguinte, a um n dado com facilidade. Uma lista duplamente ligada permite-nos remover um n qualquer da lista em tempo constante, usando apenas um ponteiro para essa clula.

Listas duplamente ligadas - operaes anterior(): devolve o elemento anterior a um determinado elemento. cria(): devolve uma lista com um elemento insere(): insere um determinado elemento na lista. mostra(): mostra o contedo da lista. procura(): devolve a posio de um determinado elemento. remove(): remove o elemento desejado da lista.

Lista duplamente Ligada - operaes#include #include typedef struct listadl{ struct listadl *prox; //prximo elemento da lista struct listadl *ant; //elemento anterior da lista int dado; }LDL;

Lista duplamente Ligada - operaesDevolve uma lista com elemento elem.LDL *cria(int elem){ LDL*tmp; tmp =(LDL *)malloc(sizeof(tmp)); tmp->dado = elem; tmp->prox = NULL; tmp->ant = NULL; return tmp; }

Lista duplamente Ligada - operaesInsere o elemento elem na lista L.void *insere(int elem, LDL *L){ LDL*tmp; tmp=L; while((tmp->prox ==NULL)==0) tmp = tmp->prox; tmp->prox = cria(elem); (tmp->prox)-> ant = tmp; }

Lista duplamente Ligada - operaesImprime todos os elementos da lista.

void *mostra(LDL *L){ LDL*tmp, *no1, *no2; tmp=L; while((tmp->prox ==NULL)==0){ no1 = tmp->prox; no2 = tmp->ant; printf(O elemento: %d, tmp->dado);

if((no1 == NULL)==0) printf(O proximo:%d, no1->dado); else printf(No possui prximo.); if((no2 == NULL)==0) printf(O anterior:%d, no2->dado); else printf(No possui anterior.); tmp= tmp->prox; } }

Lista duplamente Ligada - operaesRemove o elemento elem da lista L.

LDL *remove(int elem, LDL *L){ LDL*tmp, *proxno, *noant; tmp=L; while((tmp->prox ==NULL)==0){ proxno = tmp->prox; noant = tmp->ant; if((tmp->dado == elem) if((noant == NULL)==0) if((proxno == NULL)==0){ noant->prox =proxno; proxno->ant =noant; free(tmp); return L; } else{ noant->prox=NULL; free(tmp); return L; }

else if((proxno == NULL)==0){ proxno->ant =NULL; free(tmp); L = proxno; return L; } else { L = NULL; free(tmp); return L; } else{ tmp = tmp -> prox; } printf(O elemento %d no se encontra na lista\n, elem); }

Lista duplamente Ligada - operaesDevolve a posio do elemento elem.int *procura(int elem, LDL *L){ LDL*tmp; int pos = 0; tmp=L; while((tmp->prox ==NULL)==0) if((tmp->dado) == elem){ printf(A posio do elemento %d %d\n, elem, pos); return pos; } else{ pos++; tmp = tmp->prox; } printf(O elemento no se encontra na lista); }

Lista duplamente Ligada - operaesDevolve o elemento anterior a elem.

void *anterior(int elem, LDL *L){ LDL*tmp, *noant;

tmp=L; while((tmp==NULL)==0) if((tmp->dado) == elem){ noant = tmp->ant; printf(O elemento anterior a %d %d\n, elem, noant->dado); else printf(No existe anterior); exit(); } else tmp = tmp->prox; printf(O elemento no se encontra na lista);}

Lista Circular Ligada As listas circulares so do tipo simples ou duplamente ligadas, em que o n final da lista a ponta para o n inicial. Este tipo de estrutura adapta-se a situaes do tipo FIFO (First In First Out).Fig. 1 Lista circular ligada ( lista simplesmente ligada)dado dado dado dado

Fig. 2 Lista circular ligada ( lista duplamente ligada)dado dado dado dado

Lista circular Ligada - operaestypedef struct no{ int dado; struct no *prox; }NO, LCSL; NO cabeca; 1. Inicializa a lista circular int inicializa(LCSL *cabeca) { *cabeca=NULL; return 0; } 2. Verifica se a lista est cheia 3. Aloca e desaloca n. int aloca(LCSL *lista, int valor){ LCSL *tmp; tmp= (LCSL) malloc(sizeof(no)); if (tmp==NULL) return 1; // Erro *lista = tmp; tmp->dado = valor; tmp->prox = NULL; return 0; } void liberta(LCSL *lista){ free(*lista); *lista=NULL; }

int vazia(LCSL lista){ return (lista==NULL)? 1:0; }

Lista circular Ligada - operaes4. Insero de um item int insere(LCSL *lista, int valor) { LCSL tmp; if (aloca(&tmp, valor)== 1) return 1; // Erro if (vazia(*lista) == 1){ //True=1 tmp->prox = tmp; *lista=tmp; } else { tmp->prox = *lista->prox; *lista->prox = tmp; } return 0; }

5. Adiciona um item ao fim da lista. int adiciona(LCSL *lista, int valor){ LCSL tmp; if (aloca(&tmp, valor)== 1) return 1; // Erro if (vazia(*lista) == 1) //True=1 tmp->prox = tmp; else{ tmp->prox = *lista->prox; *lista->prox = tmp; } *lista = tmp; return 0; //Ok }

Lista circular Ligada - operaes6. Eliminao de um n int apagaNo(LCSL *lista, LCSL no) { LCSL tmp; if(vazia(*lista) == 1) return 1; if(no==no->prox) *lista=NULL; else { for(tmp=*lista->prox; tmp!=*lista && tmp->prox!=no; tmp=tmp->prox) ; if(tmp->prox !=no) return 1; tmp->prox = no->prox; if(no== *lista) *lista=tmp; } free(&no); return 0; }

Pilhas e Filas1. 2. 3. 4. 5. 6. 7. 8. Pilhas Implementao sequencial da pilha Implementao dinmica da pilha Filas Implementao sequencial da fila Implementao dinmica da fila Fila circular Exerccios.

Pilhas Pilhas so listas onde a insero ou a remoo de um item feita no topo. Definio: dada a pilha P= (a*1+, a*2+, , a*n+), dizemos que a[1] o elemento da base da pilha; a[n] o elemento topo da pilha; e a[i+1] est acima de a[i]. Pilhas so conhecidas como listas LIFO (last in first out)

Implementao de pilhas Como lista sequencial ou ligada? No caso geral de listas ordenadas, a maior vantagem da alocao dinmica sobre a sequencial, se a memria no for problema, a eliminao de deslocamento na insero ou eliminao dos elementos. No caso das pilhas, essas operaes de deslocamento no ocorrem. Portanto, alocao sequencial mais vantajosa na maioria das vezes. Como o acesso a pilha limitado ao ltimo elemento inserido, todos os elementos do meio do vector devem estar preenchidos. H desvantagens quando a quantidade de dados a ser armazenados no conhecido antecipadamente.

Pilhas

Implementao Sequencial#define MAXPILHA 50 #define tpilha(p) (p->topo p->base) typedef struct pilha{ int base[MAXPILHA]; int *topo; }PILHA;

Implementao Sequencial1. Inicializa a pilha vazia int inicializa(PILHA *pp){ pp->topo = pp->base; return 1; } Verifica se pilha est vaziaint vazia(PILHA *pp){ return (pp->topo == pp->base) ? 1 : 0; }

2.

3.

Coloca dado na pilha. Apresenta erro se no haver espao. int push(PILHA *pp, int dado){ if(tpilha(pp) == MAXPILHA) return 0; *pp->topo=dado; pp->topo++; return 1; }

Implementao Sequencial4. Retira o valor do topo da pilha a atribui a dado. int pop (PILHA *pp, int dado){ if(vazia(pp) == 1) return 0; pp->topo--; *dado = *pp->topo return 1; } Retorna o valor do topo da pilha se remov-lo. int topo(PILHA *pp, int *dado){ if(pop(pp, dado) == 0) return 0; return push (pp, dado)}

5.

Implementao Dinmica#define INCR 50 #define tpilha(p) (p->topo p->base) typedef struct pilha{ int *base; int *topo; int tam; }PILHA;

Implementao dinmica1. Aloca espao para pilha e inicializa como vazia int inicializa(PILHA *pp){ pp->base = (int *) malloc (INCR *sizeof(int)); if(pp->base == NULL) return 0; pp->topo = pp->base; pp->tam = INCR; return 1; }

Implementao Dinmica2. Coloca dado na pilha. Se no houver mais espao, aloca mais uma parte da memria. int push(PILHA *pp, int dado){ int *novapilha; if(tpilha(pp) == pp->tam){ *novapilha = (int *) realloc(pp->base, pp->tam + INCR)*sizeof(int *)); if(novapilha==NULL) return 0; pp->base=novapilha; pp->topo=pp->base + pp->tam; pp->tam+=INCR; } *pp->topo->dado; pp->topo++; return 1; } As funes pop() e topo() da implementao de pilhas esttica e dinmica so as mesmas.

Fila Uma Fila uma estrutura de dados do tipo FIFO (First In First Out), cujo funcionamento inspirado no de uma fila natural, na qual o primeiro elemento a ser inserido sempre o primeiro elemento a ser retirado.

FilasUma fila tem por norma as seguintes funcionalidade: Colocar e retirar dados da fila: insere guardar um elemento na fila remove retirar um elemento da fila topo retornar o elemento do topo da fila.

Testar se a fila est vazia ou cheia: cheia Verificar se a fila est cheia (no pode guardar mais elementos). vazia Verificar se a fila est vazia (no contm elementos)

Inicializar ou limpar: inicializa Colocar a fila num estado pronto a ser utilizada

Filas A implementao de uma fila pode ser efectuada atravs da utilizao de diferentes estruturas de dados (vectores, listas ligadas, rvores, etc.). De seguida, apresenta-se duas implementao de uma fila atravs da utilizao de vectores e listas ligadas.

Filas Caractersticas das filas: Os dados so armazenados pela ordem de entrada

Tipos de filas: Filas de espera (queues) com duplo fim (deque double-ended queue)

Filas de espera com prioridades (priority queues)

Implementao das filas: usando vectores / arrays (circulares ou no) utilizando um apontador para ns de informao (lista ligada)

Filas Implementao em C usando arrays Vantagens: Facilidade de implementao.

Desvantagens: Vectores possuem um espao limitado para armazenamento de dados. Necessidade de definir um espao grande o suficiente para a fila Necessidade de um indicador para o inicio e para o fim da fila

Mtodo de Implementao A adio de elementos fila resulta no incremento do indicador do fim da fila A remoo de elementos da fila resulta no incremento do indicador do inicio da fila

Filas As FILAS so listas lineares que adotam a poltica FIFO (First In First Out - primeiro a entrar o primeiro a sair) para a manipulao de elementos. Inseres so feitas no final da fila (enfileirar elemento); Remoes so feitas no incio da fila (desenfileirar elemento);

Filas Operaes Bsicas Criao Destruio Insero de um elemento Remoo de um elemento Localizao de um elemento para consulta ou alterao da informao

Filas Outras Operaes Buscar por elementos que coincidam com certo padro (casamento de padro) Ordenar uma lista Intercalar duas listas Concatenar duas listas Dividir uma lista em duas Fazer cpia da lista

Filas Representao Fsica Pode ser feita de duas formas: Garantindo-se a precedncia dos elementos pela contiguidade fsica na memria usando-se vectores. Garantindo-se a precedncia dos elementos pelo seu encadeamento usando-se apontadores.

Filas Implementao Sequencial

Filas Implementao Sequencial GERAR UMA FILA COM OS ELEMENTOS 15, 10, 23, 7 e 14 max - tamanho mximo da fila n - nmero de elementos na fila

Filas Implementao SequencialENFILEIRAR 15 (inserir o elemento 15 na fila)

Filas Implementao SequencialENFILEIRAR 10 (inserir o elemento 10 na fila)

Filas Implementao SequencialENFILEIRAR 23 (inserir o elemento 23 na fila)

Filas Implementao SequencialENFILEIRAR 7 (inserir o elemento 7 na fila)

Filas Implementao Sequencial ENFILEIRAR 14 (inserir o elemento 14 na fila)

Filas Implementao SequencialDESENFILEIRAR (retirar elemento da fila sempre do incio)

Filas Implementao SequencialDESENFILEIRAR (retirar elemento da fila - sempre do incio)

Filas Implementao SequencialDESENFILEIRAR (retirar elemento da fila - sempre do incio)

Filas Implementao Sequencial DESENFILEIRAR (retirar elemento da fila - sempre do incio)

Filas Implementao SequencialDESENFILEIRAR (retirar elemento da fila - sempre do incio)

Filas Implementao Sequencial DESENFILEIRAR (retirar elemento da fila - sempre do incio)

Filas Implementao Sequencial Ao ENFILEIRAR verificar se fila est cheia (fila=max-1): se fila cheia, imprimir mensagem fila cheia; seno, enfileirar elemento e actualizar fim da fila.

Ao DESENFILEIRAR verificar se fila est vazia (fim=-1): se fila vazia, no desenfileirar e imprimir mensagem fila vazia; seno, desenfileirar, mostrar elemento desenfileirado e movimentar elementos das posies i+1 para i, i = 1 .. n-1.

Fila Circular Implementao Sequencial Para aproveitar as posies do vector liberadas, os ndices se comportam de uma forma circular incr(i) = mod (i+1, MAX) Inicio marca a posio do prximo elemento a ser retirado da fila Fim, marca a posio (vazia) onde ser inserido o prximo elemento

Fila Circular Implementao Sequencial Fila vazia, se inicio = fim Fila cheia, se fim e inicio esto em posies consecutivas (circularmente), ou seja, incio = incr(fim) A posio indicada por fim permanece sempre vazia

Fila Circular Implementao Sequencial GERAR UMA FILA COM OS ELEMENTOS 15, 10, 23 RETIRAR 15 e INSERIR 7, 14 e 30 max - tamanho mximo da fila n - nmero de elementos na fila

Fila Circular Implementao Sequencial ENFILEIRAR 15 (inserir o elemento 15 na fila)

Fila Circular Implementao Sequencial ENFILEIRAR 10 (inserir o elemento 10 na fila)

Fila Circular Implementao Sequencial ENFILEIRAR 23 (inserir o elemento 23 na fila)

Fila Circular Implementao SequencialDESENFILEIRAR (retirar elemento do incio da fila)

Fila Circular Implementao SequencialENFILEIRAR 7 (inserir o elemento 7 na fila)

Fila Circular Implementao Sequencial ENFILEIRAR 14 (inserir o elemento 14 na fila)

Fila Circular Implementao Sequencial

Fila Circular Implementao Sequencial

Fila Circular Implementao Sequencial

Fila Circular Implementao Sequencial

Fila Circular Implementao Sequencial

Fila Circular Encadeamento

Capitulo III: rvores

Docente: Dikiefu Fabiano, Msc

Sumrio3.1 Introduo 3.2 Tipos de rvores 3.3 rvores binrias 3.3.1 Estrutura de uma rvore binria 3.3.2 Descrio 3.3.3 Altura 3.3.4 Representao em C 3.4 rvores Genricas 3.4.1 Estrutura de uma rvore genrica 3.4.2 Representao em C 3.4.3 Problemas com Representao

Introduo As estruturas anteriores so chamadas de unidimensionais (ou lineares) Exemplo so listas sequenciais e ligadas

No podem ser usadas como hierarquias. Exemplo: rvore de directrios rvore uma estrutura adequada para representar hierarquias A forma mais natural para definirmos uma estrutura de rvore usando recursividade

Estrutura de rvores Uma rvore composta por um conjunto de ns. Existe um n r, denominado raiz, que contm zero ou mais sub-rvores, cujas razes so ligadas a r. Esses ns razes das sub-rvores so ditos filhos do n pai, no caso r. Ns com filhos so comumente chamados de ns internos e ns que no tm filhos so chamados de folhas, ou ns externos. tradicional desenhar as rvores com a raiz para cima e folhas para baixo, ao contrrio do que seria de se esperar.

Estrutura de rvores

Por adoptarmos essa forma de representao grfica, no representamos explicitamente a direco dos ponteiros, subentendendo que eles apontam sempre do pai para os filhos.

Tipos de rvores O nmero de filhos permitido por n e as informaes armazenadas em cada n diferenciam os diversos tipos de rvores existentes. Estudaremos dois tipos de rvores. Primeiro, examinaremos as rvores binrias, onde cada n tem, no mximo, dois filhos. Depois examinaremos as chamadas rvores genricas, onde o nmero de filhos indefinido. Estruturas recursivas sero usadas como base para o estudo e a implementao das operaes com rvores.

rvore Binria Um exemplo de utilizao de rvores binrias est na avaliao de expresses. Como trabalhamos com operadores que esperam um ou dois operandos, os ns da rvore para representar uma expresso tm no mximo dois filhos. Nessa rvore, os ns folhas representam operandos e os ns internos operadores.

rvores Binrias

Esta rvore representa a expresso (3+6)*(4-1)+5

Estrutura de uma AB Numa rvore binria, cada n tem zero, um ou dois filhos. De maneira recursiva, podemos definir uma rvore binria como sendo: uma rvore vazia; ou um n raiz tendo duas sub-rvores, identificadas como a sub-rvore da direita (sad) e a sub-rvore da esquerda (sae).

Estrutura de uma AB Os ns a, b, c, d, e, f formam uma rvore binria da seguinte maneira: A rvore composta do n a, da subrvore esquerda formada por b e d, e da sub-rvore direita formada por c, e e f. O n a representa a raiz da rvore e os ns b e c as razes das subrvores. Finalmente, os ns d, e e f so folhas da rvore.

Descrio de AB Para descrever rvores binrias, podemos usar a seguinte notao textual: A rvore vazia representada por , e rvores no vazias por .

Com essa notao, a rvore da Figura anterior representada por: .

Descrio de AB Uma sub-rvore de uma rvore binria sempre especificada como sendo a sae ou a sad de uma rvore maior, e qualquer das duas sub-rvores pode ser vazia. As duas rvores da Figura abaixo so distintas.

Altura de uma AB Uma propriedade fundamental de todas as rvores que s existe um caminho da raiz para qualquer n. Podemos definir a altura de uma rvore como sendo o comprimento do caminho mais longo da raiz at uma das folhas. A altura de uma rvore com um nico n raiz zero e, por conseguinte, dizemos que a altura de uma rvore vazia negativa e vale -1.

Representao em C Podemos definir um tipo para representar uma rvore binria. Vamos considerar que a informao a ser armazenada so valores de caracteres simples. Vamos inicialmente discutir como podemos representar uma estrutura de rvore binria em C. Que estrutura podemos usar para representar um n da rvore? Cada n deve armazenar trs informaes: a informao propriamente dita, no caso um caractere, e dois ponteiros para as sub-rvores, esquerda e direita.

Representao em Cstruct arv { char info; struct arv* esq; struct arv* dir; }; typedef struct arv Arv; Da mesma forma que uma lista encadeada representada por um ponteiro para o primeiro n, a estrutura da rvore como um todo representada por um ponteiro para o n raiz.

Criando rvoresArv* inicializa(void) { return NULL; } Arv* cria(char c, Arv* sae, Arv* sad) {Arv* p=(Arv*)malloc(sizeof(Arv)); p->info = c; p->esq = sae; p->dir = sad; return p;

}

rvore Vaziaint vazia(Arv* a) { return a==NULL; }

Exemplo Exemplo: Usando as operaes inicializa e cria, crie uma estrutura que represente a seguinte rvore.

Exemplo/* sub-rvore com 'd' */ Arv* a1= cria('d',inicializa(),inicializa()); /* sub-rvore com 'b' */ Arv* a2= cria('b',inicializa(),a1); /* sub-rvore com 'e' */ Arv* a3= cria('e',inicializa(),inicializa()); /* sub-rvore com 'f' */ Arv* a4= cria('f',inicializa(),inicializa()); /* sub-rvore com 'c' */ Arv* a5= cria('c',a3,a4); /* rvore com raiz 'a'*/ Arv* a = cria('a',a2,a5 );

Exemplo

Alternativamente, a rvore poderia ser criada recursivamente com uma nica atribuio, seguindo a sua estrutura. Como isso pode ser feito?

ExemploArv* a = cria('a', cria('b', inicializa(), cria('d', inicializa(), inicializa()) ), cria('c', cria('e', inicializa(), inicializa()), cria('f', inicializa(), inicializa()) ) );

Exibe Contedo da rvorevoid imprime (Arv* a) { if (!vazia(a)){ printf("%c ", a->info); /* mostra raiz */ imprime(a->esq); /* mostra sae */ imprime(a->dir); /* mostra sad */ } } Como chamada essa forma de exibio? E para exibir na forma in-fixada? E na ps-fixada?

Liberando MemriaArv* libera (Arv* a){ if (!vazia(a)){ libera(a->esq); /* libera sae */ libera(a->dir); /* libera sad */ free(a); /* libera raiz */ } return NULL; }

Criao e LiberaoVale a pena notar que a definio de rvore, por ser recursiva, no faz distino entre rvores e sub-rvores. Assim, cria pode ser usada para acrescentar uma sub-rvore em um ramo de uma rvore, e libera pode ser usada para remover uma sub-rvore qualquer de uma rvore dada.

Criao e LiberaoConsiderando a criao da rvore feita anteriormente, podemos acrescentar alguns ns, com: a->esq->esq = cria('x', cria('y',inicializa(),inicializa()), cria('z',inicializa(),inicializa()) ); E podemos liberar alguns outros, com: a->dir->esq = libera(a->dir->esq); Deixamos como exerccio a verificao do resultado final dessas operaes.

Buscando um Elemento Essa funo tem como retorno um valor booleano (um ou zero) indicando a ocorrncia ou no do carcter na rvore.int busca (Arv* a, char c){ if (vazia(a)) return 0; /* no encontrou */ else return a->info==c ||busca(a->esq,c) ||busca(a->dir,c); }

Buscando um Elemento Podemos dizer que a expresso:return c==a->info || busca(a->esq,c) || busca(a->dir,c);

equivalente a:if (c==a->info) return 1; else if (busca(a->esq,c)) return 1; else return busca(a->dir,c);

rvores Genricas Como vimos, numa rvore binria o nmero de filhos dos ns limitado em no mximo dois. No caso da rvore genrica, esta restrio no existe. Cada n pode ter um nmero arbitrrio de filhos. Essa estrutura deve ser usada, por exemplo, para representar uma rvore de directrios. Supor que no h rvore vazia.

Exemplo

Representao em C Devemos levar em considerao o nmero de filhos que cada n pode apresentar. Se soubermos que numa aplicao o nmero mximo de filhos 3, podemos montar uma estrutura com 3 campos apontadores, digamos, f1, f2 e f3. Os campos no utilizados podem ser preenchidos com o valor nulo NULL, sendo sempre utilizados os campos em ordem. Assim, se o n n tem 2 filhos, os campos f1 e f2 seriam utilizados, nessa ordem, ficando f3 vazio.

Representao em CPrevendo um nmero mximo de filhos igual a 3, e considerando a implementao de rvores para armazenar valores de caracteres simples, a declarao do tipo que representa o n da rvore poderia ser:struct arv3 { char val; struct arv3 *f1, *f2, *f3; };

Exemplo

Problemas com Representao Como se pode ver no exemplo, em cada um dos ns que tem menos de trs filhos, o espao correspondente aos filhos inexistentes desperdiado. Alm disso, se no existe um limite superior no nmero de filhos, esta tcnica pode no ser aplicvel. O mesmo acontece se existe um limite no nmero de ns, mas esse limite ser raramente alcanado, pois estaramos tendo um grande desperdcio de espao de memria com os campos no utilizados. H alguma soluo para contornar tal problema?

SoluoUma soluo que leva a um aproveitamento melhor do espao utiliza uma lista de filhos: um n aponta apenas para seu primeiro (prim) filho, e cada um de seus filhos, excepto o ltimo, aponta para o prximo (prox) irmo. A declarao de um n pode ser:struct arvgen { char info; struct arvgen *prim; struct arvgen *prox; }; typedef struct arvgen ArvGen;

Exemplo da Soluo

Exemplo da Soluo Uma das vantagens dessa representao que podemos percorrer os filhos de um n de forma sistemtica, de maneira anloga ao que fizemos para percorrer os ns de uma lista simples. Com o uso dessa representao, a generalizao da rvore apenas conceitual, pois, concretamente, a rvore foi transformada em uma rvore binria, com filhos esquerdos apontados por prim e direitos apontados por prox.

Criao de uma rvoreGenArvGen* cria (char c) { ArvGen *a =(ArvGen *)malloc(sizeof(ArvGen)); a->info = c; a->prim = NULL; a->prox = NULL; return a; }

Insero Como no vamos atribuir nenhum significado especial para a posio de um n filho, a operao de insero pode inserir a sub-rvore em qualquer posio. Vamos optar por inserir sempre no incio da lista que, como j vimos, a maneira mais simples de inserir um novo elemento numa lista ligada.void insere (ArvGen* a, ArvGen* f) { f->prox = a->prim; a->prim = f; }

Exemplo Criao rvoreGen Com as funes cria e insere como construir a rvore abaixo?

Exemplo Criao rvoreGen/* cria ns como folhas */ ArvGen* a = cria('a'); ArvGen* b = cria('b'); ArvGen* c = cria('c'); ArvGen* d = cria('d'); ArvGen* e = cria('e'); ArvGen* f = cria('f'); ArvGen* g = cria('g'); ArvGen* h = cria('h'); ArvGen* i = cria('i'); ArvGen* j = cria('j'); ... /* monta a hierarquia */ insere(c,d); insere(b,e); insere(b,c); insere(i,j); insere(g,i); insere(g,h); insere(a,g); insere(a,f); insere(a,b);

Impresso (pr-ordem)void imprime (ArvGen* a) { ArvGen* p; printf("%c\n",a->info); for (p=a->prim; p!=NULL; p=p->prox) imprime(p); }

Busca de Elementoint busca (ArvGen* a, char c) { ArvGen* p; if (a->info==c) return 1; else { for (p=a->prim; p!=NULL; p=p->prox) { if (busca(p,c)) return 1; } } return 0; }

Liberao de MemriaO nico cuidado que precisamos tomar na programao dessa funo a de liberar as subrvores antes de liberar o espao associado a um n (isto , usar ps-ordem).

Liberao de Memriavoid libera (ArvGen* a){ ArvGen* p = a->prim; while (p!=NULL) { ArvGen* t = p->prox; libera(p); p = t; } free(a); }

Capitulo IV - Ordenao

Docente: Dikiefu Fabiano, Msc

Sumrio4. Ordenao Interna 4.1 Ordenao por Seleco 4.2 Ordenao por Insero 4.3 Shellsort 4.4 Quicksort 4.5 Heapsort

148

Introduo - Conceitos Bsicos Ordenar: processo de rearranjar um conjunto de objectos em uma ordem ascendente ou descendente. A ordenao visa facilitar a recuperao posterior de itens do conjunto ordenado. A maioria dos mtodos de ordenao baseada em comparaes das chaves. Existem mtodos de ordenao que utilizam o princpio da distribuio. Notao utilizada nos algoritmos: Os algoritmos trabalham sobre os registos de um arquivo. Cada registo possui uma chave utilizada para controlar a ordenao. Podem existir outros componentes em um registo.

149

Conceitos bsicosUm mtodo de ordenao estvel se a ordem relativa dos itens com chaves iguais no se altera durante a ordenao. Alguns dos mtodos de ordenao mais eficientes no so estveis. A estabilidade pode ser forada quando o mtodo noestvel. Sedgewick (1988) sugere agregar um pequeno ndice a cada chave antes de ordenar, ou ento aumentar a chave de alguma outra forma.

150

Classificao dos mtodos de ordenao1. Ordenao interna: arquivo a ser ordenado cabe todo na memria principal. 2. Ordenao externa: arquivo a ser ordenado no cabe na memria principal. Diferenas entre os mtodos: Em um mtodo de ordenao interna, qualquer registo pode ser imediatamente cessado. Em um mtodo de ordenao externa, os registos so cessados sequencialmente ou em grandes blocos.

151

Classificao dos mtodos de ordenao interna Mtodos simples: Adequados para pequenos arquivos. Produzem programas pequenos. Mtodos eficientes: Adequados para arquivos maiores. Usam menos comparaes. As comparaes so mais complexas nos detalhes. Mtodos simples so mais eficientes para pequenos arquivos.

152

Ordenao por SelecoUm dos algoritmos mais simples de ordenao. Algoritmo: Seleccione o menor item do vector. Troque-o com o item da primeira posio do vector. Repita essas duas operaes com os n 1 itens restantes, depois com os n 2 itens, at que reste apenas um elemento.

As chaves em negrito sofreram uma troca entre si.153

Ordenao por Selecovoid selectionSort(int vector[],int tam) { int i, j, min, aux; for(i=0; i v[i+1] ) { swapbubble( v, i ); } } } }

Mtodo de ordenao Bolha com ordenao de strings. void bubble(int v[], int qtd){ int i, trocou; char aux; do { qtd--; trocou = 0; for(i = 0; i < qtd; i++) if(strcasecmp(v[i],v[i + 1])>0) { strcpy(aux, v[i]); strcpy(v[i], v[i + 1]); strcpy(v[i + 1], aux); trocou = 1; } }while(trocou==1); }

Cdigo da ordenao SelectionSort com strings void ordenar_seleccao() { int j; for(i=0; i key && i >= 0) { vector[i+1] = vector[i]; --i; } vector[i+1] = key; } }

A colocao do item no seu lugar apropriado na sequncia destino realizada movendo-se itens com chaves maiores para a direita e ento inserindo o item na posio deixada vazia.162

Ordenao por InseroConsideraes sobre o algoritmo: O processo de ordenao pode ser terminado pelas condies: Um item com chave menor que o item em considerao encontrado. O final da sequncia destino atingido esquerda. Soluo: Utilizar um registo sentinela na posio zero do vector.163

Ordenao por Insero O nmero mnimo de comparaes e movimentos ocorre quando os itens esto originalmente em ordem. O nmero mximo ocorre quando os itens esto originalmente na ordem reversa. o mtodo a ser utilizado quando o arquivo est quase ordenado. um bom mtodo quando se deseja adicionar uns poucos itens a um arquivo ordenado, pois o custo linear. O algoritmo de ordenao por insero estvel.

164

ShellsortProposto por Shell em 1959. uma extenso do algoritmo de ordenao por insero. Problema com o algoritmo de ordenao por insero: Troca itens adjacentes para determinar o ponto de insero. So efectuadas n 1 comparaes e movimentaes quando o menor item est na posio mais direita no vector. O mtodo de Shell contorna este problema permitindo trocas de registos distantes um do outro.

165

Shellsort Os itens separados de h posies so rearranjados. Todo h-simo item leva a uma sequncia ordenada. Tal sequncia dita estar h-ordenada. Exemplo de utilizao:

Quando h = 1 Shellsort corresponde ao algoritmo de insero.166

Shellsort Como escolher o valor de h: Sequncia para h: h(s) = 3h(s 1) + 1, para s > 1 h(s) = 1, para s = 1. Knuth (1973, p. 95) mostrou experimentalmente que esta sequncia difcil de ser batida por mais de 20% em eficincia. A sequncia para h corresponde a 1, 4, 13, 40, 121, 364, 1.093, 3.280, . . .

167

Shellsortvoid shellsort ( Int v [ ] , int n) { int i,j,x,h = 1; do h = h *3 + 1; while (h < n) ; do { h /= 3; for ( i = h + 1; i x > 0) { v[ j ] = v[ j h] ; j = h; i f ( j pivot) { j--; k--; t = array[i]; array[i] = array[j]; array[j] = array[k]; array[k] = t;

} else {j--; swap(array[i], array[j]); } } i--; swap(array[begin], array[i]); if (i - begin > 1) sort(array, begin, i); if (end - k > 1) sort(array, k, end); }

Lembrando que quando voc for chamar a funo recursiva ter que chamar a mesma da seguinte forma ordenar_quicksort(0,n-1). O 0(zero) serve para o incio receber a posio zero do vector e o fim ser o tamanho do vector -1.

void ordenar_quicksort(int ini, int fim) { int i = ini, f = fim; char pivo[50]; strcpy(pivo,vector[(ini+fim)/2]); if (i a[filho])) filho++; if (a[filho] > t) { a[pai] = a[filho]; pai = filho; filho = pai*2 + 1; } else break; } a[pai] = t; } }188

HeapsortAlgoritmo:

Os itens de v[4] a v[7] formam um heap.O heap estendido para a esquerda (esq = 3), englobando o item v[3], pai dos itens v[6] e v[7]. A condio de heap violada: O heap refeito trocando os itens D e S. O item R incluindo no heap (esq = 2), o que no viola a condio de heap. O item O incluindo no heap (esq = 1). A Condio de heap violada: O heap refeito trocando os itens O e S, encerrando o processo.189

HeapsortExemplo da operao de aumentar o valor da chave do item na posio i:

O tempo de execuo do procedimento AumentaChave em um item do heap O(log n).190

Construo de HeapAlgoritmo:

1. Construir o heap. 2. Troque o item na posio 1 do vector (raiz do heap) com o item da posio n. 3. Use o procedimento Refaz para reconstituir o heap para os itens v[1], v[2], . . . , v[n 1]. 4. Repita os passos 2 e 3 com os n 1 itens restantes, depois com os n 2, at que reste apenas um item.

HeapsortExemplo de aplicao do Heapsort :

1 S R O N E D A

2 R N N E D A D

3 O O A A A E

4 E E E D N

5 N D D O

6 7 A D A S R

O caminho seguido pelo procedimento Refaz para reconstituir a condio do heap est em negrito. Por exemplo, aps a troca dos itens S e D na segunda linha da Figura, o item D volta para a posio 5, aps passar pelas posies 1 e 2.

Referncias1. Levitin, Anany Introduction to the design and analysis of algorithm Addison-Wesley 2003 2. Pedro Neto, Joo Programao, algoritmo e estrutura de dados escola editora 2008 3. Damas, Lus Programao em C 4. Ziviani, Nivio e Botelho, Fabiano Cupertino, Projecto de Algoritmos com implementao em Pascal e C editora Thomson, 2007 5. http://www.icmc.usp.br/~sce182/arvore.html 6. http://w3.ualg.pt/~hshah/ped 7. http://www.liv.ic.unicamp.br/~bergo/mc202/