La création et la Compréhension des listes liées à des structures en C
J'ai du mal à saisir les concepts de struct
et de la liste liée structure de données ensemble. Par exemple, disons que nous avons pour avoir ce code: un struct
qui a un travailleur ayant un contenu et une liste liée de ces structures qui contient des nœuds de chaque travailleur et un pointeur vers le nœud suivant(?).
typedef struct Schedule {
char name[10];
char description[10];
int hours;
int workordernum;
} Work;
typedef struct linkedlist {
struct Schedule work;
struct linkedlist *next;
} Node;
Le problème est de savoir comment vous faire une méthode qui ajoute toujours un nœud dans le début de la liste, une méthode qui ajoute n'importe où(au milieu) dans la liste à l'aide définis par l'utilisateur workordernum
, et une méthode qui met toujours à la fin.
Je ne suis pas tout à fait comprendre ->
et *
usages correctement. J'ai lu en ligne sur la création de la tête et la queue des nœuds, mais je n'ai pas très bien son utilisation correctement, car ils avaient un struct
pour une liste et une struct
pour un nœud.
Une autre chose que je n'avais pas obtenir de l'est, permet de dire que l'ajout d'un nœud au début de la liste des œuvres, comment allez-vous alors change à chaque workordernum
de la valeur pour tous les nœuds qui ont été précédemment?
Je comprends que l'on doit garder la trace de chaque fois qu'un nœud est ajouté, supprimé ou déplacé, ce qui signifie que chaque fois que ces méthodes sont appelées nous devons avoir une variable qui garde la trace du nombre. Donc, si nous avons un nœud dans la liste de tous les prêts, de sa commande serait l'un, puis nous ajoutons une autre pour le début, comment ferions-nous pour changer le numéro d'ordre de 1 à 2 et celui d'être ajouté à 1?
Ou comment node->next->next->suivant les travaux si nous n'avons qu'un pointeur? Alors, comment pourrions-nous l'impression de tous d'entre eux? Puisque nous ne pouvons pas utiliser un for
boucle.
Ce sont donc ces concepts, je ne peux pas saisir le code sage. Je voudrais bien vouloir reconnaissants si vous prenez votre temps pour l'expliquer plutôt que de simplement donner le code, si possible. Parce que j'aurais à appliquer ce que j'ai à apprendre à se déplacer et supprimer des nœuds. Je veux apprendre sur mon propre. Si quelque chose doit être donné comme un exemple de code alors que c'est bien, mais s'il te plaît, ne postez pas de tous les codes de réponse pour moi.
-Merci
*Veuillez pardonner les erreurs de format depuis que je suis nouveau sur ce site.
Edit: je comprends un pointeur est une adresse et que ->
se rapporte à "pointant" un membre. Je veux dire, je comprends toutes les bases, mais ma compréhension n'est pas assez ferme que j'ai pu faire ce que j'ai besoin d'aide.
Edit2: je vais essayer de faire un nœud de tête associé à la liste de ce que j'ai appris jusqu'à présent. Je vais être en utilisant les structures ci-dessus et il sera lâche le code, il n'est pas parfait. C'est juste pour s'assurer que je suis sur la bonne voie jusqu'à présent.
int main() {
//creates a work struct to hold user content
Work *workstruct = (Work*)malloc((sizeof(struct Schedule));
//creates first node to hold a work struct for linkedlist
Node *initialNode = (Node*)malloc((sizeof(struct linkedlist));
//Method call to add work nodes to list in main
addWork(initialNode, workstruct);
}
void addWork(Node *initialNode, Work *workstruct) {
//Suppose user already initialized workstruct
//create double-pointer to make initialNode as head
Node **head = (Node **)malloc(sizeof(struct linkedlist));
//assigns user's workstruct to the workstruct of initialNode
initialNode->work = *workstruct;
//If im understanding what you have taught me so far,
//this is how you always add a node on the head
initialNode->next = *head;
*head = initialNode;
}
La seule question que je semble avoir jusqu'à présent est que chaque fois que j'essaie d'ajouter un nouveau nœud à la liste, il fait le nouveau nœud de la tête mais perd le nœud précédent qui était dans la liste.
->
et *
usages correctement. Vous devriez commencer avec la bonne base avant d'essayer pour les plus avancés, concept.D'accord, cela semble très proche de "veuillez m'apprendre tous sur les listes liées", qui, en dehors de ne pas être une question appropriée pour un Débordement de Pile va être difficile si vous n'avez pas réussi à maîtriser de base de la syntaxe de pointeur encore.
Cette tutoriel sur les pointeurs et tel de C est datée (c'est à dire, pas jusqu'à la dernière norme, ni de machines et d'outils), mais il vaut la peine de toute façon. Non, il n'y a pas de route royale pour apprendre ce qui vous prendra quelques semaines d'efforts soutenus.
obtenez ce livre : Apress Sujets Avancés en C, c'est une bonne référence pour les structures de Données et des pointeurs, vous avez manqué beaucoup de sorte que vous besoin d'une référence, non seulement une réponse à votre question
Merci, j'ai déjà vérifié que tutoriel. Merci de me faire confiance quand je dis, je ne comprends PLUS comment pointeurs de travail.
OriginalL'auteur user3570478 | 2014-04-24
Vous devez vous connecter pour publier un commentaire.
Listes chaînées - 101 - liée Individuellement des Listes de
C'est une longue réponse. La raison j'ai fait tellement de détail est qu'il y a un grand nombre de liens de la liste de questions qui, je l'espère, de répondre sur place, avec le bon contexte.
Lorsque j'ai appris le C, j'ai eu du mal avec les pointeurs. Cependant, après la mise en œuvre d'une liste liée, j'ai enfin commencé à saisir la notion de pointeurs. Maître des listes liées est une bonne chose en C, et il va vous aider à être à l'aise avec les pointeurs. Quand les choses semblent confus, prenez un crayon et du papier et de l'esquisse d'un schéma d'une liste et les liens associés aux nœuds. Il m'arrive de le faire lorsque je travaille avec des complexes liste des implémentations.
Une liste chaînée est une façon de stocker des enregistrements de données. Contrairement à un tableau où tous les éléments sont logés dans un bloc de mémoire contiguë de mémoire, lié à des éléments de la liste occuper aléatoire des fragments de mémoire.
Il y a deux types de base de la liste liée; une liste liée individuellement, et une liste à double liaison. La différence est que une liste liée individuellement ne peut être parcouru dans un sens; alors qu'une liste à double liaison peut être parcouru dans les deux sens.
Une liste liée individuellement est accessible par l'intermédiaire de son "chef" pointeur, ou un pointeur à la tête d'une liste de noeuds. Une liste à double liaison peut également être consulté par l'intermédiaire de son "chef" pointeur, ou par l'intermédiaire de sa "queue" pointeur.
Contrairement à un tableau où chaque élément de la matrice peuvent être directement adressée par son index de tableau, la liste des éléments à accès séquentiel.
Voici une présentation d'une liste liée individuellement:
Chaque nœud dans la liste, avec sa charge utile de données, est allouée séparément. Un nœud de la structure (C) pourrait ressembler à quelque chose comme ceci:
Pour initialiser une liste liée individuellement de la structure ci-dessus:
'"' est maintenant un pointeur vers une liste liée (sans nœuds).
Ici est de savoir comment ajouter un nouveau nœud à la tête de cette liste:
Q: Pourquoi est un "double-pointeur" nécessaire (c'est à dire: LIST_NODE_T **...)? Pourquoi ne pas utiliser un "simple" de niveau pointeur (c'est à dire: LIST_NODE_T *...)?
Un: Un "simple" pointeur sur la liste de la tête ne serait pas suffisant pour cette opération. Plus précisément, cette opération désigne une nouvelle "tête de nœud". Cela signifie que cette fonction doit modifier le pointeur qui pointe vers le nœud de tête.
AVANT:
APRÈS:
Note qu'avant, HEADPTR a été pointant vers "Node #Y'; puis après, HEADPTR est pointant vers 'nœud'. Lorsque cette fonction est appelée, l'adresse de la "pointeur est passé, permettant à cette fonction pour modifier l'emplacement où le" pointeur pointe. Dans otherwords, l'adresse de la "pointeur est passé dans cette fonction, qui est représenté (en interne pour cette fonction) comme un pointeur vers le" pointeur (pointeur vers un pointeur). C'est pourquoi il est un "double-pointeur".
Q: Qu'est-ce " goto NETTOYAGE;' entreprise?
Un: Le langage C, à la différence de C++ et de JAVA, n'a pas de notion d '"exception". La vérification des erreurs en C est critique. Il y a un certain nombre de raisons que le malloc() la fonction peut échouer, et si c'est le cas, le code est à manipuler avec autant de tact que possible. Le "goto NETTOYAGE' instruction provoque le flux de programme normal d'ignorer le code de saut à la 'NETTOYAGE:' étiquette à l'intérieur de cette fonction, ci-dessous).
Évidemment, si la fonction malloc() a échoué, il serait imprudent d'essayer d'initialiser le pointeur NULL (retourné par l'échec de malloc) avec les lignes qui suivent immédiatement. Donc, il est important de détourner le flux du programme d'ignorer cette initialisation (et sur le lien qui vient plus tard).
Il n'y a rien de spécial à propos de la 'NETTOYAGE:' étiquette. J'ai pu l'ont appelé 'ERREUR:', 'SORTIE', 'TERMINER:', 'LIAHONA:', 'MY_BAD" ou toute autre chose qui convenait à mon plaisir. (Les étiquettes n'ont pas à être en majuscules, ni ont-ils être mis à la marge de gauche. Cependant, mon style est de faire de sorte qu'ils se démarquent.)
Étiquettes, tels que le 'NETTOYAGE' a un champ d'application limité aux frontières de la fonction où elles sont placées, et qui permet à chaque fonction pour un NETTOYAGE de: "l'étiquette (si nécessaire).
La fonction ci-dessus pourrait être appelé comme suit:
La LIST_InsertHeadNode() la fonction peut être appelée plusieurs fois. Chaque appel d'ajouter un nouveau nœud à la liste. Le nouveau nœud est placé à la "tête" de la liste, ce qui a pour effet de pousser le reste des nœuds plus bas dans la liste.
Après l'ajout de plusieurs nœuds de la liste, il peut être bon pour accéder à la liste; peut-être d'imprimer la charge utile de chaque nœud:
La fonction ci-dessus peut être appelée main():
D'ajouter des nœuds à la tête d'une liste [ie: LIST_InsertHeadNode()] est un moyen pour ajouter des nœuds. Cependant, il y a des moments où l'ajout de nœuds à l'autre extrémité de la liste (c'est à dire: la liste "queue") est préférable. Le code ci-dessous montre comment c'est fait.
Tout d'abord, une fonction qui sera de retour l'actuel "queue nœud" de la liste.
Ensuite, une fonction qui permet d'insérer un nœud à la queue de la liste.
Remarque importante: La LIST_GetTailNode() va définir le tailNode pointeur vers le dernier nœud de la liste liée; -moins - il n'y a pas de nœuds dans la liste. Lorsque la liste est vide, LIST_GetTailNode() permet de définir la tailNode pointeur à NULL.
Cette "autre chose" cas indique se produit lorsque tailNode est NULL, ce qui signifie que (pour l'instant) de la liste liée a pas de nœuds. Dans ce cas, ce nœud sera la première (la tête) nœud dans la liste (ou la dernière). Ainsi, l'appelant "la Liste Tête de" pointeur est mis à jour pour indiquer que ce nouveau nœud est maintenant à la tête de nœud.
La LIST_InsertTailNode() la fonction est appelée de la même façon LIST_InsertHeadNode() est appelée. La seule différence est que, avec LIST_InsertTailNode(), le nouveau nœud est inséré à la liste de la queue, plutôt qu'à la liste du tête de.
OK, alors maintenant, vous pouvez insérer un nouveau nœud à la tête ou à la queue de la liste. Ce sujet de l'insertion d'un nouveau nœud quelque part dans le milieu de la liste?
Par exemple, supposons que vous voulez avoir une liste où tous les nœuds sont triés par certains de terrain dans la charge utile, comme 'nom'. Alors qu'il est possible d'ajouter tous les nœuds, puis trier la liste par la suite; il est beaucoup plus facile à insérer chaque nouveau nœud dans la liste dans sa place. Ce faisant, la liste sera toujours maintenu dans l'ordre automatiquement.
L'accomplissement de ce qui est fait en deux étapes. Tout d'abord, allouer et initialiser le nouveau nœud. Alors, où sa place est dans la liste, puis lier le nouveau nœud dans la liste à cet endroit.
Tout d'abord, une fonction qui sera de retour ce sera le nœud parent " pour le nouveau nœud. (Ce nœud suppose que la liste est maintenue dans l'ordre de tri par nom):
Et maintenant, une fonction qui permet d'insérer de nouveaux nœuds, en gardant la liste triée par nom.
Remarque importante: La LIST_FetchParentNodeByName() va définir le parent pointeur vers le nœud de la liste qui est immédiatement inférieur au spécifiée j'__nom; -sauf - le nœud de tête est plus grande que la valeur spécifiée j'__nom. Pour ce cas particulier, LIST_FetchParentNodeByName() permet de définir le parent pointeur à NULL.
La LIST_InsertNodeByName() la fonction est appelée de la même façon LIST_InsertHeadNode() ou LIST_InsertTailNode() est appelée. La seule différence est que, avec LIST_InsertNodeByName(), le nouveau nœud est inséré dans son triée (par nom) emplacement dans la liste, plutôt qu'à la liste de tête ou de queue.
Il y aura des occasions où un nœud devra être supprimé de la liste. Ceci est fait par la localisation du nœud à supprimer, supprimer le lien avec le nœud de la liste, puis de supprimer le nœud et c'est la charge utile.
Tout d'abord, une fonction pour localiser un nœud spécifique par la charge utile de nom de domaine.
Ici est une fonction qui supprime un nœud de la liste qui correspond à une charge spécifique de nom.
Remarque importante: La LIST_FetchNodeByName() va définir le parent pointeur de la delNode; -sauf - le delNode est le nœud de tête. Pour ce cas particulier, LIST_FetchNodeByName() permet de définir le parent pointeur à NULL.
REMARQUE: Tout le code ci-dessus a été testé et doit être fonctionnel, et peut être téléchargé sous: 23279119_List_101.c
(La suite - selon la demande...)
Oui s'il vous plaît continuer à enseigner. Je n'ai pas causer des problèmes. Je ne peux pas comprendre la complexité de la structure du code que vous avez avec double pointeurs et avoir un int List et. Vous n'avez pas besoin d'utiliser mes structures, mais ce que je voulais dire à rendre le code plus simple était avec les normes d'enseignement de la matière elle-même. Je veux dire, si je n'ai pas entièrement comprendre la notion de listes liées comment puis-je comprendre la moitié de la structure de votre code votre en essayant de m'enseigner? Je m'en tiens à mes paroles, j'ai VRAIMENT envie d'apprendre. Encore une fois, je suis désolé pour la cause de vos rep difficulté. J'apprécie fort, que vous essayez de m'enseigner.
Avant que je continue; il y a deux choses. 1) je voudrais savoir si il y a des parties de mon explication que vous confondez peut-être... je peux préciser. 2) j'ai dirigé la maison et sera hors ligne pour environ 20 min ou alors...
Pour commencer, tout d'abord, pourquoi doit-il y avoir un double pointeur? Ne peut-il pas travailler?
Aussi comment ne travail de nettoyage lors de l'ajout d'un nœud? Je n'ai jamais vu utilisé.
OriginalL'auteur Mahonri Moriancumer