INF 01126 Estruturas de Dados I Estruturas de
- Slides: 42
INF 01126 - Estruturas de Dados I Estruturas de Dados Genéricas (em C) Gabriel Mattos Langeloh gmlangeloh@inf. ufrgs. br *material do prof. Anderson Rocha Tavares
Estruturas de Dados: generalidade ● Dados diferentes ● Mesmas operações ○ Exemplo: inserir (no início) em uma lista de inteiros 8 42 prox ini prox Antes: 8 42 prox 15 prox ini prox Depois:
Estruturas de Dados: generalidade ● Dados diferentes ● Mesmas operações ○ Exemplo: inserir (no início) em uma lista de floats 8. 0 4. 2 prox ini prox Antes: 8. 0 4. 2 prox 0. 15 prox ini prox Depois:
Estruturas de Dados: generalidade ● Dados diferentes ● Mesmas operações ○ Exemplo: inserir (no início) em uma lista ● Códigos diferentes : ( typedef struct st_nodo_int { int dado; struct st_nodo_int *prox; } t_nodo_int; int inserir_ini(t_lista_int *l, int dado); typedef struct st_nodo_float { float dado; struct st_nodo_float *prox; } t_nodo_int; int inserir_ini(t_lista_float *l, float dado);
Estruturas de Dados Genéricas: ideia ● Dados diferentes ● Mesmas operações ○ Exemplo: inserir (no início) em uma lista ● Mesmo código : ) typedef struct st_nodo<TIPO> { TIPO dado; struct st_nodo<TIPO> *prox; } t_nodo; int inserir_ini(t_lista *l, <TIPO> dado); ● C++ permite construções desse tipo, mas C não : (
Tipos parametrizados ● Exemplo em C++ (https: //repl. it/@andertavares/Cpp-Generic-List-Example ) #include <iostream> #include <list> using namespace std; int main () { list<int> ints; list<float> floats; ints. push_front(7); ints. push_front(9); floats. push_front(4. 55); floats. push_front(2 e 20); . . . return 0; } Saída:
Estruturas genéricas em C ● C não permite tipos parametrizados : ( ● Mas possui: ○ Tipos de dados genéricos ■ Vamos armazenar o espaço necessário para os dados e copiar os bytes quando o usuário mandar inserir ○ Recursos para customizar as funções ■ O usuário irá fornecer a funções para coisas específicas de cada tipo
Exemplo: Listas genéricas em C typedef struct st_nodo { void* dado; struct st_nodo *prox; } t_nodo; void*: ponteiro sem tipo (referencia qualquer tipo de endereço) typedef st_lista { int tam_dado; //numero de bytes que um elemento ocupa t_nodo *ini; } t_lista;
Listas genéricas em C - Ilustração typedef struct st_nodo { void* dado; struct st_nodo *prox; } t_nodo; typedef st_lista { int tam_dado; //numero de bytes que um elemento ocupa t_nodo *ini; } t_lista; ini dado prox
Listas genéricas em C - Exemplo (ints) typedef struct st_nodo { void* dado; struct st_nodo *prox; } t_nodo; typedef st_lista { int tam_dado; //numero de bytes que um elemento ocupa t_nodo *ini; } t_lista; 8 15 -1 ini dado prox
Listas genéricas em C - Exemplo (strings) typedef struct st_nodo { void* dado; struct st_nodo *prox; } t_nodo; typedef st_lista { int tam_dado; //numero de bytes que um elemento ocupa t_nodo *ini; } t_lista; “Joao” “roupa” “teatro” ini dado prox
Listas genéricas em C - Interface, parte 1 typedef struct st_nodo {. . . } t_nodo; typedef struct st_lista {. . . } t_lista; void inicializar(t_lista *l, int tam_dado); void inserir_ini(t_lista *l, void *dado); void* consultar(t_lista *l, int pos); int tamanho(t_lista *l); /* Exemplo de uso de uma lista generica */ t_lista minha_lista; inicializar(&minha_lista, sizeof(int)); //lista de inteiros int numero = 2, indice = 3; inserir(&minha_lista, &numero); int* res = (int *) consultar(&minha_lista, indice); if (res == NULL) { printf(“Nao encontrado!n”); }. . .
Listas Genéricas: inicialização Procedimentos necessários: 1. Estabelece as condições iniciais necessárias void inicializar(t_lista *l, int tam_dado) { l->tam_dado = tam_dado; l->ini = NULL; }
Listas Genéricas: inserção no início Procedimentos necessários: 1. Aloca espaço para armazenar nodo 2. Aloca espaço para armazenar dado e o copia 3. Encadeia elemento int inserir(t_lista_enc *l, void* dado, int pos){ t_nodo *novo = NULL; // Ponteiro para novo elemento (1) novo = (t_nodo *) malloc(sizeof(t_nodo)); // Aloca um novo nodo if (novo == NULL) return 0; // falta de memoria (2) novo->dado = malloc(l->tam_dado); // aloca espaco para o dado (3) if(novo->dado == NULL) return 0; // testa falta de memoria memcpy(novo->dado, l->tam_dado); // copia o dado novo->prox = l->ini; l->ini = novo;
Listas Genéricas: consulta (implementação) Procedimentos necessários: 1. Percorre a lista até a posição desejada 2. Retorna o endereço do dado apropriadamente void *consulta(t_lista_enc *l, int pos) { int i = 0; t_nodo *atual = l-> ini; // Aux. para percorrer a lista (1) (2) } while (atual != NULL && i<pos) { atual = atual->prox; i++; } if (atual != NULL) return &(atual->dado); else return NULL;
Listas Genéricas: tamanho (implementação) Procedimentos necessários: 1. Conta o número de elementos int tamanho(t_lista_enc *l){ int cont = 0; t_nodo *atual = l>ini; while (atual != NULL) { cont++; atual = atual ->prox; } return cont; } LEMBRETE: versão não otimizada!
Listas genéricas em C - Interface, parte 2 typedef struct st_nodo {. . . } t_nodo; typedef struct st_lista {. . . } t_lista; void inicializar(t_lista *l, int tam_dado); void inserir_ini(t_lista *l, void *dado); void* consultar(t_lista *l, int pos); int tamanho(t_lista *l); void print_lista(t_lista *l); int buscar(t_lista *l); int remover(t_lista *l); void destruir(t_lista *l); Essas funções não vão funcionar assim, vamos ver o porquê.
Listas Genéricas: imprimir Se a lista fosse de inteiros. . . void print_lista(t_lista *l){ t_nodo *atual; printf("["); //1. marcador de 'inicio da lista' //2. exibir cada elemento for(atual = l->ini; atual != NULL; atual = atual->prox){ printf("%d", atual->dado); if(atual->prox != NULL) printf(", "); } printf("]n"); //3. marcador de 'fim da lista' }
Listas Genéricas: imprimir Se a lista fosse de floats… void print_lista(t_lista *l){ t_nodo *atual; printf("["); //1. marcador de 'inicio da lista' //2. exibir cada elemento for(atual = l->ini; atual != NULL; atual = atual->prox){ printf("%f", atual->dado); if(atual->prox != NULL) printf(", "); } printf("]n"); //3. marcador de 'fim da lista' }
Listas Genéricas: imprimir Se a lista fosse de structs. . . void print_lista(t_lista *l){ t_nodo *atual; printf("["); //1. marcador de 'inicio da lista' //2. exibir cada elemento for(atual = l->ini; atual != NULL; atual = atual->prox){ printf("%d, ", atual->dado. algo_int); printf("%s", atual->dado. algo_string); É possível customizar o if(atual->prox != NULL) printf("n"); separador de itens? } printf("]n"); //3. marcador de 'fim da lista' }
Listas Genéricas: imprimir Se a lista fosse de structs. . . void print_lista(t_lista *l, char* sep){ t_nodo *atual; printf("["); //1. marcador de 'inicio da lista' //2. exibir cada elemento for(atual = l->ini; atual != NULL; atual = atual->prox){ printf("%d, ", atual->dado. algo_int); É possível customizar printf("%s", atual->dado. algo_string); o(s) comando(s) de if(atual->prox != NULL) printf("%s", sep); imprimir? } printf("]n"); //3. marcador de 'fim da lista' }
Listas Genéricas: imprimir Se a lista fosse de structs. . . A ideia está correta, mas a sintaxe, não. void print_lista(t_lista *l, comando_imprime, char* sep){ t_nodo *atual; printf("["); //1. marcador de 'inicio da lista' //2. exibir cada elemento for(atual = l->ini; atual != NULL; atual = atual->prox){ comando_imprime(atual->dado); if(atual->prox != NULL) printf("%s", sep); } printf("]n"); //3. marcador de 'fim da lista' }
Listas Genéricas: imprimir Em C, é possível passar funções como parâmetro Necessário identificar a função (retorno e parâmetros) void print_lista(t_lista *l, comando_imprime, char* sep){ t_nodo *atual; printf("["); //1. marcador de 'inicio da lista' //2. exibir cada elemento for(atual = l->ini; atual != NULL; atual = atual->prox){ comando_imprime(atual->dado); if(atual->prox != NULL) printf("%s", sep); } printf("]n"); //3. marcador de 'fim da lista' }
Listas Genéricas: imprimir Em C, é possível passar funções como parâmetro Necessário identificar a função (retorno e parâmetros) void print_lista(t_lista *l, void func_imprime(void* dado), char* sep){ t_nodo *atual; printf("["); //1. marcador de 'inicio da lista' //2. exibir cada elemento for(atual = l->ini; atual != NULL; atual = atual->prox){ func_imprime(atual->dado); if(atual->prox != NULL) printf("%s", sep); } printf("]n"); //3. marcador de 'fim da lista' }
Listas Genéricas: imprimir O usuário fornece a função que imprime o dado Exemplos: void print_int(void* dado){ int* endereco = (int*) dado; printf("%d", *endereco); } void print_float(void* dado){ float* endereco = (float*) dado; printf("%f", *endereco); } void print_string(void* dado){ char** endereco = (char**) dado; printf("%s", *endereco); }
Listas genéricas em C - Interface, parte 2 typedef struct st_nodo {. . . } t_nodo; typedef struct st_lista {. . . } t_lista; void inicializar(t_lista *l, int tam_dado); void inserir_ini(t_lista *l, void *dado); void* consultar(t_lista *l, int pos); int tamanho(t_lista *l); void print_lista(t_lista *l, void func_imprime(void *), char *sep); int buscar(t_lista *l, void *dado, int func_compara(void *, void *)); int remover(t_lista *l, int pos, void func_libera(void *)); void destruir(t_lista *l, void func_libera(void *)); Usuário fornece as funções para imprimir, comparar e liberar dados
Listas Genéricas: remoção Procedimentos necessários: 1. Procura elemento a ser removido 2. Manipula ponteiros 3. Desaloca memória para o elemento a ser removido int remover(t_lista_enc *l, int pos, void func_libera(void *)) { int i = 0; t_nodo *ant = NULL; // Aux. p/ anterior t_nodo *atual = l->ini; // Aux. p/ percorrer lista while(atual != NULL && i < pos) { // percorre ant = atual; atual = atual->prox; i++; }. . . }
Listas Encadeadas: remoção (implementação) Procedimentos necessários: 1. Procura elemento a ser removido 2. Manipula ponteiros 3. Desaloca memória para o elemento a ser removido int remover(t_lista_enc *l, int pos, void func_libera(void *)) {. . . if(atual == NULL) return 0; //nao achou if(ant == NULL) { // Vai remover o 1 o l->ini = atual->prox; // ou l->ini = null; } else { // Vai remover do meio ou final ant->prox = atual->prox; }. . . }
Listas Encadeadas: remoção (implementação) Procedimentos necessários: 1. Procura elemento a ser removido 2. Manipula ponteiros 3. Desaloca memória para o elemento a ser removido int remover(t_lista_enc *l, int pos, void func_libera(void *)) {. . . if(func_libera != NULL) func_libera(atual->dado); //apaga dado free(atual); //apaga nodo return 1; }
Listas Encadeadas: remoção (implementação) Procedimentos necessários: 1. Procura elemento a ser removido 2. Manipula ponteiros 3. Desaloca memória para o elemento a ser removido int remover(t_lista_enc *l, int pos, void func_libera(void *)) {. . . //exemplo: if(func_libera != NULL) int libera_string(void* d 1){ func_libera(atual->dado); //apaga dado free(atual); //apaga d 1; nodo char** e 1 = (char**) free(*e 1); return 1; } }
Listas Encadeadas: destruição (implementação) Procedimentos necessários: 1. Remove todos os elementos, liberando memória 2. (reaproveitando código) void destruir(t_lista_enc *l, void func_libera(void *)) { while(remover(l, 0, func_libera)); }
Listas Encadeadas: buscar (implementação) Procedimentos necessários: 1. Procura pelo elemento na lista 2. Retorna a posição do elemento int buscar(t_lista *l, void* dado, int func_compara(void *, void *)){ t_nodo *atual = l->ini; // Aux. para percorrer a lista int i = 0; while (atual != NULL && func_compara(atual->dado, dado) != 0){ atual = atual->prox; i++; } if (atual == NULL) return -1; //chegou ao fim e nao achou return i; }
Listas Encadeadas: buscar (implementação) Procedimentos necessários: 1. Procura pelo elemento na lista 2. Retorna a posição do elemento //exemplo: int buscar(t_lista *l, void* dado, int func_compara(void *, void *)){ int compara_string(void* d 1, void* d 2){ t_nodo *atual = l->ini; // Aux. para percorrer a lista char** e 1 = (char**) d 1; int i = 0; char** e 2 = (char**) d 2; return strcmp(*e 1, *e 2 ); while (atual != NULL && func_compara(atual->dado, dado) != 0){ } atual = atual->prox; //exemplo i++; (o retorno é no estilo de strcmp): } compara_int(void* d 1, void* d 2){ int if int* (atual NULL) return -1; //chegou ao fim e nao achou e 1 == = (int*) d 1; } int* e 2 = (int*) d 2; return i; ( *e 1 - *e 2 ); }
Para saber mais: ponteiros para funções
Ponteiros para funções ● Na verdade, estamos passando o endereço das funções como parâmetro
Ponteiros para funções ● Função: sequência de instruções para o processador ● Instruções: palavras binárias que residem na memória ● Programa: somatório de todas as suas funções ○ main() é uma função ; )
Ponteiros para funções ● Função: sequência de instruções para o processador ● Instruções: palavras binárias que residem na memória ● Programa: somatório de todas as suas funções ○ main() é uma função ; )
Ponteiros para funções ● Ponteiros: armazenam endereços de memória ○ Inclusive o de instruções ● Um ponteiro para uma função armazena o endereço da sua primeira instrução
Ponteiros para funções - Sintaxe ● Declarar um ponteiro para função: tipo_retorno (*nome)(tipo_param 1, tipo_param 2, . . . ); tipo_retorno nome(tipo_param 1, tipo_param 2, . . . ); ● Exemplo: // tambem vale
Ponteiros para funções - Sintaxe ● Declarar um ponteiro para função: tipo_retorno nome(tipo_param 1, tipo_param 2, . . . ); ● Chamar a função através do ponteiro: var = nome(lista, de, parametros); ● Exemplo: Antes de usar, o ponteiro precisa receber o endereço da função.
Ponteiros para funções - Exemplo: https: //ide. geeksforgeeks. org/8 Ja. J 6 k. St Declaração Atribuição Uso
Ponteiros para funções: outro exemplo https: //repl. it/@andertavares/Function. Parameter. Example
- Série estatística geográfica
- Inf 121 uci
- A iliolumbalis
- Inf
- Transversalis tengely
- Centorovi kriteriji
- Define prim
- Artere thyroidienne inf
- Oran cherry release
- Inf
- Inf 70
- Inf3135
- Inf 327
- Inf 1900
- Inf 111
- Eurodatabase
- Cyclopeptide mushroom
- Infinitive without to
- Tuleb ma või da
- Porno inf
- Inf
- 1331x torrent
- Inf hartsol
- Inf
- Mag inf
- Inf1060
- Inf schule scratch
- Inf smartwatch
- Inf 110
- Dh character table
- Rcbottom.inf
- Hash160 to address
- Inf
- Pars sympathica
- Manifestversion
- Inf 3 form
- Vascularization of brain
- Dipl wirt inf
- Verb + to infinitive examples
- Inf
- Enformatik sınav soruları
- Potencial de ação
- Textura naturais e artificiais