2010-07-21 3 views
0

Possible en double:
What is the fastest way to swap values in C?Comment échanger des valeurs?

Comment puis-je échanger les valeurs de deux variables sans utiliser 3 variable? Je veux échanger (échanger) les valeurs de deux variables a et b.

+3

Quel type de données? –

+1

Pourquoi ne voulez-vous pas utiliser une autre variable? Je ne pense pas que ce soit possible. –

+1

Était-ce une question d'entrevue ou un devoir? – MikeD

Répondre

17

Utilisation std::swap:

std::swap(a,b) 
+0

Note: Ceci utilise une troisième variable sous le capot. Mais vous n'avez pas à le faire vous-même, et ce n'est pas possible sans quoi (le swap XOR ne compte pas, car il ne fonctionne qu'avec des entiers (? Peut-être d'autres primitives, aussi?)). Ça ne va pas mieux que ça. – delnan

+1

@Vladimir: je conseillerais d'utiliser aussi std :: swap(), mais cette réponse n'est pas vraiment ce que l'OP a demandé. alors, expliquez pourquoi il est préférable d'utiliser std :: swap() au lieu de hacky xorswap. – akira

+0

@delnan: "pas possible" est un peu fort. Par exemple, x86 a des opcodes 'xchg' qui pourraient facilement échanger deux variables entières (et souvent des pointeurs) sans impliquer de temporaire. Il est clair qu'une fonction de bibliothèque peut avoir une version spécialisée qui utilise l'assemblage en ligne pour certains types. –

4

Vous faites allusion à une énigme assez célèbre. La réponse dépend du type de données. Il n'y a pas d'algorithme pour un type générique.

0

À moins que vous ne puissiez utiliser des instructions spécifiques au processeur qui effectuent l'échange sans une troisième variable, vous devrez utiliser un temporaire pour effectuer l'échange, désolé. Vous pouvez utiliser std::swap mais cela masque uniquement le temporaire.

1

https://en.wikipedia.org/wiki/XOR_swap_algorithm

void xorSwap (int *x, int *y) { 
    if (x != y) { 
     *x ^= *y; 
     *y ^= *x; 
     *x ^= *y; 
    } 
} 
+0

Aucune raison d'utiliser des pointeurs au lieu de références, je pense. Juste fait pour le code d'appel plus maladroit. (Et si je fais 'xorSwap (0, 0)'?) – GManNickG

+0

a) Comme le suggère l'URL, il s'agit d'une copie directe du formulaire wikipedia. b) parce que c ne connaît pas les «références» et que cela fonctionnera donc aussi bien en C++ qu'en c. c) 'if (x! = y)' couvre 'xorSwap (0, 0)' ainsi que 'xorSwap (& z, & z)' – akira

+1

@akira: Totalement masqué sur le dernier point, mais si un argument est nul c'est va encore exploser. Si nous écrivons C++ qui se soucie si cela fonctionne en C? Les références sont beaucoup plus propres IMO. – GManNickG

0

Il y a quelques façons que vous pouvez le faire. Vous pouvez échanger les pointeurs, ou si les valeurs sont des nombres entiers, vous pouvez utiliser un petit hack arithmétique:

a=a+b; 
b=a-b; 
a=a-b; 
+1

Cela ne fonctionne que si le premier ajout ne déborde pas. – Joel

+0

Très vrai (plus de caractères) – Josiah

0

Vous pouvez utiliser le XOR swap algorithm

a = a^b; 
b = b^a; 
a = a^b; 

Cependant, ce n'est pas une bonne idée. Aussi de wikipedia:

La plupart des compilateurs modernes peuvent optimiser la variable temporaire dans l'échange naïf, auquel cas l'échange naïf utilise la même quantité de mémoire et le même nombre de registres que l'échange XOR et est au moins aussi rapide , et souvent plus rapide. [ cite] Le swap XOR est également beaucoup moins lisible et peut être complètement opaque pour quiconque n'est pas déjà familier avec la technique.
9

Généralement, vous ne le faites pas. Il n'y a aucune raison de ne pas utiliser une troisième variable, appelez simplement std::swap(a, b) et continuez votre vie.

Avec les entiers, vous pouvez faire:

void swap(int& a, int& b) 
{ 
    if (a != b) 
    { 
     a ^= b; 
     b ^= a; 
     a ^= b; 
    } 
} 

Mais cela donne généralement de moins bonnes performances que d'utiliser une troisième variable.

+0

@Kirill: Ce ne sont pas les valeurs qui doivent être différentes, ce sont les variables elles-mêmes. Échanger avec le même emplacement rend le tout 0. – GManNickG

+0

si l'emplacement des mêmes variables sera égal. Si les variables sont égales, vous ne devriez pas faire d'échange. 'a! = b' est plus commun –

+0

@Kirill: Haha, duh. Ma faute. :) Nommez le "moment le plus stupide" pour moi. – GManNickG

0

Généralement, aura besoin d'une troisième variable vide pour permuter le contenu de deux autres variables.

Cependant, il existe des cas spéciaux. Voici un échange spécial pour deux bool des variables a et b:

void swap_bools(bool &a, bool &b) 
{ 
    if (a != b) 
    { 
     a = !a, b = !b; 
    } 
} 
Questions connexes