Sort a list by a certain element of the C ++ class

0

The project is in CodeBlocks, what I want is that when you show the list, show them sorted by the "Key" field either ascending or descending. Or that the function insert the order and print them or vice versa.

zapatos.h

#ifndef ZAPATOS_H        
#define ZAPATOS_H    
#include<string.h>     
#include<algorithm>    
#include<list>  
#include<iterator>  
#include<iomanip>  
#include<iostream>        
using namespace std;

template <typename T>
class zapatos
{
public:
    zapatos();

    void pideDatos();
    void muestraDatos();
    //void eliminarUltimo();
    void eliminar();
    void bubble(zapatos,T n);
    void buscarDato();
    void modificarDato();

    zapatos *siguiente;
    zapatos *anterior;
    zapatos *auxPrimero=NULL;
    zapatos *auxUltimo=NULL;

    int auxZap,auxz2,auxz3;
    zapatos *auxTres;
    zapatos *auxDos;
    zapatos *zapatosLDE;
  private:
    T precio;
    string modelo;
    T clave;

};
template <typename T>
zapatos<T>::zapatos()
{
//ctor
}
template <typename T>
void zapatos<T>::pideDatos(){
zapatosLDE=new zapatos;

cout<< "Ingrese la Clave del producto: ";
cin>>zapatosLDE->clave;
cout<< "Ingrese el Modelo: ";
getline(cin,zapatosLDE->modelo);
getline(cin,zapatosLDE->modelo);
cout<< "Ingrese el precio:$";
cin>>zapatosLDE->precio;
cout<<endl;

zapatosLDE->siguiente=auxPrimero;
    auxPrimero=zapatosLDE;

}/*
template <typename T>
void zapatos<T>::bubble(zapatos clave,T n){
T aux;
for(int i=0; i<n-1; i++){
    for(int j=0; j<n-1-i;j++){
        if(zapatosLDE->clave > zapatosLDE->clave[j+1] ){
            aux=clave[j];
            clave[j]=clave[j+1];
            clave[j+1]=aux;
        }
    }
 }
 }
 */
 template <typename T>
 void zapatos<T>::muestraDatos(){

 cout<< "\t|Clave|\t\t|Modelo|\t\t|Precio|"<<endl;
 int clave=0;
 while(zapatosLDE!=NULL){
    //zapatos<T>::bubble(clave ,T n);
    cout<<"\t"<<zapatosLDE->clave<<"\t"
        <<"\t"<<zapatosLDE->modelo<< "\t"
        <<"\t\t$"<<zapatosLDE->precio<<endl;
        zapatosLDE=zapatosLDE->siguiente;
  }

  }/*
  template <typename T>
  void zapatos<T>::sort(){
  int temp_data;
  zapatosLDE=auxPrimero;
  auxTres=zapatosLDE;

  while(zapatosLDE){
    auxTres=zapatosLDE;
    if(zapatosLDE->clave > auxTres->clave){
        temp_data=zapatosLDE->clave;
               zapatosLDE->clave=temp_data;
                auxTres->clave=temp_data;
                break;
    }
  }zapatosLDE=zapatosLDE->siguiente;
  }*/
  template <typename T>
  void zapatos<T>::eliminar(){
   char ask[2];
   int tecla=1;

  zapatosLDE=auxPrimero;

  if(zapatosLDE==NULL){
    cout<< "No hay Datos!"<<endl;
  }else{
    cout<< "Ingrese la clave del producto a eliminar: "<<endl;
    cin>>auxZap;
    do{
        if(auxZap==zapatosLDE->clave){
                cout<< "\nClave: "<<zapatosLDE->clave<<endl
                << "Modelo: "<<zapatosLDE->modelo<<endl
                << "Precio: "<<zapatosLDE->precio<<endl;
        cout<< endl<< "Seguro de continuar? S/N"<<endl;
        cin>>ask[2];
        if((ask[2]=='S')||(ask[2]=='s')){
            auxPrimero=zapatosLDE->siguiente;
            delete(zapatosLDE);
        }
            //zapatosLDE=auxPrimero;
            cout<< "Dato eliminado"<<endl;
            break;
        }else{
            //auxUltimo=zapatosLDE;
            auxTres=zapatosLDE;
                    zapatosLDE=zapatosLDE->siguiente;
            if(zapatosLDE==NULL){
                cout<< "Dat no found"<<endl;
                //break;
            }

        }
            if(auxZap== zapatosLDE->clave){
                    cout<< "\nClave: "<<zapatosLDE->clave<<endl
                << "Modelo: "<<zapatosLDE->modelo<<endl
                << "Precio: "<<zapatosLDE->precio<<endl;
        cout<< endl<< "Seguro de continuar? S/N"<<endl;
        cin>>ask[2];
        if((ask[2]=='S')||(ask[2]=='s')){

            auxDos=zapatosLDE->siguiente;
            delete(zapatosLDE);

            zapatosLDE=auxTres;
            zapatosLDE->siguiente=auxDos;
                        cout<< "Dato elimina2"<<endl;
                        break;
        }
            }
    }while(zapatosLDE!=NULL);
  }
  }

  template <typename T>
  void zapatos<T>::buscarDato(){

  zapatosLDE=auxPrimero;
  if(zapatosLDE==NULL)
    cout<< "Zero elements"<<endl;
   else{
    cout<< "Escriba la clave #:";
    cin>>auxz3;

    int tecla=1;
    do{
        if(auxz3==zapatosLDE->clave){
            cout<< "Clave: "<<zapatosLDE->clave<<endl
                << "Modelo: "<<zapatosLDE->modelo<<endl
                << "Precio:$"<<zapatosLDE->precio<<endl;
            tecla=2;
        }else{
            zapatosLDE=zapatosLDE->siguiente;
            if(zapatosLDE==NULL)
                cout<< "No found!!"<<endl;
        }
     }while((tecla!=2) && (zapatosLDE!=NULL));
   }
  }
  template <typename T>
  void zapatos<T>::modificarDato(){
  int tecla;
  zapatosLDE=auxPrimero;

  if(zapatosLDE==NULL)
    cout<< "No hay elements"<<endl;
  else{
    cout<< "Clave del zapato a modificar: ";
    cin>>auxz2;

    int n=0;
    do{
        if(auxz2==zapatosLDE->clave){
            cout<<endl
                <<"Clave "<<zapatosLDE->clave<<endl
                << "Modelo "<<zapatosLDE->modelo<<endl
                << "Precio "<<zapatosLDE->precio<<endl<<endl;

            cout<< "Qué quiere modificar?: "<<endl
                << "1.clave"<<endl
                << "2.modelo"<<endl
                << "3.precio"<<endl;
            cin>>tecla;

            n=1;
            switch(tecla){
            case 1:
                cout<< "Escriba la nueva clave"<<endl;
                cin>>zapatosLDE->clave;
                break;

            case 2:
                cout<< "Escriba el nuevo modelo"<<endl;
                getline(cin,zapatosLDE->modelo);
                getline(cin,zapatosLDE->modelo);
                break;

            case 3:
                cout<< "Escriba el nuevo precio"<<endl;
                cin>>zapatosLDE->precio;
                break;
            }
        }else{
            zapatosLDE=zapatosLDE->siguiente;
            if(zapatosLDE==NULL)
                cout<< "Dato no encontrado!!"<<endl;
        }
    }while( (zapatosLDE!=NULL) && (n==0));
  }
  }

  #endif // ZAPATOS_H

main.cpp

#include <iostream>  
#include"zapatos.h"  
#include<string.h>  
#include<cstdlib>  
#include<algorithm>  
#include<conio.h>  
using namespace std;  

int main()  
{
 zapatos<int> Z;

 bool flag=false;
 char tecla;

 do{
    system("cls");
    cin.clear();

    cout<< "\t***Elige una opcion***"<<endl
        << "\t1)Agregar"<<endl
        << "\t2)Quitar"<<endl
        << "\t3)Buscar"<<endl
        << "\t4)Mostrar Lista"<<endl
        << "\t5)Modificar"<<endl
        << "\t6)Salir"<<endl;
    cin>>tecla;

    switch(tecla){
    case '1':
        cout<<endl<< "Opcion 1)Insertar"<<endl;
        Z.pideDatos();
        system("pause");
        break;

    case '2':
        cout<<endl<< "Opcion 2)Eliminar"<<endl;
        Z.eliminar();
        system("pause");
        break;

    case '3':
        cout<<endl<< "Opcion 3)Buscar"<<endl;
        Z.buscarDato();
        system("pause");
        break;

    case '4':
        cout<<endl<< "Opcion 4)Mostar"<<endl;

        Z.muestraDatos();
        system("pause");
        break;

    case '5':
        Z.modificarDato();
        system("pause");
        break;

    case '6':
        cout<< "Hasta Luego :-)";
        flag=true;
        break;
    }
}while(flag!=true);
getch();
return 0;
}
    
asked by Julio Alvarado 10.10.2016 в 03:44
source

1 answer

3

I do not know what margin of freedom you have when solving this practice, but the truth is that the design of zapatos<T> is horrible. A single class is both a linked list and a node ... as well as exposing its internal logic (the pointers of the linked list) happily, which ends up breaking any concept of encapsulation.

Another inconsistency that exists is that it is assumed that the list is double linked and yet in the creation of the nodes only the pointer siguiente is initialized, with which the double link is irretrievably lost.

That said, sorting records can be a trivial operation if you use, say, a vector. The idea is to dump the list to a vector, sort that vector and return to sew the resulting list. This way you avoid having to deal with the problem of pointers when moving site nodes constantly:

std::vector<zapatos<T>*> lista;
zapatos<T>* ptr = siguiente;

// Se vuelca la lista al vector
while( ptr )
{
  lista.push_back(ptr);
  ptr++;
}

// Se ordenan los registros
std::sort(lista.begin(),lista.end(),
          [](zapatos<T>* ptr1, zapatos<T>* ptr2)
          { return ptr1->clave < ptr2->clave; });

// Se recompone la lista
siguiente = lista[0];
ptr = siguiente;

for( size_t i=1; i<lista.size(); ++i )
{
  // Se actualizan los punteros de la lista
  ptr->siguiente = lista[i];
  lista[i]->anterior = ptr;

  ptr = lista[i];    
}

The ideal would be to place this logic in a function ordenar() or similar since it is not necessary to execute it constantly.

Another possibility, if the list has to be always ordered according to the key, is to force the list to be always ordered. This can be achieved by modifying the function pideDatos so that instead of adding the element to the beginning of the list, insert the element in the corresponding position. It would also be necessary to modify the function modificarDato so that, in the case of modifying the key, the new position of the element is recalculated.

template <typename T>
void zapatos<T>::pideDatos()
{
  zapatosLDE=new zapatos;

  cout<< "Ingrese la Clave del producto: ";
  cin>>zapatosLDE->clave;
  cout<< "Ingrese el Modelo: ";
  getline(cin,zapatosLDE->modelo);
  cout<< "Ingrese el precio:$";
  cin>>zapatosLDE->precio;
  cout<<endl;

  if( !auxPrimero )
    auxPrimero = zapatosLDE;
  else if( auxPrimero->clave > zapatosLDE->clave )
  {
    zapatosLDE->siguiente = auxPrimero;
    auxPrimero->anterior = zapatosLDE;
    auxPrimero = zapatosLDE;
  }
  else
  {
    zapatos<T>* ptr = auxPrimero;

    while( ptr->siguiente )
    {
      if( ptr->siguiente->clave > zapatosLDE->clave )
        break;
    }  

    if( ptr->siguiente )
    {
      zapatosLDE->siguiente = ptr->siguiente;
      ptr->siguiente->anterior = zapatosLDE;
    }

    ptr->siguiente = zapatosLDE;
    zapatosLDE->anterior = ptr;       
  }
}

And something similar would be missing for modificarDato .

FINAL NOTE : It would be advisable for the constructor to initialize the pointers to NULL (from C ++ 11 the ideal is to use nullptr ) as well as you should implement the destructor to release all the reserved memory.

Greetings.

    
answered by 10.10.2016 / 09:17
source