[C] modifica quicksort con più pivot

di il
10 risposte

[C] modifica quicksort con più pivot

Ciao a tutti, devo implementare un Quicksort in C che utilizzi 'k' pivot invece che uno solo. Sono riuscita (forse) a fare la Partition, ma ora non riesco a capire come utilizzarla nella funzione ricorsiva, vi posto il codice:
#include <stdio.h>
#include <stdlib.h>

int Max (int A[],int k)
{
	int max=0,i,tmp;
	for(i=0;i<k-1;i++)
	{
		if (max<A[i])
		{
			max=A[i];
		}
	}
	printf("pivot=%d  ",max);
	printf("\n");
	return max;
}

int Swap (int A[], int i, int j)
{
	int tmp;
	tmp=A[j];
	A[j]=A[i];
	A[i]=tmp;
}
int Kpartition (int *A,int p,int r,int k)
{
	int i, j, pivot,z,q;
	i=p;
	j=r;
	for (z=0;z<k-1;z++)
	{
	pivot=Max (A, k);
	i=0;
		while (i<=j)
		{
			
			if (pivot==A[i])
				q=i;
			if (A[i]>pivot)
			{
				Swap(A,i,j);
				j--;
			}
			while (A[j]>pivot)
				j--;
			i++;
		}
		Swap(A,q,j);
		for(i=0; i<=r; i++)
			printf("%d  ",A[i]);
		printf("\nj=%d",j);
		}
	return j;
}
int Kquicksort(int A[], int p,int r,int k) //funzione ricorsiva che non riesco ad implementare
{
	int q;
	q=Kpartition(A,p,r,k);
	Kquicksort
}
int main ()
{
	int A[]={50,10,5,60}, n=3;
	int i,k=3;
	Kquicksort(A,0,n,k);

}
La mia idea teorica è di riapplicare la funzione Kpartition su ogni partizione formata nel vettore fino a che le partizioni risulteranno sempre più piccole e il vettore sarà ordinato. Ma purtroppo non riesco a capire né come fare il caso base della funzione ricorsiva né che parametri passare alla chiamata della funzione ricorsiva. C'è qualcuno che potrebbe darmi una mano? mi basterebbe giusto un idea sulla quale lavorare

10 Risposte

  • Re: [C] modifica quicksort con più pivot

    
    int Kquicksort(int A[], int p,int r,int k) //funzione ricorsiva che non riesco ad implementare
    {
       int q;
       if(p>=r)
          //Sei nel caso base quindi fai quello che devi fare
         q=Kpartition(A,p,r,k);
       
       Kquicksort(A, p, q, k);
       Kquicksort(A, q+1, r, k);
    }
    
    Il mio è solo l'imput, non ho visto nè come implementi la Kpartition ne altro.
  • Re: [C] modifica quicksort con più pivot

    Si questa è la ricorsione che ho utilizzato anch'io nel quicksort normale dove c'è solo un pivot e di conseguenza due partizioni del vettore iniziale, ma siccome devo utilizzare più pivot e quindi il vettore è diviso in 3 o più parti non riesco a capire come fare sto sclerando!
  • Re: [C] modifica quicksort con più pivot

    Calma!
    La Kpartition ti ritorna un valore. Come fai a dividere in k parti il vettore?

    Non ho capito quello che desideri fare, spiegati meglio per favore.
  • Re: [C] modifica quicksort con più pivot

    Allora ti faccio un esempio, ho k=3 quindi devo usare 2 pivot,
    vett di partenza {50,10,30,20,40,90,70,80,5}
    per scegliere il primo pivot prendo il massimo tra i primi k-1 elementi del vettore ovvero pivot=50
    sistemo il vettore così: elementi < del pivot a sinistra e quelli > a destra e risulta in questo modo {10,30,40,20,5,50,90,70,80}
    scelgo il secondo pivot nello stesso modo in cui ho scelto il primo quindi pivot=30 e faccio lo stesso procedimento con questo risultato {10,20,5,30,40,50,90,70,80}.
    A questo punto dovrei riapplicare la partition sulle 3 partizioni del vettore cioè {10,20,5},{30,40},{50,90,70,80} e ripetere ricorsivamente fino a che ogni partizione ha un solo elemento e quindi è ordinata.
    Non so so se mi sono spiegata bene
  • Re: [C] modifica quicksort con più pivot

    Quando scegli il secondo pivot, prendi già un valore certamente minore del precedente (dal momento che partizioni separatamente per ciascun pivot. Più in generale, ogni pivot è minore del precedente.

    Di conseguenza, ogni pivot va confrontato solo con la partizione a sinistra del pivot precedente. Di fatto con questo metodo risparmi ricorsioni a sinistra, perché di fatto è già come se ricorresti una volta quando applichi il secondo pivot (la complessità asintotica non dovrebbe cambiare, ma sarebbe comunque interessante valutare l'entità della potatura dell'albero delle ricorsioni), per cui nel sottovettore di sinistra arrivi più rapidamente ad avere vettori di dimensione 1.

    Se avesti almeno 3 pivot e prendessi alternatatamente i pivot da entrambe le estremità del vettore, oppure avesti 2 pivot presi dalle estremità opposte ma scambiassi le estremità a seconda del lato su cui ricorri probabilmente le prestazioni sarebbero ancora migliori, perché mentre con la versione attuale a sinistra ordini più velocemente che a sinistra, dove mantieni il quick sort classico, con la nuova ordineresti velocemente da entrambe le parti.

    ciao
  • Re: [C] modifica quicksort con più pivot

    Ah forse ho capito cosa intendi ma io non conosco il numero di pivot che devo utilizzare, quindi devo fare un codice generale. La mia domanda è: come faccio a fare la funzione ricorsiva sulle varie partizioni del vettore? ad esempio in un quicksort normale chiamo la funzione con i parametri (A,p,q) dove p è l'inizio e q è dove finisce la prima partizione, e poi la richiamo con i parametri (A,q+1,r) dove r è l'ultimo elemento del vettore. Ma in un quicksort generalizzato dove non so quante partizioni del vettore avrò che parametri passo??
  • Re: [C] modifica quicksort con più pivot

    Allora io alla Kpartition farei ritornare un vettore di elementi e non un solo elemento, così da avere gli indici delle k partizioni, quindi il prototipo della Kparition dovrà essere:

    int * Kpartition(int *, int , int, int);

    Adesso puoi implementare la funzione ricorsiva:
    
    int Kquicksort(int A[], int p, int r, int k) //funzione ricorsiva che non riesco ad implementare
    {
       int i;
       int *q;
       if(p>=r)
          //Sei nel caso base quindi fai quello che devi fare
       q=Kpartition(A,p,r,k);
       for(i=0; i<k; i++)
           Kquicksort(A, q[i], q[i+1], k);
       
    }
    
    Dovrebbe funzionare provaci e fammi sapere!
  • Re: [C] modifica quicksort con più pivot

    Grazie mille! chiedo l'ultima cosa adesso sembra quasi funzionare solo che va in crash e non riesco a capire cosa sia dovuto penso che sia colpa del vettore contenente gli indirizzi dei pivot. Mi dite dove sto sbagliando?
    #include <stdio.h>
    #include <stdlib.h>
    
    int Max (int A[],int k)
    {
    	int max=0,i,tmp;
    	for(i=0;i<k-1;i++)
    	{
    		if (max<A[i])
    		{
    			max=A[i];
    		}
    	}
    	return max;
    }
    
    void Swap (int A[], int i, int j)
    {
    	int tmp;
    	tmp=A[j];
    	A[j]=A[i];
    	A[i]=tmp;
    	return;
    }
    int *Kpartition (int *A,int p,int r,int k)
    {
    	int i, j, pivot,z,q,a;
    	int *B=(int*)malloc(k-1*sizeof(int));
    	i=p;
    	j=r;
    	for (z=k-1;z>0;z--)
    	{
    	pivot=Max (A, k);
    	i=0;
    		while (i<=j)
    		{
    			
    			if (pivot==A[i])
    				q=i;
    			if (A[i]>pivot)
    			{
    				Swap(A,i,j);
    				j--;
    			}
    			while (A[j]>pivot)
    				j--;
    			i++;
    		}
    		Swap(A,q,j);
    		B[z]=j;
    		j--;
    		}
    
    	return B;
    }
    void Kquicksort(int A[],int p,int r,int k) 
    {
    	int i;
    	int *q;
    	if(p>=r)
    	{
          for(i=0; i<=7; i++)
    			printf("%d  ",A[i]);
    	  return;
    	}
    	q=Kpartition(A,p,r,k);
    	for(i=0; i<k-1; i++)
    		Kquicksort(A, q[i], q[i+1], k);
    }
    void main ()
    {
    	int A[]={50,10,5,80,4,20,90,2}, n=7;
    	int B[]={0,0};
    	int i,k=3;
    	Kquicksort(A,0,n,k);
    	return;
    }
    So che molto probabilmente è sbagliatissimo allocare il vettore in quel modo perchè tutte le volte che chiamo la funzione me ne alloca un altro nuovo o sbaglio?
    E in oltre mi sono appena accorta che non sempre li ordina giusto penso che non ce la farò mai a consegnarlo giustoooo
  • Re: [C] modifica quicksort con più pivot

    Il vettore che ritorna la Kpartition alla cella 0 deve avere il valore di p.

    I vettori è giusto che siano sempre diversi, forse il problema sta nel rilasciare la memoria quando non ti servono più. Puoi passare alla Kpratition un vettore che allochi nella funzione Kquicksort in modo da poter rilasciare le risorse alla fine della funzione, questo per fare le cose in maniera ordinata. Ma secondo me è un passo che puoi affrontare dopo, adesso è importante prima cosa far funzionare l'algoritmo.
  • Re: [C] modifica quicksort con più pivot

    L'ho fatto ma non funziona lo stesso, non riesco proprio a capire dove sta l'errore!
    Ho sistemato un po la partition ma ora va in crash
    int *Kpartition (int *A,int p,int r,int k)
    {
    	int i, j, pivot, z, q, a;
    	int B[3];
    	i=p;
    	j=r;
    	for (z=k-1;z>=1;z--)
    	{
    	pivot=Max (A, k);
    	i=p;
    		while (i<j)
    		{
    			if (pivot==A[i])
    				q=i;
    			if (A[j]>pivot)
    				j--;
    			if (A[i]>pivot)
    			{
    				Swap(A,i,j);
    				j--;
    			}
    			i++;
    		}
    		if (A[q]>A[j])
    		{
    			Swap(A,q,j);
    			B[z]=j;
    			j--;
    		}
    		else
    			B[z]=q;
    		
    		printf("z=%d\n  ",z);
    		for(i=0; i<=8; i++) 
    		printf("%d  ",A[i]);
    		printf("\n");
    
    		}
    	B[0]=p;
    
    	return B;
    }
Devi accedere o registrarti per scrivere nel forum
10 risposte