J'ai une gamme d'arêtes, qui est définie comme une gamme de titres de type C de double, où tous les 4 doubles définissent un bord, comme celui-ci: donc donc je veux utiliser < Code> STD :: Trier () Code> Pour trier la longueur de bord. S'il s'agissait d'un Mais dans ce cas, la double matrice a une taille de bloc qui n'est pas exprimée par le type de pointeur. Pour des raisons de performance (mémoire-utilisation et CPU), disons qu'il est indésirable de créer de nouveaux tableaux ou de transformer la matrice en quelque sorte. Pour des raisons de performance à nouveau, disons que nous voulons utiliser est-il possible de appeler Une approche évidente est d'essayer de forcer -Cast le pointeur: p> mais comment puis-je vous assurer que les données sont alignées correctement? En outre, comment puis-je vous assurer qu'il sera toujours aligné correctement sur toutes les plates-formes et toutes les architectures? P> ou puis-je utiliser un Struct Edge {Double X1, Y1, X2, Y2; }; EDGE * P; CODE>, je serais bon d'aller. P> Qsort () Code> Vous permet de spécifier explicitement la taille du bloc, mais std :: Trier () Code> Induit la taille de bloc forte> par le type de pointeur. P> std :: try () code> au lieu de qsort () code>. P> std :: try () code> sans gaspiller un seul cycle de la CPU sur la transformation des données? P> Approche possible: H2>
Typef double [4] bord; code>? P> p>
10 Réponses :
std::array< std::array<int, L>, N > array; // or std::vector< std::vector<int> > if N*L is not a constant std::sort( array.begin(), array.end() );
Ensuite, utilisez qsort code>, à l'aide de STD :: Trier n'est pas un moyen plus rapide.
#ifdef NDEBUG #define WAS_NDEBUG #undef NDEBUG #endif #define NDEBUG #include <algorithm> #ifdef WAS_NDEBUG #undef WAS_NDEBUG #else #undef NDEBUG #endif
Je ne comprends pas. Comment cela gère-t-il la nature du bloc de la matrice?
Vous pouvez utiliser un "itérateur de filet" pour cela. Un "itérateur Stride" enveloppe un autre itérateur et une taille d'une étape entière. Voici un croquis simple:
int array[N*L];
std::sort( make_stride_iter(array,L),
make_stride_iter(array,L)+N );
N'est-ce pas && A C ++ 0x Thingy? On dirait une bonne solution, je vais vérifier.
"N'est-ce pas && A c ++ 0x Thingy?" - Droite, mon erreur. Je l'ai changé.
Ouch, c'est un code de code. Boost :: iterator_Adaptor Code>: boost.org/doc/libs/1_40_0/libs/iterator/doc/...
Ouais, en utilisant une bibliothèque d'adaptateur itérateur semble être une bonne idée. D'ailleurs, je pense que les itérateurs de Stride devraient faire partie de STD :: ou au moins Boost :: également. ;)
Je ne sais pas si vous pouvez obtenir le même résultat sans beaucoup plus de travail. triera tous les éléments de STD :: Trier () Code> est effectué pour trier les séquences d'éléments définis par deux itérateurs d'accès aléatoire. Malheureusement, il détermine le type de l'élément de l'itérateur. Par exemple: tableau code>. Le problème est qu'il suppose que l'inscription, l'incrément, la décrémentation et d'autres indexation em> les opérateurs de l'itérateur sur des éléments de la séquence. Je crois que la seule façon dont vous pouvez trier des tranches de la matrice (je pense que c'est ce que vous êtes après), est d'écrire un itérateur qui index basé sur l code>. C'est ce que Sellibitze a effectué dans le Stride_iterator (code> réponse code> / a>. p> p>
Je ne me souviens pas exactement comment faire cela, mais si vous pouvez fausse de fausses fonctions anonymes, vous pouvez créer une fonction COMP (L) qui renvoie la version de Comp pour les tableaux de longueur ... de cette façon de devenir Un paramètre, pas un global, et vous pouvez utiliser qsort. Comme les autres ont mentionné, sauf dans le cas où votre tableau est déjà trié, ou à l'envers ou quelque chose, qsort va être à peu près aussi rapide que tout autre algorithme. (Il y a une raison pour laquelle il s'appelle Quicksort après tout ...) P>
Que diriez-vous d'avoir un vecteur de réorganisation? Vous initialisez le vecteur avec 1..n / l, pass std :: Trier un comparateur qui compare des éléments I1 * L..I1 * L + L à I2 * L..I2 * L + L, et lorsque votre vecteur est correctement trié , réorganiser le tableau C en fonction de la nouvelle commande. P>
En réponse à Commentaire: Oui, les choses sont compliquées, mais cela peut être une bonne complication! Jetez un coup d'oeil ici . P>
Les choses sont compliquées si vous n'utilisez pas de matrice supplémentaire (ce que je ne le ferai pas).
Il ne fait partie d'aucune norme ANSI, ISO ou POSIX, mais certains systèmes fournissent le alternativement, si vous n'avez pas qsort_r () code> fonction, ce qui vous permet de passer un paramètre de contexte supplémentaire à la fonction de comparaison. Vous pouvez ensuite faire quelque chose comme ceci: qsort_r code>, vous pouvez utiliser le Callback (3) code> package de la bibliothèque FFCAlT pour créer des fermetures à l'exécution. Exemple: P> #include <callback.h>
void comp_base(void *data, va_alist alist)
{
va_start_int(alist); // return type will be int
int L = (int)data;
const void *a = va_arg_ptr(alist, const void*);
const void *b = va_arg_ptr(alist, const void*);
// Now that we know L, compare
int return_value = comp(a, b, L);
va_return_int(alist, return_value); // return return_value
}
...
// In a function somewhere
typedef int (*compare_func)(const void*, const void*);
// Create some closures with different L values
compare_func comp1 = (compare_func)alloc_callback(&comp_base, (void *)L1);
compare_func comp2 = (compare_func)alloc_callback(&comp_base, (void *)L2);
...
// Use comp1 & comp2, e.g. as parameters to qsort
...
free_callback(comp1);
free_callback(comp2);
Arkadiy a la bonne idée. Vous pouvez trier en place si vous créez un tableau de pointeurs et triez cela: sortie: p>
remplacer int * buf = neuf int [nombre]; avec int * buf = neuf int [longueur]; La réponse d'Arkady était correcte, mais je voulais une solution sans un deuxième tableau. Je vais accepter sa réponse comme étant la meilleure solution 'Couse qu'il a proposé l'idée originale.
Beaucoup de ces réponses semblent trop excédentaires. Si vous devez vraiment le faire de style C ++, en utilisant l'exemple de JMUCCHIELLO:
sort((Block<4> *)&array[0], (Block<4> *)&array[NN]);
Cela nécessite que la longueur soit connue au moment de la compilation, cependant.
pas difficile à modifier autrement. De l'exemple, je l'ai basé sur, c'est.
Pour la nouvelle question, nous devons passer dans Nous pouvons accomplir les deux en réinterprétant simplement notre double Array comme s'il s'agissait d'un tableau de 4 doubles. Faire ceci: p> ne fonctionne pas, car vous ne pouvez pas attribuer de tableau, et ou, sinon c ++ 11: p> satisfait aux deux exigences. Ainsi: p> Si vous êtes préoccupé par l'alignement, peut toujours affirmer qu'il n'y a pas de remplissage supplémentaire: P> trier () code> une sorte d'itérateur qui ne nous laissera pas seulement comparer les bonnes choses (c'est-à-dire veiller à prendre 4 étapes via notre double [] code> à chaque fois au lieu de 1) mais échangez également les bonnes choses (c.-à-d. Swap 4 double code> s au lieu d'un). échange code> devra. Mais ce faisant: p> static_assert(sizeof(Edge) == 4 * sizeof(double), "uh oh");
Merci, je viens de voir la réponse. Pouvons-nous être sûrs qu'une telle structure est toujours alignée correctement? Est-il défini par la norme ou est-il laissé à la mise en œuvre? De plus, static_assert code> nécessite également C ++ 11, n'est-ce pas?
@sashoalm je le crois, bien que je ne puisse pas vous donner une citation. Edge code> doit avoir le même alignement que double code> - il ne devrait donc pas y avoir de rembourrage. Si ce n'est pas le cas, j'aimerais vraiment savoir pourquoi pas. Et vous pouvez utiliser boost_static_assert () code> à la place.
'#pragma pack' est supporté par VC ++ et GCC - Je ne l'utiliserais pas, si possible, si possible
Pourquoi STD :: Tri être plus rapide?
@Nick Johnson: Il utilise un meilleur algorithme autant que je sache.
Emperiquement, c'est, probablement parce qu'il peut aligner la comparaison. Cependant, sa peine de profiter d'un premier profilage de votre demande pour déterminer que le tri est un goulot d'étranglement qui mérite d'optimiser - le QSort fonctionne bien.
Avoir L Global n'affecte pas la sécurité du fil. En fait, comme vous pouvez le constater, QSort reçoit ce paramètre, mais il la copie à l'intérieur. En tant que côté, STD :: Trier est plus rapide que dans certains cas, mais ne sont sûrement pas sur des tableaux de CLARE C.
Remarque ajoutée sur
qsort code> en raison d'un nombre de mauvaises réponses.@Diego Sevilla: L affecte ma fonction de comparaison.
Pourquoi ne pouvez-vous pas copier votre tableau C dans un vecteur, trier, puis copier? Le tri est Nlogn de toute façon. Les 2 NS supplémentaires ne feront pas une différence notable.
Je veux utiliser seulement O (1) de mémoire supplémentaire.
REMARQUE SUR VOTRE PREMIER MISE À JOUR: Ne MPI_RECV prend-il un pointeur de mémoire tampon de sortie en tant que paramètre? Si tel est le cas, il n'y a aucune raison pour ne pas vous fournir un pointeur dans un vecteur plutôt qu'un tableau brut. Ce n'est pas que cela aide au problème réel pour essayer de le faire avec STD :: Trier, ce qui n'est bien sûr pas là où ils sont stockés, mais le fait que la taille des éléments triés n'est pas connue tant que le moment de l'exécution, alors STD :: Trier ne sait pas comment les déplacer.
@Alexandru J'ai le même problème, j'ai donc réécrit la question (espérons-le, mieux c'est maintenant) et ajouté une prime.
@sashoalm avez-vous envisagé d'utiliser une fonction de comparaison dans
trier () code> fonction?@sashoalm a jeté une réponse. La réinterprétation d'un tableau ne doit pas avoir de problèmes d'alignement - et devrait gérer correctement et échanger correctement.