如何在循环中创建节点并将它们插入链表

How to create nodes in a loop and insert them to a linked list

这是我的结构:

typedef struct gene{
    char* name;
    int length;
    int* sequence;
} gene;

typedef struct genes{
    gene gene;
    struct genes* next;
} genes;

构造函数:

genes* createGenes(gene newGene){
    genes* geneArr = malloc(sizeof(genes));
    if (NULL != geneArr){
        geneArr->gene = newGene;
        geneArr->next = NULL;
    }
    return geneArr;
}

void deleteGenes(genes* geneArr){
    if(NULL != geneArr->next){
        deleteGenes(geneArr->next);
    }
    free(geneArr);
}

genes* addGene(genes* geneList, gene newGene){
    genes* toAdd = createGenes(newGene);
    if (NULL != toAdd){
        geneList->next = toAdd;
    }
    return geneList;
}

和一个函数(它创建一个具有给定长度的序列。对于 5 -> {2, 2, 2, 2, 2}):

gene twosGene(char* name, int length){
    gene newGene;
    newGene.name = name;
    newGene.length = length;
    newGene.sequence = (int*)malloc(sizeof(int) * length);

    for(int i = 0; i < length; i++){
        newGene.sequence[i] = 2;
    }
    return newGene;
}

这是我的 main() 函数:

int main(){
    int count = 1;

    genes* geneArr = createGenes(twosGene("gene1", count++));

    for (int i = 0; i < 4; ++i) {
        geneArr = addGene(geneArr, twosGene("geneLoop", count++));
    }

    genes* iter;
    for (iter = geneArr; NULL != iter; iter = iter->next) {
        printf("gene=%d\n", iter->gene.length);
        free(iter->gene.sequence);
    }

    deleteGenes(geneArr);

    return 0;
}

我期望这样的输出:

gene=1
gene=2
gene=3
gene=4
gene=5

但我得到的是:

gene=1
gene=5

另外,当我使用 Valgrind 时,我的程序中有一些泄漏。

==20580== HEAP SUMMARY:
==20580==     in use at exit: 132 bytes in 6 blocks
==20580==   total heap usage: 11 allocs, 5 frees, 1,244 bytes allocated

我不明白为什么。感谢您的帮助。

在此函数内

genes* addGene(genes* geneList, gene newGene){
    genes* toAdd = createGenes(newGene);
    if (NULL != toAdd){
        geneList->next = toAdd;
    }
    return geneList;
}

你总是覆盖最初在语句中创建的节点的下一个数据成员

genes* geneArr = createGenes(twosGene("gene1", count++));

您似乎想在当前列表的末尾添加一个新节点。在这种情况下,函数看起来像

genes* addGene(genes* geneList, gene newGene){
    genes* toAdd = createGenes(newGene);
    if (NULL != toAdd){
        genes *current = geneList;

        while ( current->next != NULL ) current = current->next;
        current->next = toAdd;
    }
    return geneList;
}

但是通常这个函数定义也是无效的,因为最初 geneList 可以等于 NULL。所以使用你的方法应该按以下方式重写函数

genes* addGene(genes* geneList, gene newGene){
    genes* toAdd = createGenes(newGene);
    if (NULL != toAdd){
        if ( geneList == NULL )
        {
            geneList = toAdd;
        }
        else
        {
            genes *current = geneList;

            while ( current->next != NULL ) current = current->next;
            current->next = toAdd;
        }
    }

    return geneList;
}

然而,如果将指针传递给列表的头指针,即使这个函数实现也可以得到改进。

例如

int addGene( genes **geneList, gene newGene )
{
    genes* toAdd = createGenes(newGene);
    int success = toAdd != NULL;

    if ( success )
    {
        while ( *geneList != NULL ) geneList = &( *geneList )->next;
        *geneList = toAdd;
    }

    return success;
}

在这种情况下函数可以这样调用

genes* geneArr = createGenes(twosGene("gene1", count++));

for (int i = 0; i < 4; ++i) {
    addGene( &geneArr, twosGene("geneLoop", count++));
}

在:

genes* geneArr = createGenes(twosGene("gene1", count++));

for (int i = 0; i < 4; ++i) {
    geneArr = addGene(geneArr, twosGene("geneLoop", count++));
}

第一个分配链表的头部。在 for 循环中,接下来每次迭代都会覆盖这个 head。你 should/could 做了:

genes* geneArr = createGenes(twosGene("gene1", count++));

genes *geneNext= geneArr;
for (int i = 0; i < 4; ++i) {
    geneNext = addGene(geneNext, twosGene("geneLoop", count++));
}

此外,addGene 必须提前指针才能使上述工作正常。

genes* addGene(genes* geneList, gene newGene){
    genes* toAdd = createGenes(newGene);
    if (NULL != toAdd){
        geneList->next = toAdd;
        genelist= geneList->next;  // add this statement.
    }
    return geneList;
}

现在可以打印了,因为你还有头。

addGene 函数未添加到列表末尾。它只是将新基因与第一个基因联系起来。正如 Valgrind 所报告的,列表中第一个基因之后的任何内容都是 "forgotten",导致内存泄漏。

这是 addGenes 函数的更新版本,应该可以使用:

genes* addGene(genes* geneList, gene newGene){
    genes* toAdd = createGenes(newGene);
    if (NULL != toAdd){
        if (geneList == NULL){
            geneList = toAdd;
        } else {
            genes *last = geneList;
            while (last->next != NULL){
                last = last->next;
            }
            last->next = toAdd;
        }
    }
    return geneList;
}