Sorting by name and number plate

Asked

Viewed 512 times

0

I have this List simply chained and n know how to order it. I need to sort by name and number.

#include <stdio.h>
#include <stdlib.h>

void BuscarMatricula();
void Inserir();
void Exibir();
void Remover();
int menu();
void OrdenaNome();


typedef struct registro 
{
    char nome[50];
    int matricula;
    float nota;
    struct registro *prox;
}Registro;


int menu()
{
    int op;
    printf("\n\tLista Encadeada Simples-\n");
    printf("Informe a opção desejada\n");
    printf("1 - Inserir\n");
    printf("2 - Buscar pro Matricula\n");
    printf("3 - Remover\n");
    printf("4 - Ordenar por nome\n");
    printf("5 - Ordenar por Matricula\n");
    printf("6 - Exibir os elementos da Lista\n");
    printf("7 - Calcular média da turma\n");
    scanf("%d", &op);
    return op;
}



void Inserir(Registro *inicio)
{
    Registro *novo;
    novo=inicio;
    if(novo->prox==NULL) // Alocação comúm;
    { 
        novo->prox=(Registro *)malloc(sizeof(Registro));
        novo = novo->prox;
    printf("Informe o nome do aluno\n");
    scanf("%s",novo->nome);
    __fpurge(stdin);

    printf("Informe a Matricula do Aluno\n");
    scanf("%d", &novo->matricula);

    printf("Informe a nota do Aluno\n");
    scanf("%f", &novo->nota);
    novo->prox = NULL;

    }
    else // novo apontando para uma posição já alocada;
    {
        novo=novo->prox;
        Inserir(novo);
    }

}

void Exibir(Registro *inicio)
{
    Registro *Exibir;
    Exibir=inicio->prox;
    if(Exibir==NULL)
    {
        printf("\t-------------------------------------------------\n");
        printf("\tRegistro Vazio\n");
        printf("\t-------------------------------------------------\n");
    }
    else{
    do{
        printf("\t Nome do Aluno: %s | Matricula :%d | Nota: %.2f \n", Exibir->nome,Exibir->matricula,Exibir->nota );
        printf("\t-------------------------------------------------\n");
        Exibir=Exibir->prox;
    }while(Exibir!=NULL);
    }
}

void BuscarMatricula(Registro *inicio)
{
    int Pesquisar_matricula;
    Registro *Buscar;
    Buscar=inicio->prox;
    if(Buscar==NULL)
        {
        printf("\t-------------------------------------------------\n");
        printf("\tRegistro Vazio\n");
        printf("\t-------------------------------------------------\n");
    }
    else{
    printf("Informe a matricula do aluno\n");
    scanf("%d", &Pesquisar_matricula);
    do{
        if(Pesquisar_matricula==Buscar->matricula)
        {
            printf("\t Nome do Aluno: %s | Matricula :%d | Nota: %.2f \n", Buscar->nome,Buscar->matricula,Buscar->nota );
            break;
        }
        else
            Buscar=Buscar->prox;
        if(Buscar==NULL)
            printf("Matricula não encontrada\n");
    }while(Buscar!=NULL);
    }
}

void Remover(Registro *inicio)
{
    int Pesquisar_matricula;
    Registro *Remover;
    Registro *anterior;
    Remover=inicio->prox;
    anterior=inicio;
    if(Remover==NULL)
        {
        printf("\t-------------------------------------------------\n");
        printf("\tRegistro Vazio\n");
        printf("\t-------------------------------------------------\n");
    }
    else{
    printf("Informe a matricula do aluno\n");
    scanf("%d", &Pesquisar_matricula);
    do{
        if(Pesquisar_matricula==Remover->matricula)
        {
            printf("\t Aluno removido: %s | Matricula :%d | Nota: %.2f \n", Remover->nome,Remover->matricula,Remover->nota );
            anterior->prox=Remover->prox;
            free(Remover);
            break;
        }
        else
            Remover=Remover->prox;
            anterior=anterior->prox;
        if(Remover==NULL)
            printf("Matricula não encontrada\n");
    }while(Remover!=NULL);
    }
}

void OrdenaMatricula(Registro *inicio)
{
    int ss;
    Registro *Ordenar;
    Ordenar=inicio->prox;
    Registro *aux;



    while(Ordenar!=NULL)
    {
        aux=Ordenar->prox;
        while(aux!=NULL)
        {
            if(aux->matricula<Ordenar->matricula)
            {   
                ss=Ordenar->matricula;
                Ordenar->matricula=aux->matricula;
                aux->matricula=ss;
            }
        }   
        Ordenar=Ordenar->prox;
        aux=aux->prox;
    }

}





int main()
{ 
    Registro *inicio;
    inicio=(Registro *)malloc(sizeof(Registro));  
    inicio->prox=NULL;


    int op;
    int sair=0;
    int posvalida;
    while(!sair)
    {
        op=menu();
        switch(op)
        {
            case 1:{
                Inserir(inicio);
                break;

            }
            case 2:{
                BuscarMatricula(inicio);
                break;
            }
            case 3:{
                Remover(inicio);
                break;
            }
            case 5:{
                OrdenaMatricula(inicio);
                break;
            }
            case 6:{
                Exibir(inicio);
                break;
            }
            case 7:{
                sair=1;
                break;
            }
        }

    }

}

1 answer

1

The function OrdenaMatricula was very close to working. It only has the pointer increment aux in the while wrong and missed using the nome and the nota.

You can modify it to:

void OrdenaMatricula(Registro *inicio) {
    int ss;
    char nometemp[50]; //variavel adicionada para o swap
    float notatemp; //variavel adicionada para o swap

    Registro *Ordenar;
    Ordenar=inicio->prox;
    Registro *aux;

    while(Ordenar!=NULL) {
        aux=Ordenar->prox;

        while(aux!=NULL) {
            if(aux->matricula<Ordenar->matricula) {
                //agora troca os 3 campos de dados de cada vez
                ss=Ordenar->matricula;
                strcpy(nometemp,Ordenar->nome);
                notatemp = Ordenar->nota;

                Ordenar->matricula=aux->matricula;
                strcpy(Ordenar->nome, aux->nome);
                Ordenar->nota = aux->nota;

                aux->matricula=ss;
                strcpy(aux->nome, nometemp);
                aux->nota = notatemp;
            }
            aux=aux->prox; //aux tem de navegar para o da frente aqui
        }
        //em vez de aqui, que era onde estava 
        Ordenar=Ordenar->prox;
    }   
}

See the example in Ideone

The ordination by nome is exactly the same changing just the if of the second while. Instead of repeating the whole function to sort by name can try to reuse the whole logic once it is equal.

There are several ways to do this. I show one that uses pointers to functions so that it can pass a record comparison function. To start the function is changed OrdenaMatricula to receive a comparison function and do the if based on that function:

void Ordena(Registro *inicio, int *compara(Registro*,Registro*) ) {
    //--------------------------------^ função de comparação aqui
    ...

    while(Ordenar!=NULL) {
        aux=Ordenar->prox;
        while(aux!=NULL) {
            if(compara(aux, Ordenar) > 0) {
            //---^ comparação é feita agora chamando a função recebida com os 2 registros
                ...
            }
            aux=aux->prox;
        }
        Ordenar=Ordenar->prox;
    }
}

Note that in this last step I changed the function name to Ordena since it will serve for both sorts. I also assumed that the comparison function returns an integer with value >0 for longer, <0 for minor and 0 for the same, the style of strcmp.

The comparison function for the plates would look like this:

int comparaMatriculas(Registro *r1, Registro *r2){
    return (r1->matricula - r2->matricula);
}

And in the main the call to Ordena must now include this last function:

case 5: {
    Ordena(inicio, comparaMatriculas /*<--aqui*/);
    break;
}

For the comparison of names you only need to create a function that compares the names you can directly base on strcmp of <string.h>

int comparaNomes(Registro *r1, Registro *r2){
    return strcmp(r1->nome, r2->nome);
}

And make the corresponding call on main:

case 4: {
    Ordena(inicio, comparaNomes );
    break;
}

Additional notes

To try to be framed with the algorithm and logic of the question I did not change the way in which the order itself was being done. There are, however, more efficient ways of ordering, although they are considerably more complex.

Can:

  • Switch the algorithm to a more efficient one like Merge Sort, which already ensures complexity in the order of O(n log n).
  • Do not change the list elements by copying their values, but move only the pointers.
  • Speaking of performance... I did this analysis for some sorting methods in Java. Average time to sort 30,000 elements: better implementation of BubbleSort gave 1692.41 ms; MergeSort gave 4.29 ms

  • Isac, I think it would be better to just do the topological change, without changing the content of each node, changing only the pointers. I did something similar here: https://answall.com/a/246301/64969

  • 1

    @Jeffersonquesado Yes would certainly be better and more efficient as indicated in the notes. I did not do this not only to change the logic that the AP already had and also because it is considerably more complicated. Later on I will probably complement the answer with this solution as well.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.