Baixe o app para aproveitar ainda mais
Prévia do material em texto
Listas Filas Pilhas Estrutura de Dados *agrupamento *organização *ordenação Lista, filas, pilhas, árvores e grafos Complexidade algorítmica Letra O representa o custo máximo que o algorítimo gera. N Custo Mínimo Máximo Tipo Operações envolvidas (tempo) O(n) Listas log(n) Árvores O (1) Tabela Hash Lista Estática – Estrutura Física PROJETO CODEBLOCKS: Aula_17_08 Desvantagem: - Tamanho fixo definido, o que gera pouca flexibilidade; Qt Me Fcp Fcm ? ? ? ? vDados[TAM_LISTA]; #define TAM_LISTA 4 TAM_LISTA - #define TAM_LISTA 4 É a quantidade de elementos que a lista poderá ter, lembrando que a lista é estática, ou seja, isso não poderá mudar em tempo de execução. Qt - int QtdeElementos; Irá armazenar a quantidade de elementos presentes na lista. Me - int MaxElementos; Irá armazenar o número máximo de elementos suportado pela lista. vDados – void vDados[TAM_LISTA]; Representa o vetor de dados que a lista conterá, é do tipo void pois não é possível saber o tipo de dados que a lista vai receber, uma vez que ela é genéria. Fcm - int (* FncComparar)( void Elemento, void ChaveBusca); Ponteiro para função que recebe dois parâmetros e é utilizada para comparar dois itens da lista. Nota-se que os parâmetros “Elemento” e “ChaveBusca” são do tipo void, pois a lista é genérica e não sabemos com qual tipo de dado ela trabalhará. Essa função recebe um elemento da lista e uma chave de busca para que possa ser possível efetuar a comparação entre esses elementos. Fcp - int (*FncCopiar)(void Origem, void Destino); Ponteiro para função utilizada para copiar um item da lista. Nota-se que os parâmetros “Origem” e “Destino” são do tipo void, pois a lista é genérica e não sabemos com qual tipo de dado ela trabalhará. Essa função recebe um dado origem que será copiado no dado destino. Lista Estática – Estrutura da lista (Struct) ListaEstatica.h Lista Estática – Funções da lista A lista deve possuir algumas funções básicas para seu funcionamento, são elas: void InicializaLista(ListaEstatica *ptrLista, int (*ptrFncComparar)(void *ptrElemento, void *ptrChaveBusca), int (*ptrFncCopiar)(void *ptrDestino, void *ptrOrigem)); Essa função irá inicializar nossa lista, ou seja, prepará-la para o uso, no caso iniciar as variáveis do struct e fazer com que os ponteiros pras funções comparar e copiar apontem para as funções certas. Essa função recebe como parâmetro um ponteiro para lista (*ptrLista) pois não podemos modificar a lista diretamente, e também recebe os ponteiros para as funções de comparação e cópia. int Consulta(ListaEstatica *ptrLista, void *ptrChaveBusca); Essa função servirá para buscar elementos dentro da lista. Ela receberá por parâmetro um ponteiro para lista e um ponteiro para chave de busca que será usado para identificar o elemento. int ConsultaPosicao(ListaEstatica *ptrLista, int idxPosicao); Essa função funciona como a primeira porém ao invés de receber a chave de busca ela já vai receber diretamente o índice do elemento procurado. int Inclui(ListaEstatica *ptrLista, void *ptrNovoElemento); Essa função servirá para incluirmos elementos na lista (dentro de vDados). Ela recebe um ponteiro para lista e um ponteiro para o novo elemento que será adicionado. Em uma lista o novo elemento entra ao final. int IncluiPosicao(ListaEstatica *ptrLista, int idxPosicao); Essa função servirá para incluirmos elementos na lista (dentro de vDados), diferente da outra função, nessa poderemos incluir o elemento em qualquer posição da lista, por isso ela também recebe por parâmetro o índice da posição desejada. ListaEstatica.h int Altera(ListaEstatica *ptrLista, void *ptrNovoElemento, void *ptrChaveBusca); Essa função servirá para alterarmos um item da lista. Ela recebe os seguintes parâmetros: um ponteiro para lista, um ponteiro para o novo elemento e um ponteiro para a chave de busca. int AlteraPosicao(ListaEstatica *ptrLista, void *ptrNovoElemento, int idxPosicao); Essa função servirá para alterarmos um item determinado pelo índice. Ela recebe os seguintes parâmetros: um ponteiro para lista, um ponteiro para o novo elemento e o índice do elemento que será alterado. void *Exclui(ListaEstatica *ptrLista, void *ptrChaveBusca); Essa função servirá para excluir um elemento da lista, por meio de sua chave de busca. Ela recebe por parâmetro um ponteiro para lista e um ponteiro para chave de busca. void *ExcluiPosicao(ListaEstatica *ptrLista, int idxPosicao); Essa função servirá para excluir um elemento da lista, por meio de um índice. Ela recebe por parâmetro um ponteiro para lista e o índice da posição. ListaEstatica.h Me Fcp Qt Pilha Estática – Estrutura Física (LiFo – Last in First out) ? ? ? ? PROJETO CODEBLOCKS: Aula_02_09_PilhaEst Qt - int QtdeElementos Irá armazenar a quantidade de elementos presentes na lista. Me - int MaxElementos Irá armazenar o número máximo de elementos suportado pela lista. Fcp - int FncCopiar() Função utilizada para copiar um item da lista vDados[TAM_PILHA]; #define TAM_PILHA 4 Qt Me Fcp Fila Estática – Estrutura Física (FiFo – First in First out) Organização lógica da fila circular: Para que a fila consiga funcionar de forma circular devemos aplicar o seguinte incremento idx = (idx + 1)%MaxElementos ? ? ? ? PROJETO CODEBLOCKS: Aula_09_09_FilaEst Qt - int QtdeElementos Irá armazenar a quantidade de elementos presentes na lista. Me - int MaxElementos Irá armazenar o número máximo de elementos suportado pela lista. Fcp - int FncCopiar() Função utilizada para copiar um item da lista EXERCÍCIO 7 13 10 30 Pilha (recursos) c1 c2 c3 c4 Fila (consumo) Relação quantidade x consumidor 1 4 20 50 Descrição do problema: 1 - Produção (insere pilha) 2 - Consumo (insere fila) 3 - Atender(executar alterações fila/pilha) Primeiro elemento da fila irá interagir com o topo da pilha, se o topo da pilha satisfazer o pedido do primeiro elemento da fila ele será “removido da fila”, caso contrário o topo da lista será removido para que o segundo elemento (de cima pra baixo) tente satisfazer o pedido do primeiro elemento da fila. DESAFIO: refazer o exercício usando uma pilha de filas para representar diferentes produtos cn n n PROJETO CODEBLOCKS: Exercicio_09_09_ListaDinamica Lista Estática → Vetores (tamanho fixo) ( SUPER / SUB ) - Dimensionamento do vetor Falta de espaço Consome memória desnecessária * No nosso caso o problema é minimizado por estarmos usando vetores de ponteiros Problema das listas Estáticas FCopiar FCompararQtdeElementos MaxElementos 1 2 3 4 PROJETO CODEBLOCKS: Aula_16_09_ListaDinamica Lista Dinâmica → alocação de memória Qt Me *pi Fcm Fcp*pf 1 2 Nó Nó Nó vDados[TAM_LISTA] Lista Dinâmica – Estrutura Física Vantagem + Solucionar o problema das listas estáticas Desvantagens - Não há acesso direto ao nó do índice / posição x - Maior consumo memória para referências Qt Me *ptrI Fcm Fcp*ptrF 1 2 Nó Descritor Descritor É outra struct (ListaDinamica) Qt – int QtdeElementos Me – int MaxElementos *ptrI – No ptrInicio; *ptrF – No ptrFim; Fcm – int ptrFncComparar Fcp – int ptrFncCopiar Nós São estruturas (struct) *NoA Da *NoP *NoA – void* ptrNoAnt Endereço para o nó anterior. Da – void* Dado Endereço para o dado que o nó vai armazenar. *NoP – void* ptrNoProx Endereço para o próximo nó. PROJETO CODEBLOCKS: Aula_16_09_ListaDinamica Nó Nó Nó Nó PROJETO CODEBLOCKS: Aula_16_09_ListaDinamica Lista Dinâmica – Funcionamento dos nós Qt Me *ptrI Fcm Fcp*ptrF NULL; 0 Lista vazia PROJETO CODEBLOCKS: Aula_16_09_ListaDinamica Lista Dinâmica – Funcionamento dosnós Qt Me *ptrI Fcm Fcp*ptrF NULL; ? 1 - Surge o dado PROJETO CODEBLOCKS: Aula_16_09_ListaDinamica Lista Dinâmica – Funcionamento dos nós Qt Me *ptrI Fcm Fcp*ptrF NULL; ? 2 - Cria-se o nó *NoA *Da *NoP PROJETO CODEBLOCKS: Aula_16_09_ListaDinamica Lista Dinâmica – Funcionamento dos nós Qt Me *ptrI Fcm Fcp*ptrF NULL; ? 3 – Referência o dado para o ptrDado do nó *NoA *Da *NoP PROJETO CODEBLOCKS: Aula_16_09_ListaDinamica Lista Dinâmica – Funcionamento dos nós Qt Me *ptrI Fcm Fcp*ptrF NULL; ? 4 - Seta o ptrNoProx como nulo *NoA *Da *NoP NULL; PROJETO CODEBLOCKS: Aula_16_09_ListaDinamica Lista Dinâmica – Funcionamento dos nós Qt Me *ptrI Fcm Fcp*ptrF NULL; ? 5 – Verifica se a lista esta vazia if (!ptrLista->QtdeElementos) /* nesse caso será true */ *NoA *Da *NoP NULL; PROJETO CODEBLOCKS: Aula_16_09_ListaDinamica Lista Dinâmica – Funcionamento dos nós Qt Me *ptrI Fcm Fcp*ptrF NULL; ? 6 – Seta o ptrNoAnt para null, pois não há elementos antes do primeiro *NoA *Da *NoP NULL; NULL; PROJETO CODEBLOCKS: Aula_16_09_ListaDinamica Lista Dinâmica – Funcionamento dos nós Qt Me *ptrI Fcm Fcp*ptrF NULL; ? 6 - Seta o início da lista para o Nó *NoA *Da *NoP NULL; NULL; PROJETO CODEBLOCKS: Aula_16_09_ListaDinamica Lista Dinâmica – Funcionamento dos nós Qt Me *ptrI Fcm Fcp*ptrF ? 6 – Atualiza o campo ptrFim da lista para o último elemento. Incrementa a quantidade de elementos *NoA *Da *NoP NULL; ++ NULL; PROJETO CODEBLOCKS: Aula_16_09_ListaDinamica Lista Dinâmica – Funcionamento dos nós Qt Me *ptrI Fcm Fcp*ptrF ? 0 – Lista com 1 elemento *NoA *Da *NoP NULL; NULL; PROJETO CODEBLOCKS: Aula_16_09_ListaDinamica Lista Dinâmica – Funcionamento dos nós Qt Me *ptrI Fcm Fcp*ptrF ? 1 – Surge outro dado *NoA *Da *NoP NULL; ?NULL; PROJETO CODEBLOCKS: Aula_16_09_ListaDinamica Lista Dinâmica – Funcionamento dos nós Qt Me *ptrI Fcm Fcp*ptrF ? 2 – Cria-se outro nó *NoA *Da *NoP NULL; ? *NoA *Da *NoP NULL; PROJETO CODEBLOCKS: Aula_16_09_ListaDinamica Lista Dinâmica – Funcionamento dos nós Qt Me *ptrI Fcm Fcp*ptrF ? 3 – Referência o dado para o campo ptrDado do novo nó *NoA *Da *NoP NULL; ? *NoA *Da *NoP NULL; PROJETO CODEBLOCKS: Aula_16_09_ListaDinamica Lista Dinâmica – Funcionamento dos nós Qt Me *ptrI Fcm Fcp*ptrF ? 4 – Campo ptrNoAnt = ptrLista- >ptrFim Ou seja, o campo anterior do novo nó vai receber o nó anterior a ele. *NoA *Da *NoP NULL; ? *NoA *Da *NoP NULL; PROJETO CODEBLOCKS: Aula_16_09_ListaDinamica Lista Dinâmica – Funcionamento dos nós Qt Me *ptrI Fcm Fcp*ptrF ? 5 – ptrLista→ptrFim→ptrNoProx = ptrNoAux; Ou seja, o campo próximo do nó anterior recebe o novo nó *NoA *Da *NoP NULL; ? *NoA *Da *NoP PROJETO CODEBLOCKS: Aula_16_09_ListaDinamica Lista Dinâmica – Funcionamento dos nós Qt Me *ptrI Fcm Fcp*ptrF ? 6 – ptrLista→ptrFim = ptrNoAux; Atualiza o campo ptrFim da lista. Incrementa a quantidade de elementos da lista *NoA *Da *NoP NULL; ++ ? *NoA *Da *NoP PROJETO CODEBLOCKS: Aula_16_09_ListaDinamica Lista Dinâmica – Funcionamento dos nós Qt Me *ptrI Fcm Fcp*ptrF *NoA *Da *NoP *NoA *Da *NoP *NoA *Da *NoP *NoA *Da *NoP ? ? ? ? Lista estática A lista estática é usada para armazenar dados de um determinado tipo, ela possui um número Máximo de elementos e também um índice para controle deles. A contiguidade é de extrema Importância para que a lista mantenha sua estrutura. A lista Inserindo elemento no meio uma lista dinâmica: Será necessário: ● Criar o nó ● Referenciar o dado C para o campo dado do nó ● Verificar se a lista está vazia ● Fazer seu campo Anterior apontar para o próximo de A ● Seu ponteiro próximo para o anterior de B ● e após isso o Campo próximo de A deve apontar para o anterior de C(ou pro nó em que C está) ● e o campo Anterior de B deve apontar para o próximo de C ● o campo anterior de A agora é null ● campo próximo de B null Adicionando elementos em uma lista estática: Apenas desloca o PROJETO CODEBLOCKS: Aula_05_10_ExercicioLD main.c ListaDinamica c; c = ExcluiTudo(parâmetros); /* Retorno da função (apenas o descritor é retornado com seus devidos ponteiros) */ ListaDinamica ExcluiTudo(ListaDinamica *ptrLista, void *ptrChaveBusca); ListaDinamica d; return d; Função que retorna uma ListaDinamica d. A única coisa que será retornada é struct ListaDinamica Qt Me *PI Fcm Fcp*PFQt Me *ptrI Fcm Fcp*ptrF Nó Descritor Nó Nó PROJETO CODEBLOCKS: Aula_28_09_PilhaDinamica Qt Me Fcm Fcp 1 *ptrDado ? Pilha Dinâmica – Estrutura Física *ptrProx *ptrDado ?*ptrProx *ptrDado ?*ptrProx Cria o nó, o campo dado aponta pro A, o ptrProx recebe o topo e o topo recebe ele. Qt Me *PI Fcm Fcp*PF 1 2 Da *NoP Da *NoP Da *NoP Da *NoP ? ? ? ? Fila Dinâmica – Estrutura Física PROJETO CODEBLOCKS: Aula_30_09_FilaDinamica Cria o nó, seta o dado pro elemento, seta o próximo para nulo, seta inicio e fim para o nó criado (para primeiro elemento). Incrementa um; Inserir o outro dado, cria um nó, o dado aponta pra b, não cai no if pois já existe um elemento, ptrprox = noaux, ptrfila→ptrfim = noaux APS 1 – ESTRUTURA DE DADOS Lista Produtos / Estoque Lista de compra do usuário e partir delas serão geradas sub-listas. A cada novo cliente zera a lista do cliente anterior para criar a lista do cliente atual. 2 – Poder alterar o estoque a qualquer momento, o que pode implicar um novo produto ou apenas atualizar a quantidade presente no estoque. 3 – Ler a lista de compra dos clientes (mesmo do 2) 4 – O cliente poderá alterar a lista de compras antes de confirmar a compra “Deseja alterar a lista de comprar” “não” Após isso ele não pode mais modificar a lista pois foi confirmada a lista de compra. Struct Produto{ Char[10] nome; Int quantidade; Int precoUnitario; } EXERCÍCIO – LISTA DINÂMICA Excluir e retornar todos os elementos com uma chave de busca qualquer Duas maneiras: - utilizando rotinas prontas - reescrevendo todo o código ListaDinamica ExcluiTudo(ListaDinamica *ptrLista, void *ptrChaveBusca); ListaDinamica d; ListaDinamica *ExcluiTudo(ListaDinamica *ptrLista, void *ptrChaveBusca); ListaDinamica *p = (ListaDinamica *) malloc(sizeof(ListaDinamica)); int ExcluiTudo(ListaDinamica *ptrListaEntrada, void *ptrChaveBusca, ListaDinamica *ptrListaSaida); (pode ser void) Qt Me *ptrI Fcm Fcp*ptrF *NoA *Da *NoP *NoA *Da *NoP *NoA *Da *NoP *NoA *Da *NoP ? ? ? ? PROJETO CODEBLOCKS: Aula_16_09_ListaDinamica Lista Dinâmica – Funcionamento dos nós Recursão A recursão é uma ferramenta computacional que foi inspirada no comportamento de alguns elementos da natureza. Ex: A casca de um caracol, uma folha de árvore ou seus galhos, etc. Quando se utiliza recursão a pilha do sistema é usada para auxiliar no funcionamento da função. A condição (if) vem sempre antes da chamada recursiva. Vantagens: + Código mais simples e enxuto + Facilidade de implementação de problemas complexos (I.A), simulação numérica, busca e ordenação em árvore binária etc. Desvantagens: - Maior complexidade para entender o código - Consumo de memória e processamento, pois a cada chamada de rotina, seu status deve ser armazenado na pilha do sistema. - Possível StackOverflow se possuir erros na implementação Observação: Sempre que puder usar iteração (for) ao invés de recursividade, use. Quando usar? Usa-se recursão quando parte do problema se assemelha ao todo. Mais exemplos dentro da computação: ● Cálculo de fatorial ● Sequência de Fibonacci Recursãoindireta Recursão direta (mais comum) F1 F2 F3 F1 F1 F2 F1 F2 F3 /* rotina escreve inteiros positivos menores que n */ void escreve(long n){ if(n <= 0) return; escreve(n -1); printf(“%d”, n); } Recursão direta exemplo de algorítimo: /* rotina escreve o fatorial de um número */ long fatorial(long n){ } /* rotina escreve o fatorial de um número usando iteração */ long fatorial(long n){ long fat = 1; while (n > 0){ fat = fat * n; n--; } return fat; } Exercícios Recursão ● Escrever um valor (decimal) nas Bases binária, octal e hexadecimal ● Escrever uma rotina pra Caminhar em String e escrever seu conteúdo ao contrário ● Escrever uma rotina recursiva para exibir os primeiros n termos da PA de razão q e termo inicial a1 (an = a1 + (n – 1) * r) ● Escrever uma rotina recursiva para exibir os primeiros n termos da PG de razão q e termo inicial a1 (an = a1 * q n-1) Implementar rotinas recursivas para DIV e MOD utilizando operações de subtração ● Escrever uma rotina para realizar busca em Strings, Listas e Árvores. ● Escrever uma rotina para realizar busca binária em uma lista linear estática ordenada ● Escrever uma rotina recursiva para inverter uma lista simplesmente encadeada dinâmica PROJETO CODEBLOCKS: Aula_19_10_Recursao Árvores Árvores AVL Árvores B Árvores são generalizações de listas ou podemos dizer que é um grafo conexo sem ciclos. Árvores AVL: são árvores que possuem uma diferença de no máximo 2 níveis entre os folhas e os outros elementos Árvores B: muito usada para buscas em disco (HD) Árvores possuem um direcionamento (da raiz para as folhas) Caminhamentos de árvores: Profundidade (recursividade/pilha): Utiliza recursividade e a pilha do sistema Amplitude (fila): Utiliza fila da seguinte forma: Visita o nó e adiciona seus filhos na fila Grafos Conceito Básico da Teoria de Grafos Um grafo é um conjunto de N nós, que possuem ligações/relações entre qualquer pares de nós (como uma árvore sem direcionamento) Os grafos podem ser representado por matrizes (arrumar desenho) 0 2 1 X X X X X X 0 1 2 0 1 2 Conceito Básico da Teoria de Grafos Um grafo é um conjunto de N nós, que possuem ligações/relações entre qualquer pares de nós (como uma árvore sem direcionamento) Os grafos podem ser representado por matrizes (arrumar desenho) A ordem do grafo é dada pelo número de vértices que ele possui. Grau de emissão: é o número de arestas que saem de um nó Grau de recepção: é o número de arestas que chegam a um nó Nó fonte: nós que possuem apenas grau de emissão e grau de recepção 0, ou seja, apenas saem arestas dele. Nó semidouro: nós que possuem apenas grau de recepção e grau de emissão 0, ou seja, apenas chegam arestas nele. Grafos parciais; Hipergrafo; Cadeia é uma sequências de quaisquer arestas adjacentes que ligam dois vértices (nós). Se o grafo não possuir orientação, pode-se obter o caminhamento para qualquer lado Cadeia elementar não passa duas vezes pelo mesmo vértice. Cadeia simples não passa duas vezes pela mesma aresta(arco). O comprimento de uma cadeia é o número de arestas (arcos) que compõe. Ciclo: uma cadeia simples fechada (vértice inicial é o mesmo que o vértice final, porém não exige orientação). Circuito: é um caminho simples e fechado (exige orientação). Grafo Conexo: há pelo menos uma cadeia ligando cada par de nós. Grafo Desconexo: há pelo menos um par de nós que não esta ligado. Redes: é um grafo composto por dois nós especiais, apenas um fonte e apenas um semidouro. Grafo planar: um grafo que pode ser representado de forma plana sem que suas arestas se cruzem. Busca em Grafos Caminha rofundidade (usando pilha)Ṕ Tamo um nó v qualquer Poe v na pilha dos nós a serem visitados Enquanto a pilha dos nós a serem visitados não estiver vazia Retira próximo nó a ser visitado da pilha (v = nó[topo] da pilha) Se v não estiver marcado Visita v Marca v Para cada nó w adjascente à v Põe w na pilha dos nós a serem visitados CaminhaProfundidadeRecursivo(arvore *pRaiz) Se v não estiver marcado Visita v Marca v Para cada nó w adjascente à v CaminhaProfundidadeRecursivo(pRaiz→ptr???) Tabela Hash Tabela Hash Não há ordenação, mas simplesmente organização dos dados / elementos f(chave) = calculo % n → garante que o endereço esta no intervalo [o … n -1] do vetor Chave + c C e N primos entre si (não ter divisores em comum, garante melhor espalhamento) Custo: O(1) *Utiliza vetor 0 | | | | | n-1 Elemento → aplico f (elemento.chave) → endereço na tabela hash Hash aberto -Localiza próxima posição livre na tabela hash Hash fechado -Utiliza listas ou árvores p/ cada posição da Tabela Hash N elementos armazenados K elementos com chave qualquer O(1) + O(K) → lista O(1) + o(log(K)) → árvore Tabela Hash K Lista 4 9 24 Slide 1 Slide 2 Slide 3 Slide 4 Slide 5 Slide 6 Slide 7 Slide 8 Slide 9 Slide 10 Slide 11 Slide 12 Slide 13 Slide 14 Slide 15 Slide 16 Slide 17 Slide 18 Slide 19 Slide 20 Slide 21 Slide 22 Slide 23 Slide 24 Slide 25 Slide 26 Slide 27 Slide 28 Slide 29 Slide 30 Slide 31 Slide 32 Slide 33 Slide 34 Slide 35 Slide 36 Slide 37 Slide 38 Slide 39 Slide 40 Slide 41 Slide 42 Slide 43 Slide 44 Slide 45 Slide 46 Slide 47 Slide 48 Slide 49 Slide 50 Slide 51
Compartilhar