简体   繁体   中英

Move node to a new index in a linked list

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:

  1. find the node
  2. cut it out
  3. find the place to insert
  4. 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...

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:

  1. Write a function to remove and return a node given a name string.
  2. 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->

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
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM