从C中的链接列表中删除包含字符串的节点

时间:2015-09-17 03:48:03

标签: c

我正在努力编写一个删除包含链接列表中字符串的节点的方法。这就是我所拥有的。

struct node { 

    char name[128];
    struct node *next; 
};

struct node *list_delete(const char *name, struct node *list) {

    if (list->next == NULL && strcmp(name, head_name) == 0) {

        struct node *temp = list;
        list = list->next;
        free(temp);
        return list;
    }
    struct node *head = malloc(sizeof(struct node));
    head = list; 
    while (head->next != NULL) {
        if (strcmp(name, head->name) == 0) {
            struct node *temp = head;
            head = head->next;
            free(temp);
            break;
        } 
        head = head->next;
    }
    return list; 
}

当我运行时,我收到错误:

  

双重免费或腐败(!prev)

我想看看我是不是在我不应该的地方解放,但我想我已经拥有了。我也是C的新手,所以我还在学习。

4 个答案:

答案 0 :(得分:0)

如果没有看到调用它的代码,看起来你可能会遇到上一次返回return list;的问题。如果第一项是免费的,那么你将返回指向最近释放的内存的指针可能会再次释放它。

答案 1 :(得分:0)

您拥有的是前向链接列表。因此,在删除时,您需要在删除目标之前直接维护指向项目的指针。由于你的删除函数返回一个指针,我将假设这会返回新的头部(如果目标元素不是头部,则返回当前的头部。)

我应该指出,我的下面的例子有一点需要注意,它只删除第一个匹配项并且不处理具有相同名称的多个元素。如果您需要处理,您需要做的就是在while(1)中包含现有的return head;循环,并将最后2 continue;个语句替换为struct node *list_delete(const char *name, struct node *list) { struct node* prev = NULL; struct node* head = list; while (list) { if (!strcmp(list->name, name)) break; prev = list; list = list->next; } if (!list) return head; //not found, no change. if (!prev) { //element to destroy is first one head = list->next; free(list); return head; } prev->next = list->next; //make previous skip target free(list); //destroy found element return head; //head unchanged }

JFrame

答案 2 :(得分:0)

我个人觉得最好有几个指针来跟踪列表遍历。

struct node *list_delete(const char *name, struct node *list) {
        struct node *cur = NULL, *nxt = NULL;


        if( list ) { /** Valid List **/
                cur = list;
                nxt = list->next;
                while( nxt ) {  /** Next Pointer Exists **/
                        if ( strcmp( name, nxt->name ) == 0 )  { /** and Next node is what we are looking for **/
                                cur->next = nxt->next; /**  Skip Next Node **/
                                nxt->next = NULL; /** Detach It **/
                                free(nxt); /** Free it **/
                                return list;     /** Return list **/     
                        }
                        nxt = nxt->next; /** Go on further **/
                        cur = cur->next;                                
                }

                if ( strcmp( name, cur->name ) == 0 ) { /** will handle single node case **/
                        free( cur );
                        return NULL;
                }
        }

    return NULL; 
}

答案 3 :(得分:0)

对代码进行一些更改。请记住,if-else分支中不应该遗漏。

在我的NetBeans环境中通过

首先,请不要直接编辑头节点!

因为这在练习中确实是一种糟糕的方式。

此外,我认为typedef是您想要定义结构时的更好选择。

typedef struct node { 

    char name[128];
    struct node *next; 
}Node;

Node *deleteNode(const char *name, Node *head) {
    /*
     * Give one recommendation:You'd better use
     * a temp pointer instead of using the input
     * parameter directly.There is no rule for 
     * this, but I think it's a good code manner.
     */
    Node *ptr = head;
    Node *nxt;
    if(ptr == NULL)
        return head;
    /*
     * If the head node meet the requirement.
     */
    else if(strcmp(ptr->name,name) == 0){
        head = head->next;
        free(ptr);
    }
    else{
        /*
         * Search from the second Node in the List.
         */
        while(ptr->next != NULL){
            /*
             * Using a temp Node pointer.
             * So you could free the mateched Node.
             */
            nxt = ptr->next;
            if(strcmp(nxt->name,name) == 0){
                ptr->next = nxt->next;
                free(nxt);
                break;
            }
            else{
                ptr = ptr->next;
                continue;
            }
        }
        return head;
    }
}