utiles_v2017/gorden.h

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);
}
};