250 lines
5.0 KiB
C++
250 lines
5.0 KiB
C++
#pragma once
|
|
#include "garray.h"
|
|
|
|
/*
|
|
Ordenaciones de varias ordenaciones de un array
|
|
la funcion de orden f_ord(e1, e2)
|
|
ha de devolver <0 si e1<e2
|
|
0 si e1=e2
|
|
>0 si e1>e2
|
|
*/
|
|
typedef struct Indices_gorden
|
|
{
|
|
int i; //indice a a elemento con esta posicion
|
|
int io;//posicion que ocupa el elemento de la lista original en este orden
|
|
}Indices_gorden;
|
|
typedef struct Orden_gorden
|
|
{
|
|
int (*f_ord)(void* e1, void*e2);//funcion de orden
|
|
Cgarray<Indices_gorden> ind;//indices
|
|
}Orden_gorden;
|
|
|
|
template <typename T>
|
|
class Cgorden
|
|
{
|
|
public:
|
|
//variables-----------------------------------
|
|
Cgarray<Orden_gorden> ord;
|
|
Cgarray<T> *elem;
|
|
//c y d---------------------------------------
|
|
//**************************************************************
|
|
Cgorden(Cgarray<T> *el=NULL)
|
|
{
|
|
elem=el;
|
|
}
|
|
//**************************************************************
|
|
~Cgorden()
|
|
{
|
|
//borramos arrays
|
|
for (int i=0; i<ord.n; i++)
|
|
{
|
|
if(ord[i].ind.ptr)
|
|
{
|
|
free(ord[i].ind.ptr);
|
|
ord[i].ind.n=ord[i].ind.m=0;
|
|
}
|
|
}
|
|
}
|
|
|
|
//**************************************************************
|
|
inline BOOL add_ord(int (*f_ord)(void*, void*))//añade un orden nuevo
|
|
{
|
|
Indices_gorden ii;
|
|
int i;
|
|
Orden_gorden o;
|
|
//inicia orden------------------
|
|
o.f_ord=f_ord;
|
|
o.ind+=elem->n;
|
|
for(i=0; i<elem->n; i++)
|
|
{
|
|
ii.i=i;
|
|
o.ind+ii;
|
|
}
|
|
//-------------------------------
|
|
//ordena
|
|
ord_qsort(0,elem->n-1,&o);
|
|
//reasigna----------------------------
|
|
for(i=0; i<elem->n; i++)
|
|
o.ind[o.ind[i].i]=i;
|
|
//añade el orden-----------------
|
|
|
|
ord+o;
|
|
o.ind.ptr=NULL;
|
|
o.ind.m=0;
|
|
return TRUE;
|
|
}
|
|
//**************************************************************
|
|
inline T* get(int i, int o)//da el elemento iesimo del orden o
|
|
{
|
|
return NULL;
|
|
}
|
|
//**************************************************************
|
|
inline int geti(int i, int o)//da el indice del elemento que iesimo del orden o
|
|
{
|
|
return ord[o].ind[i].i;
|
|
}
|
|
//**************************************************************
|
|
inline int geti(int i, int o, int oi)//da el la posicion que tiene el iesimo del orden o en el orden oi
|
|
{
|
|
return ord[oi].ind[ord[o].ind[i].i].io;
|
|
}
|
|
//******************************************************************
|
|
inline void ord_qsort(int ini, int fin, Orden_gorden *o)
|
|
{
|
|
int ii,kf,ki, jf,ji,p1,p, com;
|
|
BOOL bus=TRUE;
|
|
//caso base-------------------
|
|
p=(fin-ini);
|
|
if(p<1)
|
|
return;
|
|
if (p<2)
|
|
{
|
|
if(0<o->f_ord(elem->get(o->ind[ini].i),elem->get(o->ind[fin].i)))
|
|
{
|
|
ii=o->ind[ini].i;
|
|
o->ind[ini].i=o->ind[fin].i;
|
|
o->ind[fin].i=ii;
|
|
}
|
|
return;
|
|
}
|
|
//a pivotar-------------------
|
|
//inicializacion
|
|
p+=ini;
|
|
p1=p;
|
|
kf=fin;
|
|
ki=ini;
|
|
jf=ji=-1;
|
|
while(bus)
|
|
{
|
|
//busca por la izquierda-----
|
|
while(p>ki)
|
|
{
|
|
com=o->f_ord(elem->get(o->ind[p].i),elem->get(o->ind[ki].i));
|
|
if(com<0)
|
|
{
|
|
if(jf>=0)
|
|
{
|
|
ii=o->ind[jf].i;
|
|
o->ind[jf].i=o->ind[ki].i;
|
|
o->ind[ki].i=ii;
|
|
jf=-1;
|
|
ki++;
|
|
}
|
|
else
|
|
{
|
|
ji=ki;//encontrado tio que va al otro lado
|
|
break;
|
|
}
|
|
|
|
}
|
|
else if(com==0)
|
|
{
|
|
//elementos iguales se pone al centro
|
|
p--;
|
|
ii=o->ind[p].i;
|
|
o->ind[p].i=o->ind[ki].i;
|
|
o->ind[ki].i=ii;
|
|
}
|
|
else
|
|
ki++;
|
|
}
|
|
//busca por la derecha-----
|
|
while(p1<kf)
|
|
{
|
|
com=o->f_ord(elem->get(o->ind[p1].i),elem->get(o->ind[kf].i));
|
|
if(com>0)
|
|
{
|
|
if(ji>=0)
|
|
{
|
|
ii=o->ind[ji].i;
|
|
o->ind[ji].i=o->ind[kf].i;
|
|
o->ind[kf].i=ii;
|
|
ji=-1;
|
|
kf--;
|
|
}
|
|
else
|
|
{
|
|
jf=kf;//encontrado tio que va al otro lado
|
|
break;
|
|
}
|
|
|
|
}
|
|
else if(com==0)
|
|
{
|
|
//elementos iguales se pone al centro
|
|
p1++;
|
|
ii=o->ind[p1].i;
|
|
o->ind[p1].i=o->ind[kf].i;
|
|
o->ind[kf].i=ii;
|
|
}
|
|
else
|
|
kf--;
|
|
}
|
|
//condicion de fuga---
|
|
bus=(p>ki) && (p1<kf);
|
|
}
|
|
//falta por ordenar de un lado
|
|
//lo malo es que tocara mover memo
|
|
//se puede sin mover memo
|
|
if(p>ki)
|
|
{
|
|
//falta la izquierda-----------------
|
|
while(p>ki)
|
|
{
|
|
com=o->f_ord(elem->get(o->ind[p].i),elem->get(o->ind[ki].i));
|
|
if(com<0)
|
|
{
|
|
//cambia elemento al otro lado del pivote
|
|
ii=o->ind[p-1].i;
|
|
o->ind[p-1].i=o->ind[p1].i;
|
|
o->ind[p1].i=o->ind[ki].i;
|
|
o->ind[ki].i=ii;
|
|
p--;
|
|
p1--;
|
|
continue;
|
|
}
|
|
else if(com==0)
|
|
{
|
|
//elementos iguales se pone al centro
|
|
p--;
|
|
ii=o->ind[p].i;
|
|
o->ind[p].i=o->ind[ki].i;
|
|
o->ind[ki].i=ii;
|
|
continue;
|
|
}
|
|
ki++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while(p1<kf)
|
|
{
|
|
com=o->f_ord(elem->get(o->ind[p1].i),elem->get(o->ind[kf].i));
|
|
if(com<0)
|
|
{
|
|
//cambia elemento al otro lado del pivote
|
|
ii=o->ind[p1+1].i;
|
|
o->ind[p1+1].i=o->ind[p].i;
|
|
o->ind[p].i=o->ind[kf].i;
|
|
o->ind[kf].i=ii;
|
|
p++;
|
|
p1++;
|
|
continue;
|
|
}
|
|
else if(com==0)
|
|
{
|
|
//elementos iguales se pone al centro
|
|
p1++;
|
|
ii=o->ind[p1].i;
|
|
o->ind[p1].i=o->ind[kf].i;
|
|
o->ind[kf].i=ii;
|
|
continue;
|
|
}
|
|
kf--;
|
|
}
|
|
}
|
|
|
|
ord_qsort(ini, p-1, o);
|
|
ord_qsort(p1+1, fin, o);
|
|
}
|
|
}; |