En mode Implémentation Java d'hier, notre mécanisme de verrouillage à double vérification a introduit le mot-clé volatile en raison du problème de réorganisation des instructions. De nombreux amis m'ont demandé, pourquoi dois-je ajouter le mot-clé volatile ? Et quel effet magique a-t-il?
En ce qui concerne le mot-clé volatile , nous avons brièvement mentionné dans l'explication d'hier: les variables partagées modifiées par volatile auront les deux attributs suivants:
Variable partagée: si une variable a une copie dans la mémoire de travail de plusieurs threads, cette variable est la variable partagée de ces threads.
Visibilité: La modification d'un thread à la valeur de variable partagée peut être vue par d'autres threads en temps opportun.
Pour réorganiser, si vous ne le connaissez pas, il suffit de le Google, donc je ne le mentionnerai pas ici. N'oubliez pas que lors de l'utilisation d'une variable partagée dans plusieurs threads, vous devez vous rappeler d'ajouter une modification volatile.
En raison des contraintes de temps, nous devons toujours arriver au sujet d'aujourd'hui en premier. Le mot-clé volatile est toujours facile à détecter dans l'entretien qui nécessite des compétences de programmation simultanées. Je vous l'expliquerai brièvement plus tard.
Entrez le nœud de tête d'une seule liste liée et imprimez la valeur de chaque nœud de la fin à la fin.
Nous avons de nombreuses listes liées, des listes liées uniques, des listes liées à double sens, des listes liées à l'anneau, etc. Il s'agit du mode de liste unique le plus courant. Nous stockons généralement des données dans la zone de stockage de données, puis un pointeur pointe vers le nœud suivant. Bien qu'il n'y ait pas de concept de pointeur en Java, les références Java correspondent au problème.
Lorsque nous voyons cette question, nous réalisons souvent rapidement que chaque nœud a un prochain attribut, il est donc très simple de sortir du début à la fin. Nous allons donc naturellement penser à utiliser d'abord une boucle de temps pour éliminer tous les nœuds et les stocker dans le tableau, puis traverser le tableau dans l'ordre inverse, afin que les valeurs de nœud d'une seule liste liée puissent être imprimées dans l'ordre inverse.
Nous supposons que les données du nœud sont de type int. Le code d'implémentation est le suivant:
classe publique test05 {Node de classe statique publique {int data; Nœud suivant; } public static void printLinkReverse (Node Head) {ArrayList <Node> nœuds = new ArrayList <> (); while (head! = null) {nœuds.add (tête); head = head.next; } pour (int i = nœuds.size () - 1; i> = 0; i--) {System.out.print (nœuds.get (i) .data + ""); }} public static void main (string [] args) {node head = new node (); head.data = 1; head.next = new node (); head.next.data = 2; head.next.next = new node (); head.next.next.data = 3; head.next.next.next.next = new node (); head.next.next.next.data = 4; head.next.next.next.next.next = new node (); head.next.next.next.data = 5; printLinkReverse (tête); }}Cette méthode peut en effet implémenter l'impression d'ordre inverse des données de liste liée, mais elle utilise évidemment deux cycles complets, avec une complexité temporelle d'O (n²). etc! Sortie inversée? Il semble qu'il existe une telle structure de données qui peut parfaitement résoudre ce problème, et cette structure de données est la pile.
La pile est une structure de données "dernier en premier sortie". Le principe de la pile peut mieux répondre à nos exigences, donc le code d'implémentation est le suivant:
classe publique test05 {Node de classe statique publique {int data; Nœud suivant; } public static void printLinkReverse (Node Head) {Stack <Node> Stack = new Stack <> (); while (head! = null) {stack.push (tête); head = head.next; } while (! stack.isempty ()) {System.out.print (stack.pop (). Data + ""); }} public static void main (string [] args) {node head = new node (); head.data = 1; head.next = new node (); head.next.data = 2; head.next.next = new node (); head.next.next.data = 3; head.next.next.next.next = new node (); head.next.next.next.data = 4; head.next.next.next.next.next = new node (); head.next.next.next.next.data = 5; printLinkReverse (tête); }}Puisqu'il peut être mis en œuvre à l'aide d'une pile, il est très facile pour nous de penser que la récursivité peut également résoudre ce problème, car la récursivité est essentiellement une structure de pile. Pour implémenter la liste des liens de sortie de commande inverse, chaque fois que nous accédons à un nœud, nous sortions d'abord le nœud de manière récursive, puis publions le nœud lui-même. De cette façon, le résultat de sortie de la liste liée sera naturellement inversé.
Le code est le suivant:
classe publique test05 {Node de classe statique publique {int data; Nœud suivant; } public static void printLinkReverse (nœud head) {if (head! = null) {printLinkReverse (head.next); System.out.print (head.data + ""); }} public static void main (string [] args) {node head = new node (); head.data = 1; head.next = new node (); head.next.data = 2; head.next.next = new node (); head.next.next.data = 3; head.next.next.next = new node (); head.next.next.next.data = 4; head.next.next.next.next.next.next = new node (); head.next.next.next.next.data = 5; printLinkReverse (tête); }} Bien que le code récursif soit très soigné, il y a un problème: lorsque la liste liée est très longue, elle conduira certainement à des niveaux profonds d'appels de fonction, ce qui peut entraîner le débordement de la pile d'appels de fonction. Par conséquent, le code qui affiche le code basé sur la boucle est mieux robuste.
Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.