begin process at 2012 02 10 08:14:27
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Maths & Algorithmes

 > QUICKSORT - NON RECURSIF

QUICKSORT - NON RECURSIF


 Information sur la source

Note :
8 / 10 - par 1 personne
8,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Maths & Algorithmes Classé sous :tri, quicksort, rapide Niveau :Initié Date de création :03/03/2006 Date de mise à jour :07/03/2006 16:24:08 Vu :8 766

Auteur : nickydaquick

Ecrire un message privé
Site perso
Commentaire sur cette source (37)
Ajouter un commentaire et/ou une note

 Description

  Comme promis , voici une possibilité d'implémentation du Tri rapide sans récursivité. Le principe est simple et est représentatif des appels de fonctions dans le cas de la récursivité. En effet les appels des fonctions sont nuisibles généralement ( à mon avis ) à cause des sauvegardes sur la pile(arguments , adresse de retour , registres) et des réallocations mémoires. Une simple boucle et un " push - pop" des arguments représenté par une file ( ici un tableau avec un _ index) comble parfaitement le mecanisme de la recursivite, qui d'ailleurs ne sert qu'à alleger un code plutôt qu'àa l'optimiser.
   Ceci etant ma première source , j'espère que vous serez indulgents.
            Merci pour vos commentaires, et vos critiques

Source

  • #include <stdlib.h>
  • #define RHASH 10000000
  • void quicksort(int* const tablo, const int first , const int last)
  • {
  • //first = premier index du tableau
  • //last = dernier index du tableau
  • int debut;
  • int fin;
  • int begin;
  • int end;
  • int pivot;
  • int temp;
  • int index=0;
  • int size=0;
  • int capacite = RHASH+2;
  • //allocation de la file
  • int* queue = NULL;
  • int* cursor;
  • int* indexc;
  • queue = (int*)malloc(capacite*sizeof(int));
  • if(queue == NULL)
  • return;
  • cursor = queue;
  • indexc = queue;
  • *(cursor++) = first; //sauvegarde du debut du tablo a trier
  • *(cursor++) = last; //sauvegarde de la fin du tablo a trier
  • index = 0;
  • size = 2;
  • do
  • {
  • debut = *(indexc++); //recuperation de l'indice de debut
  • fin = *(indexc++); //recuperation de l'indice de fin
  • index+=2;
  • if(debut < fin)
  • {
  • begin = debut;
  • end = fin;
  • pivot = tablo[fin];//on prend le dernier element comme valeur pivot
  • do
  • {
  • //progresser jusqu'a un element superieur ou egal au pivot
  • while ( (begin < fin) && (tablo[begin]<=pivot) )
  • begin++;
  • //progresser jusqu'a un element inferieur ou egal au pivot
  • while ( (end > begin) && (tablo[end]>=pivot) )
  • end--;
  • //echanger les 2 elements qui sont dans le mauvais ordre
  • //comparativement au pivot
  • if (begin < end)
  • {
  • temp = tablo[end];
  • tablo[end] = tablo[begin];
  • tablo[begin] = temp;
  • }
  • }while(begin < end);//continuer a parcourir le tablo
  • //mettre le pivot a sa place dans le tableau trie
  • temp = tablo[fin];
  • tablo[fin] = tablo[begin];
  • tablo[begin] = temp;
  • //sauvegarder les indexes des prochains tris a faire
  • // dans les sous-tableaux prochains
  • // a savoir : a gauche du pivot , puis a droite du pivot
  • //sauvegarde du debut du sous-tableau a trier => a gauche du pivot
  • *(cursor++) = debut;
  • //sauvegarde de la fin du sous-tableau a trier => a gauche du pivot
  • *(cursor++) = begin-1;
  • //sauvegarde du debut du sous-tableau a trier => a droite du pivot
  • *(cursor++) = begin+1;
  • //sauvegarde de la fin du sous-tableau a trier => a droite du pivot
  • *(cursor++) = fin;
  • size+=4;
  • if(size==capacite)
  • {
  • capacite += RHASH;
  • cout<<"rehash"<<endl;
  • queue = (int*)realloc(queue,capacite*sizeof(int));
  • cursor = queue;
  • indexc = &cursor[index];
  • if(queue == NULL)
  • return;
  • }
  • }
  • }
  • while(index<size);
  • cursor = NULL;
  • indexc = NULL;
  • free(queue);
  • }
#include <stdlib.h>
#define RHASH	10000000

void quicksort(int* const tablo, const int first , const int last)
 {
	//first = premier index du tableau
	//last   = dernier index du tableau
	int debut;
	int fin;
        int begin;
	int end;
	int pivot;
	int temp;

	int index=0;
	int size=0;
	int capacite = RHASH+2;

	//allocation de la file
	int* queue = NULL;
	int* cursor;
	int* indexc;
	
	queue = (int*)malloc(capacite*sizeof(int));
		
	if(queue == NULL)
		return;

	cursor = queue;
	indexc = queue;

	*(cursor++) = first; //sauvegarde du debut du tablo a trier
	*(cursor++) = last;	//sauvegarde de la fin du tablo a trier
	index = 0;
	size = 2;

	do
	{
		debut   = *(indexc++);   //recuperation de l'indice de debut
		fin	= *(indexc++);	//recuperation de l'indice de fin

		index+=2;

		if(debut < fin)
		{
			begin	= debut;
			end		= fin;
			pivot	= tablo[fin];//on prend le dernier element comme valeur pivot

			do
			{
				//progresser jusqu'a un element superieur ou egal au pivot
				while ( (begin < fin) && (tablo[begin]<=pivot) )
					begin++;
				//progresser jusqu'a un element inferieur ou egal au pivot
				while ( (end > begin) && (tablo[end]>=pivot) )
					end--;

				//echanger les 2 elements qui sont dans le mauvais ordre
				//comparativement au pivot
				if (begin < end) 
				{
					temp			= tablo[end];
					tablo[end]		= tablo[begin];
					tablo[begin]	= temp;
				}

			}while(begin < end);//continuer a parcourir le tablo

			//mettre le pivot a sa place dans le tableau trie
			temp			= tablo[fin];
			tablo[fin]		= tablo[begin];
			tablo[begin]	= temp;


			//sauvegarder les indexes des prochains tris a faire
			// dans les sous-tableaux prochains
			// a savoir : a gauche du pivot , puis a droite du pivot

			//sauvegarde du debut du sous-tableau a trier => a gauche du pivot
			*(cursor++) = debut;
			//sauvegarde de la fin du sous-tableau a trier => a gauche du pivot
			*(cursor++) = begin-1;

			//sauvegarde du debut du sous-tableau a trier => a droite du pivot
			*(cursor++) = begin+1;
			//sauvegarde de la fin du sous-tableau a trier => a droite du pivot
			*(cursor++) =  fin;
			size+=4;

			if(size==capacite)
			{
				capacite += RHASH;
				cout<<"rehash"<<endl;
				queue = (int*)realloc(queue,capacite*sizeof(int));
				cursor = queue;
				indexc = &cursor[index];
				if(queue == NULL)
				    return;
			}
		}
	}
	while(index<size);
	cursor = NULL;
	indexc = NULL;
	free(queue);
}

 Conclusion

        Enjoy it.... :D


 Historique

07 mars 2006 16:21:42 :
En regard a tous vos commentaires voici une seconde implementation du quicksort non-recursif . Voici les comparaisons temporelles : Nombres d'elements : 1 000 000 en random() 1- quicksort no-recursif : +/- 647.82 ms 2- qsort() : +/- 1237.76 ms les performances sont modifies par la valeur de hashage-rehashage ( RHASH ) Machine test: Pentium 4 CPU 1.66GHz, 496Mb RAM , FSB 400Mhz , XPHomeSP1 Merci et aurevoir
07 mars 2006 16:24:08 :
En regard a tous vos commentaires voici une seconde implementation du quicksort non-recursif . Voici les comparaisons temporelles : [Nombres d'elements === 1 000 000 en random()] ... [quicksort non-recursif === +/- 647.82 ms ]... [qsort() === +/- 1237.76 ms ]. Les performances sont modifies par la valeur de hashage-rehashage (RHASH) ... [Machine test: Pentium 4 CPU 1.66GHz, 496Mb RAM , FSB 400Mhz , XPHomeSP1]. Merci et aurevoir

 Sources du même auteur

Source avec Zip LE QUICKSORT NON-RECURSIF ET L'IMPACT DE L'INSERTIONSORT SUR...
ALGORITHME D'EUCLIDE ETENDU

 Sources de la même categorie

Source avec Zip UN EXAMPLE D'APPLICATION EN CUDA DE L'ALGORITHME DE SCAN POU... par oguzaras
Source avec Zip Source avec une capture CHIFFREMENT DE VIGENERE par lajouad
Source avec Zip Source avec une capture ANALYSE SYNTAXIQUE par lajouad
Source avec Zip Source avec une capture STRUCTURE D'UNE MATRICE PAR LES LISTE LINÉAIRE (NON CONTUGUS... par benzarabel
Source avec Zip Source avec une capture DESSINER UNE ARBRE BINAIRE( MODE CONSOLE): par benzarabel

 Sources en rapport avec celle ci

Source avec Zip COMBSORT ALGORITHME DE TRI SIMPLE RAPIDE NON-RECURSIF par xtremejames183
Source avec Zip LE QUICKSORT NON-RECURSIF ET L'IMPACT DE L'INSERTIONSORT SUR... par nickydaquick
Source avec une capture COMPARAISON TRI + TEST CPU par lucastok2
Source avec Zip ALGORITHMES DE TRIS par NNAS
CSORTEDARRAY<TEMPLATE> VISUAL C++ MFC par shenron666

Commentaires et avis

Commentaire de vecchio56 le 03/03/2006 10:40:01 administrateur CS

Tu dis que les appels de fonctions sont pénalisants à cause des sauvegardes sur la pile et des réallocations mémoire. Qu'est ce que tu entends par réallocations mémoire?

Commentaire de nickydaquick le 03/03/2006 17:47:39

reallocations => allocations + desallocations
lorsque tu fais un appel de fonctions, a moins que je ne me trompe , l'adresse de retour de la fonction appelante , les arguments de la fonction appelee sont mis en memoire ainsi que les variables. Ce qui veut dire qu'a chaque appel ton programme fait une demande de memoire. Puis tu desalloues cette memoire au retour de la fonction. Un probleme que tu pourrais rencontrer c'est une limitation de ta recursivite dans l'echec d'une allocation pour un appel recursif. Dans mon programme tu te limiterais a moins d'appels d'allocations memoire.
En fait les appels recursifs du quicksort sont remplaces ici par des acces memoires ( notre espace est deja alloue d'un bloc dans le tas) et des test plutot qu'a des allocations-desallocations memoires repetitives
     J'espere avoir repondu a ta question. Merci et aurevoir

Commentaire de vecchio56 le 03/03/2006 17:51:23 administrateur CS

Je sais ce qu'est une réallocation, mais dans le cas de la récursivité, tout se passe dans la pile, donc ya jamais d'allocation de mémoire ailleurs

Commentaire de nickydaquick le 03/03/2006 18:16:23

une allocation memoire peut se faire soi dans la pile soi dans le tas, l'un dans l'autre une demande est toujours faite... tu ne crois pas ?
          Merci

Commentaire de vecchio56 le 03/03/2006 18:37:09 administrateur CS

Tu dis "à cause des sauvegardes sur la pile (...) et des réallocations mémoires" donc je me disais que tu parlais d'allocations ailleurs que dans la pile

Commentaire de nickydaquick le 03/03/2006 18:40:11

Excuse - moi si je n'ai pas ete tres clair dans mes propos... Je suis heureux que nous nous comprenions :D .
   Merci encore pour ta critique

Commentaire de shenron666 le 04/03/2006 10:09:58

Source intéressante de par ton approche ;-)

Il faudrait faire des tests de rapidité entre ta fonction et la même en mode récursif pour voir s'il y a réellement une différence de vitesse à ton avantage.
Surtout que tu  parles de réallocation mais tu en fais toi aussi avec "queue"

Dommage que tu n'utilises pas la stl mais ce n'est qu'un détail

Commentaire de nickydaquick le 04/03/2006 16:23:52

   Merci pour ton commentaire Shenron666. En effet il faudrait faire dess tests de rapidite , mais je suis pas mal sur que cette implementation serait plus rapide. En ce qui concerne
mon allocation memoire avec "queue" c'est vrai c'en est une , mais elle n'a lieu qu'une seule fois, contrairement a des appels recursifs.
  En ce qui concerne la STL , j'aurais pu utilise la conteneur deque<int> , mais la encore j'aurais fait appel a des fonction push_back, front , et pop_front ce qui n'est pas tres interessant. En gros je voulais limiter le plus possible les appels de fonction . Nous appelons ca chez nous : La programmation en DUR :D ... mdr
           Salut

Commentaire de vecchio56 le 04/03/2006 16:54:30 administrateur CS

Les allocations dans la pile sont bien moins couteux que dans le tas. Mais ici il n'y a c'est vrai qu'une allocation dans le tas, ce qui doit sans doute compenser en général

Commentaire de shenron666 le 07/03/2006 10:12:29

J'ai copié collé ton tri dans un programme pour le tester et voir s'il était plus rapide qu'un tri que j'avais fait : http://www.cppfrance.com/code.aspx?ID=33969

ton tri plante avec plus de 100000 éléments
en debug, ton size++ dépasse taille

j'ai également noté que ton allocation est énorme par rapport à la taille du tableau initial

mon code de test est le suivant :
#define TAILLE_TABLEAU 100000L
DWORD test_tri()
{
int* arTest = new int[TAILLE_TABLEAU];

srand(GetTickCount());
for(int i=0; i < TAILLE_TABLEAU; i++)
arTest[ i ] = rand();

DWORD tStart = GetTickCount();
TriSortNonRecursif(arTest, 0, TAILLE_TABLEAU - 1);
return (GetTickCount() - tStart);
}

Commentaire de BruNews le 07/03/2006 10:28:48 administrateur CS

Vraiment je ne copprends pas votre problème.
Le tableau à trier existe déjà puisqu'on le reçoit en param donc aucun prob mémoire vu q'il n'y a aucune alloc à faire pour un quicksort, suffit de regarder l'implem de qsort() de la CRT.

Commentaire de shenron666 le 07/03/2006 11:30:29

Oui bah l'implémentation qsort de la CRT je veux pas dire mais c'est un peu de la merde
enfin juste un peu ^^
tu veux un exemple ? ligne 249 : "goto recurse;" arghhhh
euh, c'est du basic ?

non sans dec' même la source que j'ai déposé est plus rapide sur un tableau de 1 millions d'int :
- qsort : 297 ms
- CSortedArray : 172 ms
un bon 70% de différences

enfin bon, je sais qu'il y en a à qui ça suffira mais à mon taf je traite des centaines de Mo de données et on en arrive à plusieurs Go, avec des progs en C++, MFC, POO le qsort est comment dire ? trop léger
bah c'est du C quoi (qui a dit basic ? ^^)

Commentaire de BruNews le 07/03/2006 11:53:49 administrateur CS

qsort est un algo générique, on en a le code donc on le dévie pour le spécialiser:
http://www.cppfrance.com/code.aspx?id=11151

'goto' indique que c'est de la daube ? alors change de taf, un cpu ne comprend que cela les sauts de code, pas parce qu'on ne les voit pas que le compilo écrira autre chose.

Commentaire de shenron666 le 07/03/2006 12:16:10

goto est à éviter, oui le cpu fait des sauts qu'on ne voit pas, il n'empêche qu'un code orienté objet propre et maintenable ne contient pas de goto
c'est une règle fondamentale du C++ en tout cas
le fait est que le C++ n'a pas récupéré du C que des bonnes choses

ton programme est en C ou ne contient rien de particulier en C++
tu utilises une structure pour stocker tes données
si tu utilisais une classe, pourrais-tu encore utiliser qsort pour trier tes données ?
pire encore si tu stockes des pointeurs vers des objets

pour en revenir au prog de nickydaquick, je trouve que c'est son approche qui est intéressante
il n'y a pas qu'une seule et unique manière de programmer donc moi ça me plait de voir des sources comme la sienne
reste à débugguer le code ^^

Commentaire de nickydaquick le 07/03/2006 12:37:01

MErci pour tous vos commentaires... Je tenais a te dire shenron666, que ce code a ete depose ici a titre illustratif et comprehensif. La taille du tableau est uniquement suggestif alors arrete de faire des copier - coller et inspire toi de ce code pour ameliorer le tien. Toi ki fait par exemple des tests de rapidite , arrete de nous dire si le test plante ( parce que tu n'as certainement pas determine la taille du heap a reserver au depart du prog ) , et donne nous des resultats temporels
   Merci

Commentaire de shenron666 le 07/03/2006 13:16:18

"et donne nous des resultats temporels"
euh, tu as lu mon post ? c'est fait, à titre "illustratif et comprehensif" si tu veux

si ton code n'est pas exempt de bug il va causer des problèmes dans le heap, et si tu déposes un code sans zip, comment je le récupère sans faire un copier coller ?
ton code fait une allocation :
    const int taille = 3*(last-first+1);
    int* queue = NULL;
    
    queue = new int [taille];

et lorsque tu écris dans queue, tu dépasses la "taille" que tu as allouée, là il y a un gros problème puisque tu vas aller écraser d'autres données
tu me dis que c'est à moi de débugguer ton code ? :-/

quand à déterminer la taille du heap à réserver... ????
tu peux m'expliquer ?
non mais je demande parceque qsort fonctionne, lui, :

#define TAILLE_TABLEAU 100000L
DWORD test_tri()
{
int* arTest = new int[TAILLE_TABLEAU];

srand(GetTickCount());
for(int i=0; i < TAILLE_TABLEAU; i++)
arTest[ i ] = rand();

DWORD tStart = GetTickCount();
qsort(arTest, TAILLE_TABLEAU, sizeof(int), qsort_compare);
return (GetTickCount() - tStart);
}

Commentaire de nickydaquick le 07/03/2006 14:57:03

En fait je viens de comprendre ton pb, tu voudrais un code que tu puisse carrement coller sans avoir a comprendre quoi que ce soit , faire un test si ca marche Bingo. Dans ce cas demande le moi je te le donne , optimisé et avec les comparaisons temporels en ms.
       J'attends de tes news

PS: De nos jour les gens ne savent plus la signification du mot algorithme ...

Commentaire de shenron666 le 07/03/2006 15:16:47

attends, si t'es pas prêt à accepter les critiques "non positives" concernant ton programme arrêtes de programmer
là je t'ai prévenu qu'il y avait un bug, tu le prend mal, et c'est moi qui ait un problème ?
si les tests temporels te posent problème tu n'as qu'a faire un tri bulle, le qsort est intéressant pour sa rapidité (quand il fonctionne) et comme l'a dit BruNews, pourquoi l'avoir recodé si le qsort des CRT existe ?
ah mais oui ok j'ai compris, en fait c'est pas un code source c'est un algo que tu as déposé
mea culpa, je préfère m'arrêter là
bonne continuation

Commentaire de nickydaquick le 07/03/2006 16:07:31

  Ok Shenron , tu gagnes , je vais te mettre un version rapide du Tri rapide , sans bug ... tu pourras faire les tests. Toutes mes excuses si je t'ai mal compris mais mon but etait initialement de montrer un algorithme , donc une logique revue du quicksort. Je recorrigerait donc ma source , pour que tu puisses faire des test sur autant de nombres que tu veux. Je mettrai aussi des resultats en comparatif avec la fonction qsort() de vc++6.0. Donne moi juste 5 minutes.

Commentaire de BruNews le 09/03/2006 15:17:25 administrateur CS

http://bnmvp.free.fr/SortInt.zip

Pourriez vous comparer avec vos procédures ? merci d'avance.
Je n'affiche que les millisecondes du tri pour 100 000 ou 1 000 000, pour le résutat trié dans listbox suffit de remettre les lignes du code en service mais pas utile ici.

svp ne ralez pour l'asm, il n'entre pour rien dans le tri, juste pour fournir zip minuscule.

Commentaire de fuliculi le 09/03/2006 15:30:01

L'algo le plus efficace à ce jour (il me semble) est le tri à panier. Ca ne s'applique qu'au tri de nombres entiers (pas de réel) et c'est terriblement simple et rapide.

Commentaire de BruNews le 09/03/2006 15:48:47 administrateur CS

Un exemple serait le bienvenu stp.

Commentaire de fuliculi le 09/03/2006 16:04:23

Allez hop, c'est codé à l'arrache mais j'ai pris le temps de tester un peu quand même...

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

void tri(long *tab, long size)
{
if (size<=0 || tab==NULL)
return;

long min = tab[0];
long max = tab[0];
long i, j;

// Recherche les bornes de la liste
for (i=0; i<size; i++)
{
if (tab[i]<min) min=tab[i];
if (tab[i]>max) max=tab[i];
}

if (min==max)
return;

// Un panier par valeur possible entre le min et le max
long *paniers = new long[max-min+1];
memset(paniers, 0, (max-min+1)*sizeof(long));

// Ajouter un jeton dans le panier de la valeur (min = premier panier, max = dernier panier)
for (i=0; i<size; i++)
paniers[tab[i]-min]++;

long numVal = 0;

// Remplir le tableau d'entrée avec les paniers en partant du premier (ou du dernier pour un tri décroissant)
for (i=0; i<max-min+1; i++)
// Copier autant de fois la valeur du panier qu'il contient de jetons
for (j=0; j<paniers[i]; j++)
tab[numVal++] = min+i;

delete [] paniers;
}

//#define PRINT

void main (void)
{
long max = 1000000;
long *values = new long[max];
long i;

srand((unsigned)time(NULL));

for (i=0; i<max; i++)
      values[i] = (long)rand();

#ifdef PRINT
for (i=0; i<max; i++)
printf("in  : %d ", values[i]);
#endif

long startTime = clock();
tri(values, max);
long stopTime = clock();

#ifdef PRINT
for (i=0; i<max; i++)
printf("out : %d\n", values[i]);
#endif

printf("Temps ecoule : %d ms", stopTime - startTime);

delete [] values;
}

Commentaire de fuliculi le 09/03/2006 16:18:52

Pour info, j'ai ces temps là avec mon code en release :
15 ms pour 1 millions de valeurs
219 ms pour 10 millions de valeurs

(Pentium 4 2.6GHz)

Y'a moyen d'optimiser en remplaçant certains long en int, char, short (selon vos valeur) mais attention, la plupart doivent être conservés pour accepter les long tableaux (int=65536 valeurs max)

Commentaire de fuliculi le 09/03/2006 16:27:15

J'ai ces temps là avec l'algo de nickydaquick

400 ms pour 1 millions de valeurs (26x plus de temps)
5200 ms pour 10 millions de valeurs (24x plus de temps)

Et vous?

Commentaire de fuliculi le 09/03/2006 16:29:59

Pardon (je ne spam pas) j'ai oublié l'option d'optimisation (/O2), j'ai donc 140ms contre 3500ms avec 10 millions de valeurs.

Commentaire de BruNews le 09/03/2006 23:00:53 administrateur CS

Je viens de tester, nickel pour la vitesse (presque 12 fois plus vite que celui que j'ai mis en lien).
Dommage qu'il y ait cette alloc mémoire qui peut rater (par exemple sur une plage full 32 bits on ne passe pas) mais enfin devrait aller dans beaucoup de cas, vraiment très bien.

Commentaire de fuliculi le 10/03/2006 09:31:32

En effet, il a ses limites. J'ai un manque de mémoire virtuelle si je teste avec 100 millions de valeurs.

Pour la partie photonmapping de mon raytracer, je devais trier les photons dans l'ordre de proximité d'un point. Le problème est que les distances sont en float (besoin de précision) et l'algo ne gère que les entiers. J'ai donc combiné deux algo de tri pour pouvoir profiter des performances du tri à panier. Pour trier des float, donc, je place les float dans des paniers qui ne correspondent pas à une valeur entière mais à une plage de valeurs réelles (bornées) et je remplis. Ensuite, je tri le contenu de chaque panier (tri à bulle) et je n'ai plus qu'à les vider comme dans l'algo que j'ai codé. Selon les cas, si vous n'avez pas besoin d'un tri parfait, on peut se limiter au tri à panier sans second tri.

Une autre solution à laquelle j'ai pensée consiste à convertir les float en entier avec un facteur (int = float *1000 par exemple). La encore, le tri n'est pas parfait (manque de précision) mais ça dépend encore de l'usage que l'on souhaite en faire. Je n'ai pas pris le temps de tester cette solution.

Commentaire de Noxk le 11/03/2006 16:56:41

shenron666, ton algo de tri je viens de le tester il ne marche pas, certe il est rapide mais en sorti c'est pas trié, il y a certainement quelque chose a revoir.

Commentaire de Noxk le 13/03/2006 13:35:03

Je viens de tester les algo de quicksort sur 10 000 000 d'int dans l'ordre d'arrivé, c'est :

BruNews : 1.485 seconde
le mien : 1.578
nickydaquick : 1.687
qsort : 2.859

J'ai pas testé celui de Fuliculi vu que ce n'est pas un quicksort bien que pour les int il soit plus interressant que le notre.

Commentaire de nickydaquick le 14/03/2006 01:52:00

Je suis desole mais tes temps ne sont pas exacts sur le mien ( mon ordi ) je suis en dessous des 1.6 sur un random de 10 millions de int , si tu utilises une tranche de reallocation moindre ( de l'ordre de la centaine de milliers )

Commentaire de fuliculi le 14/03/2006 08:47:30

De quel algo parle tu? je pense que le mieux est de donner les temps de chaque algo (qui fonctionne) sur le même ordi (et même conditions) pour pouvoir comparer, et éventuellement la config de m'ordi (genre si t'as 16Mo de RAM, faut pas s'étonner que ce soit plus lent ;)
L'idéal est de faire quelques tests à blanc (histoire de récupérer de la mémoire inutilisée) et de donner la moyenne, le min et le max des temps suivants, et ce, pour chaque algo.
Si quelqu'un trouve l'envie et le temps, ça m'intéresserait :)

Commentaire de Noxk le 14/03/2006 09:28:10

Salut Nicky,

J'ai effectué les test comme tu l'indiquais et les temps donnés pour le tri sont reellement meilleur mais y a un bogue, le tri est partiellement effectué. Ceci provient du fait que tu as oublié de remettre cursor a sa position final quand tu realloues la memoire.

Ca se corrige en remplacant les "*(cursor++)" par des  "*(cursor + i++)" et ensuite dans la condition "if" mettre "*(cursor + i);"


Mais meme avec ca on remarque un probleme, tu rentres trop souvent dans la condition "if" de realloc et ca bouffe un temps enorme.Ce que je te propose, vu que tu utilise dans ton algo une pile, que tu ne depiles jamais, c'est justement s'en servir comme d'une pile qu'on depile et plus besoin de realloué la memoire, le seul probleme reside dans le fait de definir une taille de la pile suffisante.

Je me permets de mettre le code corrigé a ma manière et qui ressemble un peu a celui que j'ai écrit sur l'aspect pile/depile.

#define RHASH    100000
  
void quicksort(int* const tablo, const int first , const int last)
  {
     //first = premier index du tableau
     //last = dernier index du tableau
     int debut;
     int fin;
         int begin;
     int end;
     int pivot;
     int temp;
int i=0;
  
     int index=0;
     int size=0;
     int capacite = RHASH+2;
  
     //allocation de la file
     int* queue = NULL;
     int* cursor;
     int* indexc;
    
     queue = (int*)malloc(capacite*sizeof(int));
        
     if(queue == NULL)
         return;
  
     cursor = queue;
     indexc = queue;
  
     *(cursor + i++) = first; //sauvegarde du debut du tablo a trier
     *(cursor + i++) = last;    //sauvegarde de la fin du tablo a trier
     index = 0;
     size = 2;
  
     do
     {
         //debut = *(indexc++); //recuperation de l'indice de debut
         //fin    = *(indexc++);    //recuperation de l'indice de fin
fin    = *(cursor + --i);    //recuperation de l'indice de fin
debut = *(cursor + --i); //recuperation de l'indice de debut
        
  
         index+=2;
  
         if(debut < fin)
         {
             begin    = debut;
             end      = fin;
             pivot    = tablo[fin];//on prend le dernier element comme valeur pivot
  
             do
             {
                 //progresser jusqu'a un element superieur ou egal au pivot
                 while ( (begin < fin) && (tablo[begin]<=pivot) )
                     begin++;
                 //progresser jusqu'a un element inferieur ou egal au pivot
                 while ( (end > begin) && (tablo[end]>=pivot) )
                     end--;
  
                 //echanger les 2 elements qui sont dans le mauvais ordre
                 //comparativement au pivot
                 if (begin < end)
                 {
                     temp            = tablo[end];
                     tablo[end]      = tablo[begin];
                     tablo[begin]    = temp;
                 }
  
             }while(begin < end);//continuer a parcourir le tablo
  
             //mettre le pivot a sa place dans le tableau trie
             temp            = tablo[fin];
             tablo[fin]      = tablo[begin];
             tablo[begin]    = temp;
  
  
             //sauvegarder les indexes des prochains tris a faire
             // dans les sous-tableaux prochains
             // a savoir : a gauche du pivot , puis a droite du pivot
  
             //sauvegarde du debut du sous-tableau a trier => a gauche du pivot
             *(cursor + i++) = debut;
             //sauvegarde de la fin du sous-tableau a trier => a gauche du pivot
             *(cursor + i++) = begin-1;
  
             //sauvegarde du debut du sous-tableau a trier => a droite du pivot
             *(cursor + i++) = begin+1;
             //sauvegarde de la fin du sous-tableau a trier => a droite du pivot
             *(cursor + i++) = fin;
             size+=4;
  
     //        if(size==capacite)
     //        {
     //            capacite += RHASH;
     //            cout << "rehash" << endl;
     //            queue = (int*)realloc(queue,capacite*sizeof(int));
     //            cursor = queue;
     //            indexc = &cursor[index];
//*(cursor + i);
     //            if(queue == NULL)
     //             return;
     //        }
         }
     }
     while(index<size);
     cursor = NULL;
     indexc = NULL;
     free(queue);
}

Reste plus qu'a trouver un matheux pour trouver la formule de la taille de la pile en rapport avec celle du tableau :)

Sinon au niveau des score maintenant tu es meilleur que le mien mais reste tres legerement en dessous de ceux de BruNew.

Commentaire de shenron666 le 14/03/2006 12:01:37

Salut les gens, bon j'ai pris le temps ce matin de venir aux nouvelles et j'ai vu le post de Noxk
J'avais un big problème avec mon algo lorsqu'on triait 2 fois de suite un tableau : dépassement de pile
du coup je n'avais pas fait attention qu'en plus je n'avais pas mis la bonne version en ligne qui, en effet ne trait pas
j'ai pas l'air con -__-

bref, j'ai corrigé à partir d'un algo repris sur un site très bien fait :
http://www.cs.ubc.ca/spider/harrison/Java/sorting-demo.html

le tri de 10 millions de valeurs me donne les temps suivants (en ms) :
nickydaquick (RHASH = 10000) : 797
Brunews : 2360
qsort CRT : 2906
mon tri récursif : 4750
avec la std : 1187 (std::sort d'un vector<int>)
avec la std : 2671 (std::sort_heap d'un vector<int>)

j'ai aussi essayé de trier plusieurs fois de suite un tableau, vu que je rencontrais des problèmes avec mon algo
bizarrement le tri de nickydaquick prend de plus en plus de temps, je n'ai pas regardé pourquoi
Le tri de Brunews s'en sort très bien

au final je trouve l'algo de brunews plutot performant, dommage que je sois si buté sur les goto ^_^
je me répète en disant que je trouve la méthode de nickydaquick intéressante
dès que j'aurai plus de temps je regarderai si je peux faire la même chose pour un CArray

Commentaire de Maroi le 29/04/2010 20:41:39

Salut,
Est ce que vous pouvez donner un exemple de quicksort non récursif pr les réels?
Merci bcp

Commentaire de shenron666 le 29/04/2010 20:53:06

je te conseille de passer par la stl en utilisant par exemple un std::vector<double> et la méthode de tri std::sort

Commentaire de Maroi le 30/04/2010 12:51:48

Merci bcp pour votre réponse, mais en fait je cherche un programme en C??

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

tri rapide (quicksort) et/ou tri par tas(heapsort) urgent [ par mersniyassine ] je trouve une difficulté a simuler graphiquement en C ces 2 trisya t-il quelqu'un qui peut me fournir un code.c compilable sur Turbo C qui effectue u tri alphabétique ultra rapide de chaines de caractères de longueur variable [ par mslider ] -- Bonjour, je sais que c'est un forum dédié au C mais je vais parler de pascal. En effet je connais bien ce langage et je l'ai utilisé pour trier a tri rapide(quicksort)+tri par tas(heapsort)+simulation graphique [ par mersniyassine ] mon stage d'ete comporte une simulation graphique du tri par tas et du tri rapide, je trouve une difficulté a gerer le code source,merci bien de me fo encore un pb en c svp....... [ par natacha86 ] j'ai essayer de s&#233;parer les fonctions mais ca ne marche pas...#include &lt;conio.h&gt;#include &lt;stdio.h&gt;#include &lt;string.h&gt;#include & a l aiiiiiiiiidddddeeeeeeeee [ par natacha86 ] je ne comprend pas pkoi le programme une fois qu'il a lanc&#233; le premier choix du menu a la fin il ne reviens pas au menu, il s'arrete directement, menu avec un switch [ par natacha86 ] je ne comprend pas pkoi le programme une fois qu'il a lanc&#233; le premier choix du menu a la fin il ne reviens pas au menu, il s'arrete directement, aide par rapport a l'appel d'une méthode [ par natacha86 ] quel est le probleme de ma m&#233;thode init_tab ? le programme s'arrete aprse etre pass&#233; dans cette m&#233;thode, il plante, et ne rentre pas da help une fonction qui a besoin de vous [ par natacha86 ] Re bonjour a tout le monde, voila j'ai mis tout le prog si vous voulez tester, en fait le pb viens de la fonctino tri_shell(), je ne sais pas pkoi ell tri des sommets [ par erazor ] bon apres avoir lutt&#233; pendant des jours avec un alg ode tri foireu je souhaiterai que quelqu'un me donne si posible une methode pour trier les so c++ [ par kisskool94 ] salut a tous les webmaster je suis novice et souhaiterais avoir des renseignements sur le principe et les m&#233;thodes du c++ en quoi ca consiste est


Nos sponsors


Sondage...

CalendriCode

Février 2012
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
272829    

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,499 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales