问题
i'm trying to change index in linked list.... something like: I have the linked list: 1->2->3->4->END and the user insert second node(2) and the index 4.
The function will give us the result: 1->3->4->2->END.
i know the algorithm is:
- find the node
- cut it out
- find the place to insert
- insert it
but i cant make it work... my code of the function till now is:
void changeIndex(FrameNode** head, char* name, int index)
{
FrameNode* temp = NULL;
FrameNode* curr = *head;
FrameNode* node = *head;
int counter = 1;
int flag = 0;
while (node && flag == 0)
{
if (strcmp(node->frame->name, name) == 0)
{
flag = 1;
}
else
{
node = node->next;
}
}
while (counter != index)
{
counter++;
temp = curr;
curr = curr->next;
}
temp->next = node;
curr->next = node->next;
node->next = curr;
}
i cant find what's wrong... i searched and find this- Change index in a linked list in c but it gives just the algorithm and i cant code it. please help...
回答1:
I haven't run this, but I think this is what you'll need to do... (also, I recommend using variable names that are more meaningful to the operations you're doing.)
You need to maintain a temporary pointer to the node just before the one you are moving so that you can connect it to the node following the one you are moving.
After you've made that splice, you insert the node at the proper index using beforeIndex
and reconnect the node originally at the index as the next node following the one you just moved
void changeIndex(FrameNode** head, char* name, int index)
{
FrameNode* beforeMoved = NULL;
FrameNode* beforeIndex = NULL;
FrameNode* atIndex = *head;
FrameNode* toMove = *head;
int counter = 0;
int flag = 0;
while (toMove && flag == 0)
{
if (strcmp(toMove->frame->name, name) == 0)
{
flag = 1;
}
else
{
beforeMoved = toMove;
toMove = toMove->next;
}
}
while (atIndex && (counter != index))
{
counter++;
beforeIndex = atIndex;
atIndex = atIndex->next;
}
if(toMove && (atIndex || index+1 == counter) && (toMove != atIndex))
{
if(beforeMoved == NULL)
*head = (*head)->next;
else
beforeMoved->next = toMove->next; // splice moving node out of linked list
if(beforeIndex == NULL)
*head = toMove;
else
beforeIndex->next = toMove; // add moving node to correct location
toMove->next = atIndex; // reconnect node previously at index
}
}
回答2:
For starters, I recommend using 0-indexing rather than 1-indexing, so I've made that logical modification throughout this example.
I recommend breaking the problem into steps:
- Write a function to remove and return a node given a
name
string. - Write a function to add a node at an index.
This way, each function is much easier to write and validate.
The logic for removing a node involves walking the list to find the node using strcmp
(as you're doing) and keeping track of the previous node. Once the loop terminates, if a previous node exists, then set its next
to the next next node. If no prev
node exists, then we have an empty list or we're trying to remove the head, which involves doing nothing or setting *head
to its next, respectively.
The logic for adding a node at index is similar: walk the list with a prev
node up to the index or the runner node is null (it's unclear what action you want to take for index out of range errors). When the loop terminates, we again shift pointers based on whether we have a prev
, and if not, if we have a *head
.
Here's a complete example of how you could approach this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Node {
char *name;
struct Node *next;
};
void print_list(struct Node *head) {
for (; head; head = head->next) {
printf("%s->", head->name);
}
puts("");
}
struct Node *remove_node_by_name(struct Node **head, char *name) {
struct Node *prev = NULL;
struct Node *curr = *head;
for (; curr && strcmp(curr->name, name); prev = curr, curr = curr->next);
if (curr && prev) {
prev->next = curr->next;
}
else if (curr) {
*head = (*head)->next;
}
return curr;
}
void add_node_at_index(struct Node **head, struct Node *to_add, int index) {
struct Node *prev = NULL;
struct Node *curr = *head;
for (; curr && index--; prev = curr, curr = curr->next);
if (prev) {
prev->next = to_add;
to_add->next = curr;
}
else if (*head) {
to_add->next = *head;
*head = to_add;
}
}
void change_index(struct Node **head, char *name, int index) {
struct Node *removed = remove_node_by_name(head, name);
if (removed && *head) {
add_node_at_index(head, removed, index);
}
else if (removed) {
*head = removed;
}
}
int main(int argc, char **argv) {
if (argc != 4) {
puts("usage: ./llswap [nodelist] [node name] [new index]"
"\nex: ./llswap abc b 2");
return 0;
}
struct Node *head = NULL;
struct Node *curr = NULL;
for (int i = 0; i < strlen(argv[1]); i++) {
struct Node *node = malloc(sizeof(*node));
if (!node) {
fprintf(stdout, "%s:%d malloc failed\n", __FILE__, __LINE__);
exit(1);
}
node->next = NULL;
node->name = malloc(2);
if (!node->name) {
fprintf(stdout, "%s:%d malloc failed\n", __FILE__, __LINE__);
exit(1);
}
node->name[1] = '\0';
strncpy(node->name, &argv[1][i], 1);
if (!head) {
head = node;
}
else {
curr->next = node;
}
curr = node;
}
printf("before: ");
print_list(head);
change_index(&head, argv[2], atoi(argv[3]));
printf("after: ");
print_list(head);
while (head) {
struct Node *tmp = head;
head = head->next;
free(tmp->name);
free(tmp);
}
return 0;
}
Some sample runs:
$ ./llswap abc b 2
before: a->b->c->
after: a->c->b->
$ ./llswap abc a 2
before: a->b->c->
after: b->c->a->
$ ./llswap abc a 3
before: a->b->c->
after: b->c->a->
$ ./llswap abcd d 0
before: a->b->c->d->
after: d->a->b->c->
$ ./llswap a d 0
before: a->
after: a->
$ ./llswap a a 0
before: a->
after: a->
$ ./llswap a a 2
before: a->
after: a->
$ ./llswap ab a 2
before: a->b->
after: b->a->
$ ./llswap ab a 1
before: a->b->
after: b->a->
$ ./llswap ab b 1
before: a->b->
after: a->b->
来源:https://stackoverflow.com/questions/62640833/move-node-to-a-new-index-in-a-linked-list