Je me demande s'il existe une logique pour inverser une liste à lien unique en utilisant seulement deux pointeurs.
Ce qui suit est utilisé pour inverser la liste chaînée unique à l' aide de trois pointeurs à savoir p
, q
, r
:
struct node {
int data;
struct node *link;
};
void reverse() {
struct node *p = first,
*q = NULL,
*r;
while (p != NULL) {
r = q;
q = p;
p = p->link;
q->link = r;
}
first = q;
}
Existe-t-il une autre alternative pour inverser la liste chaînée? Quelle serait la meilleure logique pour inverser une seule liste chaînée, en termes de complexité temporelle?
Réponses:
Une alternative? Non, c'est aussi simple que possible et il n'y a pas de manière fondamentalement différente de le faire. Cet algorithme est déjà O (n) time, et vous ne pouvez pas aller plus vite que cela, car vous devez modifier chaque nœud.
Il semble que votre code soit sur la bonne voie, mais il ne fonctionne pas tout à fait sous la forme ci-dessus. Voici une version de travail:
la source
reverse()
fonction doit être définie en premier, je crois. Sinon, le code d'origine fonctionnait correctement lorsqu'il était branché sur votre harnais de test soigné. Vous obtenez même +1 de ma part - mais une explication de ce que vous considérez comme des «erreurs évidentes» améliorerait votre réponse.Je déteste être porteur de mauvaises nouvelles, mais je ne pense pas que votre solution en trois points fonctionne réellement. Lorsque je l'ai utilisé dans le faisceau de test suivant, la liste a été réduite à un nœud, selon la sortie suivante:
Vous n'obtiendrez pas une meilleure complexité de temps que votre solution car c'est O (n) et vous devez visiter chaque nœud pour changer les pointeurs, mais vous pouvez faire une solution avec seulement deux pointeurs supplémentaires assez facilement, comme indiqué dans le code suivant:
Ce code génère:
ce que je pense est ce que vous recherchiez. Il peut en fait le faire car, une fois que vous avez chargé
first
le pointeur traversant la liste, vous pouvez le réutiliserfirst
à volonté.la source
first
pointeur sur la liste chaînée elle-même permet à la solution d'utiliser seulement 2 pointeurs supplémentaires , mais 3 pointeurs au total sont toujours nécessaires pour cela.first
. De la même façon la solution à trois pointeur de l'OP avaitfirst
,p
,q
etr
.la source
Voici le code pour inverser une liste liée individuellement en C .
Et ici, il est collé ci-dessous:
la source
Oui. Je suis sûr que vous pouvez faire cela de la même manière que vous pouvez échanger deux numéros sans utiliser un troisième . Convertissez simplement les pointeurs en int / long et effectuez l'opération XOR plusieurs fois. C'est l'une de ces astuces C qui en fait une question amusante, mais qui n'a aucune valeur pratique.
Pouvez-vous réduire la complexité O (n)? Non, pas vraiment. Utilisez simplement une liste doublement liée si vous pensez avoir besoin de l'ordre inverse.
la source
Robert Sedgewick, " Algorithmes en C ", Addison-Wesley, 3e édition, 1997, [Section 3.4]
Dans le cas où ce n'est pas une liste cyclique, NULL est donc le dernier lien.
la source
Juste pour le plaisir (bien que l'optimisation de la récursivité de la queue devrait l'empêcher de manger toute la pile):
la source
Pour permuter deux variables sans utiliser de variable temporaire,
le moyen le plus rapide est de l'écrire en une seule ligne
De même,
en utilisant deux swaps
solution utilisant xor
solution en une ligne
La même logique est utilisée pour inverser une liste chaînée.
la source
intptr_t
). Bien qu'intéressant, échanger de cette manière n'est pas optimal sur les systèmes modernes.Vous avez besoin d'un pointeur de piste qui suivra la liste.
Vous avez besoin de deux pointeurs:
premier pointeur pour choisir le premier nœud. deuxième pointeur pour choisir le deuxième nœud.
En traitement :
Déplacer le pointeur de piste
Pointer le deuxième nœud vers le premier nœud
Déplacer le premier pointeur d'une étape, en affectant un deuxième pointeur à un
Déplacer le deuxième pointeur d'une étape, en affectant le pointeur de piste à la deuxième
}
la source
Que diriez-vous du plus lisible:
la source
Voici une version plus simple de Java. Il n'utilise que deux pointeurs
curr
etprev
la source
Calculez la complexité temporelle de l'algorithme que vous utilisez actuellement et il devrait être évident qu'il ne peut pas être amélioré.
la source
Je ne comprends pas pourquoi il est nécessaire de retourner la tête alors que nous le passons comme argument. Nous passons en tête de la liste de liens, puis nous pouvons également mettre à jour. Voici une solution simple.
la source
la source
Non, rien de plus rapide que le courant O (n) ne peut être fait. Vous devez modifier chaque nœud, donc le temps sera de toute façon proportionnel au nombre d'éléments et c'est O (n) que vous avez déjà.
la source
L'utilisation de deux pointeurs tout en maintenant la complexité temporelle de O (n), le plus rapide possible, ne peut être possible que par la conversion de nombre de pointeurs et l'échange de leurs valeurs. Voici une implémentation:
la source
J'ai une approche légèrement différente. Je voulais utiliser les fonctions existantes (comme insert_at (index), delete_from (index)) pour inverser la liste (quelque chose comme une opération de décalage à droite). La complexité est toujours O (n) mais l'avantage est un code plus réutilisé. Jetez un œil à la méthode another_reverse () et dites-moi ce que vous en pensez tous.
la source
la source
la source
Oui, il existe un moyen d'utiliser seulement deux pointeurs. C'est en créant une nouvelle liste chaînée où le premier nœud est le premier nœud de la liste donnée et le second nœud de la première liste est ajouté au début de la nouvelle liste et ainsi de suite.
la source
Voici ma version:
où
la source
J'utilise java pour implémenter cela et l'approche est un développement piloté par les tests, donc des cas de test sont également joints.
La classe Node qui représente un nœud unique -
Classe de service qui prend le nœud de démarrage comme entrée et le réserve sans utiliser d'espace supplémentaire.
Et le cas de test qui couvre le scénario ci-dessus. Veuillez noter que vous avez besoin de pots junit. J'utilise testng.jar; vous pouvez utiliser tout ce qui vous plaît.
la source
Un algorithme simple si vous utilisez la liste chaînée comme structure de pile:
Les performances peuvent être affectées depuis l'appel de fonction supplémentaire à l'ajout et à malloc, de sorte que les algorithmes d'échange d'adresses sont meilleurs mais que l'on crée en fait une nouvelle liste afin que vous puissiez utiliser des options supplémentaires comme trier ou supprimer des éléments si vous ajoutez une fonction de rappel en tant que paramètre au inverser.
la source
Voici une approche légèrement différente, mais simple en C ++ 11:
Sortie ici
la source
Voici une implémentation utilisant 2 pointeurs (head et r)
la source
sizeof(size_t) < sizeof(ListNode*)
... vous devez utiliserstd::uintptr_t
.voici une petite solution simple ...
la source
Vous pouvez résoudre ce problème à l'aide d'un seul pointeur supplémentaire, qui doit être statique pour la fonction inverse. C'est en complexité O (n).
la source
Comme alternative, vous pouvez utiliser la récursivité-
la source
la source
la source