Die Funktion undefiniert Verhalten hat, weil es nicht in Betracht zieht, dass zum Beispiel headr
gleich sein kann NULL
oder prev1
und prev2
-NULL
gleich sein können.
Es wäre gut, eine weitere Funktion zu schreiben, die den Knoten findet, der den gegebenen Daten entspricht.
Trotzdem kann die Funktion swapNodes
folgendermaßen geschrieben werden. Es findet Knoten, die ausgetauscht werden sollen, und tauscht dann Zeiger auf die Knoten und ihre Datenelemente aus next
. Hier
Sie sind
void swap(struct Node **first, struct Node **second)
{
struct Node *tmp = *first;
*first = *second;
*second = tmp;
}
void swapNodes(struct Node **headr, int key1, int key2)
{
if (key1 == key2) return;
struct Node **first = headr;
while (*first && (*first)->data != key1) first = &(*first)->next;
if (*first == NULL) return;
struct Node **second = headr;
while (*second && (*second)->data != key2) second = &(*second)->next;
if (*second == NULL) return;
swap(first, second);
swap(&(*first)->next, &(*second)->next);
}
hier ein Demonstrationsprogramm ist.
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
};
void push(struct Node** head_ref, int new_data)
{
struct Node* new_node =
(struct Node*) malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->next = (*head_ref);
(*head_ref) = new_node;
}
void printList(struct Node *node)
{
while(node != NULL)
{
printf("%d ", node->data);
node = node->next;
}
}
void swap(struct Node **first, struct Node **second)
{
struct Node *tmp = *first;
*first = *second;
*second = tmp;
}
void swapNodes(struct Node **headr, int key1, int key2)
{
if (key1 == key2) return;
struct Node **first = headr;
while (*first && (*first)->data != key1) first = &(*first)->next;
if (*first == NULL) return;
struct Node **second = headr;
while (*second && (*second)->data != key2) second = &(*second)->next;
if (*second == NULL) return;
swap(first, second);
swap(&(*first)->next, &(*second)->next);
}
int main(void)
{
struct Node *start = NULL;
push(&start, 7);
push(&start, 6);
push(&start, 5);
push(&start, 4);
push(&start, 3);
push(&start, 2);
push(&start, 1);
printf("\n Linked list before calling swapNodes() ");
printList(start);
swapNodes(&start, 4, 3);
printf("\n Linked list after calling swapNodes() ");
printList(start);
return 0;
}
Sein Ausgang ist
Linked list before calling swapNodes() 1 2 3 4 5 6 7
Linked list after calling swapNodes() 1 2 4 3 5 6 7
In der Tat die Funktion swapNodes
wie geschrieben steht (ohne eine separate Funktion, die Knoten für ein gegebenen Daten findet) macht zwei Dinge: Es 1) findet zwei Knoten und es 2) tauscht sie. Das Suchen der Knoten kann nicht erfolgreich sein. Daher sollte die Funktion dem Benutzer melden, ob Knoten ausgetauscht wurden. In diesem Fall ist es wünschenswert, die Funktion mit dem Rückgabetyp int
zu deklarieren.
Zum Beispiel
int swapNodes(struct Node **headr, int key1, int key2)
{
int success = key1 != key2;
if (success)
{
struct Node **first = headr;
struct Node **second = headr;
while (*first && (*first)->data != key1) first = &(*first)->next;
success = *first != NULL;
if (success)
{
while (*second && (*second)->data != key2) second = &(*second)->next;
success = *second != NULL;
}
if (success)
{
swap(first, second);
swap(&(*first)->next, &(*second)->next);
}
}
return success;
}
Wenn eine eigene Funktion zu schreiben, die einen Knoten sucht, wie es oben dann die Funktion erwähnt wurde, die Knoten tauscht aussehen wird klarer und einfacher.
Zum Beispiel
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
};
void push(struct Node** head_ref, int new_data)
{
struct Node* new_node =
(struct Node*) malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->next = (*head_ref);
(*head_ref) = new_node;
}
void printList(struct Node *node)
{
while(node != NULL)
{
printf("%d ", node->data);
node = node->next;
}
}
void swap(struct Node **first, struct Node **second)
{
struct Node *tmp = *first;
*first = *second;
*second = tmp;
}
struct Node ** find(struct Node **headr, int data)
{
while (*headr && (*headr)->data != data) headr = &(*headr)->next;
return headr;
}
void swapNodes(struct Node **first, struct Node **second)
{
swap(first, second);
swap(&(*first)->next, &(*second)->next);
}
int main(void)
{
struct Node *start = NULL;
push(&start, 7);
push(&start, 6);
push(&start, 5);
push(&start, 4);
push(&start, 3);
push(&start, 2);
push(&start, 1);
printf("\n Linked list before calling swapNodes() ");
printList(start);
struct Node **first;
struct Node **second;
if ((first = find(&start, 4)) && (second = find(&start, 3))) swapNodes(first, second);
printf("\n Linked list after calling swapNodes() ");
printList(start);
return 0;
}
Versuche mit einigen Beispieltestfällen auf einen Debugger ausgeführt wird. –
Wenn Sie Daten austauschen dürfen, können Sie dies tun, um Fehler aufgrund von Zeigermanipulation zu vermeiden. –
@ ilz0R Die Referenz, auf die Sie hingewiesen haben, ist für diese Frage nutzlos. –