合并链表的两个节点中的值

时间:2017-04-11 19:16:03

标签: c stack queue nodes

我有一个squeue(堆栈和队列的组合)。我有一个名为mergeFront的函数,该作业应该将前两个节点合并为一个。例如,如果前节点是" alpha"第二个节点是" beta"它们应该合并到" alphabeta"。

alias python="python3"

当我在最后一行中void mergeFront(struct Squeue* squeue){ struct Node* temp; char *string; char *tempstring=malloc(sizeof(char)*100); temp = squeue->first; temp = temp->next; string = squeue->first->val; strcpy(tempstring, string); string = temp->val; strcat(tempstring, string); squeue->first->next->val=tempstring; temp = squeue->first; squeue->first = temp->next; free(temp); free(tempstring); } 时,第一个节点现在变为空(假设因为我有空闲' d指向的值)。如果我摆脱free(tempstring)它运行良好但存在内存泄漏。如何在正确释放内存的同时执行此操作?

节点结构如下

free(tempstring)

在获取@ikegami给出的代码后,我的代码如下:

struct Node{
    char* val;
    struct Node* next;
    struct Node* prev;
};

}

它完全正常运行,但我仍然在1块中获得10字节的泄漏内存。关于我在哪里找到这个的任何线索?

3 个答案:

答案 0 :(得分:0)

你想做什么:

  1. 为新字符串分配空间
  2. 将2个旧字符串合并为新字符串
  3. 删除2个旧字符串
  4. 删除第一个节点,并更新第一个节点
  5. 将新字符串分配给新的第一个节点
  6. -

    void mergeFront(struct Squeue* squeue){
        // Make sure there are at least 2 nodes
        if (NULL == squeue->first || NULL == squeue->first->next) {
            return;
        }
    
        // 1. Allocate space for the new string
        char *tempstring = malloc(strlen(squeue->first->val) +
                                  strlen(squeue->first->next->val) + 1);
        if (NULL == tempstring) {
            // Out of memory
            return;
        }
    
        // 2. Merge the 2 old strings into the new string
        sprintf(tempstring, "%s%s", squeue->first->val, squeue->first->next->val);
    
        // 3. Delete the 2 old strings
        free(squeue->first->val);
        free(squeue->first->next->val);
    
        // 4. Delete the first node, and update first node
        struct Node* temp = squeue->first;
        squeue->first = squeue->first->next;
        squeue->first->prev = NULL;
        free(temp);
    
        // 5. Assign the new string to the new first node
        squeue->first->val = tempstring;
    }
    

答案 1 :(得分:0)

void mergeFront(struct Squeue* squeue) {
    /* Make sure we have at least two nodes. */
    struct Node* node1 = squeue->first;  if (node1 == NULL) return;
    struct Node* node2 = node1->next;    if (node2 == NULL) return;

    /* Create the combined string. */
    char* str1 = node1->val;  size_t str1len = strlen(str1);
    char* str2 = node2->val;  size_t str2len = strlen(str2);
    char* merged = malloc(str1len + str2len + 1);
    memcpy(merged, str1, str1len);
    strcpy(merged+str1len, str2);

    /* Replace the first node's string with the combined string. */
    free(node1->val);
    node1->val = merged;

    deleteNode(squeue, node2);
}

助手:

void deleteNode(struct Squeue* squeue, struct Node* node) {
    if (node->prev == NULL)
        squeue->first = node->next;
    else
        node->prev->next = node->next;

    if (node->next == NULL)
        squeue->last = node->prev;
    else
        node->next->prev = node->prev;

    free(node->val);
    free(node);       
}

注意:

  • 我没有释放tempstring(现在称为merged)指向的内存,因为它仍在使用(squeue->first->val)!
  • 不要猜你需要多少记忆!如有必要,请进行计算。
  • * sizeof(char)没用,因为sizeof(char)总是1
  • 上面的代码需要C99支持,因为它混合了声明和代码。它可以很容易地转换为更向后兼容的代码(以可读性为代价)。
  • 为了让代码变得清晰,我使用了比我需要的更多的变量。
  • 测试。

由于你将这称为#stack; queue-queue",使用堆栈和队列操作会更有意义。

void mergeFront(struct Squeue* squeue) {
    struct Node* node1 = shift(squeue);
    if (node1 == NULL) {
        return;
    }

    struct Node* node2 = shift(squeue);
    if (node2 == NULL) {
        unshift(squeue, node1);
        return;
    }

    char* str1 = node1->val;  size_t str1len = strlen(str1);
    char* str2 = node2->val;  size_t str2len = strlen(str2);
    node1->val = realloc(node1->val, str1len + str2len + 1);
    strcpy(node1->val + str1len, node2->val);

    freeNode(node2);
    unshift(squeue, node1);
}

助手:

void freeNode(struct Node* node) {
    free(node->val);
    free(node);
}

struct Node* shift(struct Squeue* squeue) {
    struct Node* node = squeue->first;
    if (node == NULL)
        return NULL;

    squeue->first = node->next;
    if (node->next == NULL)
        squeue->last = NULL;
    else {
        node->next->prev = NULL;
        node->next = NULL;
    }

    return node;
}

struct Node* pop(struct Squeue* squeue) {
    struct Node* node = squeue->last;
    if (node == NULL)
        return NULL;

    squeue->last = node->prev;

    if (node->prev == NULL)
        squeue->first = NULL;
    else {
        node->prev->next = NULL;
        node->prev = NULL;
    }

    return node;
}

void unshift(struct Squeue* squeue, struct Node* node) {
    if (squeue->first == NULL) {
        squeue->first = node;
        squeue->last = node;
    } else {
        node->next = squeue->first;
        squeue->first = node;
    }
}

void push(struct Squeue* squeue, struct Node* node) {
    if (squeue->last == NULL) {
        squeue->first = node;
        squeue->last = node;
    } else {
        node->prev = squeue->last;
        squeue->last = node;
    }
}

测试。

答案 2 :(得分:0)

这看起来很奇怪

squeue->first->next->val=tempstring;
temp = squeue->first;
squeue->first = temp->next;
free(temp);
free(tempstring);

首先你分配tempstring并指定一个指针val指向它,但后来你释放它使val指向无效。

似乎你应该跳过free(tempstring)

为了合并两个节点。首先检查两个字符串的长度,以分配足够的空间而不是假设100就足够了。分配一个缓冲区,可以包含两个字符串加上结尾\ 0,即在两个字符串上使用strlen()并添加一个。

此后strcpy / strcat两个值都到该缓冲区。

然后释放第一个和第二个节点指向的字符串

然后将第一个节点指定为指向此新节点

然后在第一个节点中设置指针以消除第二个节点,不要忘记释放第二个节点。即每个节点是两个分配,一个用于节点本身,另一个用于它所拥有的字符串。

相关问题