350 likes | 468 Views
11.3.4 – Encadeamento circular No encadeamento apresentado, seja p um ponteiro apontando para um determinado nó Com sucessivas execuções do comando p = p-> prox ; pode-se percorrer a lista Mas, com esse comando não se chega a nós anteriores. p. Lista encadeada circular:
E N D
11.3.4 – Encadeamento circular • No encadeamento apresentado, seja p um ponteiroapontando para um determinado nó • Com sucessivas execuções do comando p = p->prox;pode-se percorrer a lista • Mas, com esse comando não se chega a nós anteriores p
Lista encadeada circular: • O ponteiro do último nó aponta para o nó-líder, ao invés de apontar para NULL • Para determinadas aplicações, os conceitos de primeiro, segundo, ... e último elementos da lista não têm relevância • Então pode-se eliminar o nó-líder, sendo um ponteiro para qualquer nó do encadeamento suficiente para identificar a lista
11.3.5 – Listas duplamente encadeadas • Há aplicações de listas lineares que exigem frequentes percursos nos dois sentidos • Pode-se acrescentar a cada nó mais um campo do tipo ponteiro (prev), com a finalidade de apontar para o nó anterior no encadeamento
Declarações: typedef char nome[16]; typedef struct nohnoh; typedefnoh *lista; typedefnoh *posicao; struct noh { nome elem; noh*prev, *prox; };
Inserção de um nó na posição p: p Nó a ser inserido
Nó a ser removido • Remoção do um nó da posição p: p
Exercícios 11.3: • Escrever um subprograma que receba como argumentos uma lista linear L encadeada por ponteiros e que elimine dessa lista os elementos em duplicata. Escrever também um programa principal para testar devidamente essa função • Escrever um subprograma que receba como argumentos dois ponteiros L1 e L2, apontando cada um para um encadeamento distinto de estruturas, ambos iniciados por um nó-líder, e que efetue uma troca de estruturas nesses encadeamentos. No encadeamento de L1 devem ficar todas as estruturas cujos elementos guardados sejam números ímpares e no encadeamento de L2 aquelas contendo números pares. Esse subprograma não deve alocar nenhuma nova estrutura, nem deixar nenhuma estrutura já existente fora dos encadeamentos, nem trocar o valor guardado em nenhuma estrutura. Escrever um programa principal para testar devidamente o referido subprograma
Escrever um subprograma que receba como argumento uma lista L encadeada circular sem nó-líder e que inverta seu encadeamento, conforme apresentado na figura abaixo Importante: o subprograma não deve deletar, nem criar qualquer nó, nem mudar o conteúdo de nenhum nó. Escrever um programa principal para testar devidamente o referido subprograma.
Capítulo XI – Noções de Estruturas de Dados 11.1 – Importância de boa estruturação de informações 11.2 – Modelos de armazenamento de informações 11.3 – Listas lineares encadeadas 11.4 – Pilhas e filas 11.5 – Árvores
11.4 – Pilhas e Filas 11.4.1 – Listas lineares com disciplina de acesso • As listas lineares gerais admitem inserção e remoção de elementos em qualquer posição • Existem listas lineares especiais que admitem inserção e remoção somente em suas duas extremidades • São elas as pilhas, as filas e os deques • Pilhas: inserção e remoção em apenas uma das extremidades • Filas: inserção numa extremidade e remoção na outra • Deques: as duas operações nas duas extremidades
11.4.2 – Pilhas • O último a entrar é o primeiro a sair (LIFO – last in first out) Podem usar estrutura contígua e encadeada A seguir, uma representação gráfica da estrutura encadeada
Estrutura encadeada para pilhas: Declarações: Operações típicas: typedef struct noh noh; typedef noh *pilha; struct noh { int elem; noh *prox; }; pilha P; Empilhar um elemento Desempilhar o elemento do topo Copiar o elemento do topo Esvaziar Verificar se está vazia
Utilidade de pilhas: • Cálculo de expressões • Gerenciamento da área de dados das funções na execução de um programa • Algoritmos para árvores e grafos • Eliminação de recursividade
11.4.3 – Filas • O primeiro a entrar é o primeiro a sair (FIFO – first in first out) • Podem usar estrutura contígua e encadeada • A seguir, uma representação gráfica da estrutura encadeada
Estrutura encadeada para filas: Declarações: Operações típicas: typedef struct noh noh; typedef struct fila fila; struct noh {int elem; noh *prox;}; struct fila {noh *fr, *tr;}; fila F; Entrar com um elemento Remover o elemento da frente Copiar o elemento da frente Esvaziar Verificar se está vazia
Utilidade de filas: • Gerenciamento da utilização de recursos computacionais pelo sistema operacional • Software de controle de saída e chegada de aeronaves em aeroportos • Algoritmos para árvores e grafos • Circuitos eletrônicos
Capítulo XI – Noções de Estruturas de Dados 11.1 – Importância de boa estruturação de informações 11.2 – Modelos de armazenamento de informações 11.3 – Listas lineares encadeadas 11.4 – Pilhas e filas 11.5 – Árvores
11.5 – Árvores 11.5.1 – Definições Forma natural de apresentação
Cada elemento é armazenado em um nó • Sobre os nós existe uma hierarquia paterna • Entre alguns pares, existe a relação “pai de” A é pai de B, C e D D é pai de H C é pai de F e G etc.
Raiz: nó de máxima hierarquia de uma árvore • Abaixo, A é a raiz • Cada nó tem um e apenas um pai (exceto a raiz) • Cada nó tem zero ou mais filhos • Um nó não pode ter um ancestral como filho • Exemplo: I não pode ser pai de H, D ou A
Definição recursiva de Árvore: • Um único nó é por si mesmo uma árvore; ele é a raiz dessa árvore • Sejam A1, A2, ... , Ak, árvores de raízes n1, n2, ..., nk, respectivamente e n um nó não pertencente a nenhuma delas • Fazendo n pai de n1, n2, ..., nk, obtém-se uma nova árvore n n1 n2 n3 nk A1 A2 A3 Ak
Mostrar que a seguinte figura é uma árvore: A H G F D C E B K J I
I, J e K são por si só árvores; fazendo H pai das raízes I, J e K, obtém-se nova árvore • F, G e E são por si só árvores; fazendo B pai de E, C pai de F e G,e D pai de H, obtém-se novas árvores • Fazendo A pai de B, C e D, obtém-se nova árvore A H G F D C E B K J I
Folha: nó sem filhos; abaixo, E, F, G, I, J e K são folhas • Irmãos: filhos de um mesmo nó; abaixo: B, C e D são irmãos; F e G são irmãos; I, J e K são irmãos • Floresta: conjunto de zero ou mais árvores disjuntas
Forma parentética: forma de representar uma árvore em que cada elemento é um caractere • Coloca-se entre parêntesis: primeiramente a raiz, depois as formas parentéticas das sub-árvores da raiz ordenadas da esquerda para a direita (recursividade): (A (B (E)) (C (F) (G)) (D (H (I) (J) (K))) )
Forma parentética: definição recursiva • Sendo c um caractere genérico, (c) é uma forma parentética correta • Se α1, α2, α3, ... αn, são formas parentéticas corretas (n > 0), então (c α1α2α3 ... αn) também é
Ordenação ou caminhamento em pré-ordem: é uma forma de ordenar todos os nós de uma árvore • Primeiramente aparece a raiz n • Seguida dos nós de A1 em pré-ordem • Seguidos dos nós de A2 em pré-ordem, etc. • Até os nós de Akem pré-ordem É também uma definição recursiva n n1 n2 n3 nk A1 A2 A3 Ak
Exemplo: pré-ordem da árvore abaixo: A B E C F G D H I J K
11.5.2 – Estruturas de dados para árvores • Uma árvore também pode ser armazenada num vetor ou num encadeamento de estruturas • Seja a árvore já vista:
A) Estrutura contígua (vetor) • Nós são índices do vetor • Os nós estão em pré-ordem
Declarações: typedef int noh; typedef struct celulacelula; typedef struct arvorearvore; struct celula {char info; int nfilhos, pai;} struct arvore {celula Espaco[100]; int nnos;} noh n1, n2, n3; arvore A1, A2, A3; Nesta estrutura, os algoritmos são geralmente ineficientes
info pai celula fesq idir Declarações: typedef struct celulacelula; typedefcelula *noh; typedefcelula *arvore; struct celula {charinformacao; noh pai, fesq, idir;}; noh n1, n2, n3; arvore A1, A2, A3; • Nós são ponteiros para células • Para ilustrar, a seguir, comandos para construir a árvore ao lado
A C G E F A arvore A; noh x, y; A = (noh) malloc (sizeof (celula)); A->info = 'A'; A->pai = A->idir = NULL; A->fesq = (noh) malloc (sizeof (celula)); x = A->fesq; x->info = 'B'; x->pai = A; x->fesq = (noh) malloc (sizeof (celula)); x->idir = (noh) malloc (sizeof (celula)); x->fesq->info = 'E'; x->fesq->pai = x; x->fesq->fesq = x->fesq->idir = NULL; x = x->idir; x->info = 'C'; x->pai = A; x->idir = NULL; x->fesq = (noh) malloc (sizeof (celula)); y = x->fesq; y->info = 'F'; y->pai = x; y->fesq = NULL; y->idir = (noh) malloc (sizeof (celula)); y->idir->info = 'G'; y->idir->pai = x; y->idir->fesq = y->idir->idir = NULL; B y x y x x
Os comandos anteriores formam apenas esta árvore em particular Em CES-11 serão vistos algoritmos gerais de formação de árvores A G A E C F B