不要忽视任何细节---C语言链表操作的教训

最近发现服务器上一些服务进程一直处于长时间高CPU状态,有些进程甚至要跑10分钟左右,跟踪了一下发现,问题出现在如23-28代码中:


#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct LIST
{
    int nValue;
    struct LIST *ptNext;
}List;

void Add2List(List **ptList, int nValue)
{
    List *ptNew = (List *)calloc(1, sizeof(List));
    ptNew->nValue = nValue;

    if(NULL == *ptList)
    {
        (*ptList) = ptNew;
    }
    else
    {
        //找到最后一个节点,将新节点放在这个节点之后
        List *ptTemp = (*ptList);
        while(ptTemp->ptNext)
        {
            ptTemp = ptTemp->ptNext;
        }
        ptTemp->ptNext = ptNew;
    }
}

int main()
{
    List *ptList = NULL;

    Add2List(&ptList, 1);
    Add2List(&ptList, 2);

    return 0;
}


出现问题的原因在于每次添加一个节点,都要遍历整个链表,在链表Node个数较少的情况下,不会出现问题,但是当Node个数达到万或者十万百万量级的时候,这样的操作是相当的耗时,当时写这个代码的时候就是图简单,因实际运行的环境中90%都是Node数量较少的情况,所以就直接写下了这么烂的代码,终于在遇到大数据量的情况,出现了问题。

解决办法有两个,如果不要求链表中的数据先进先出,可以是直接将新Node添加在表头,这时,只需要修改添加元素的函数就可以了,代码如下:

//直接添加在链表头
void Add2List(List **ptList, int nValue)
{
    List *ptNew = (List *)calloc(1, sizeof(List));
    ptNew->nValue = nValue;

    ptNew->ptNext = *ptList;
    *ptList= ptNew;
}

如果对链表元素顺序有要求的话,可以考虑记住链表最后一个元素的位置,这时需要重新设计链表结构,代码如下:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct NODE
{
    int nValue;
    struct NODE *ptNext;
}Node;

typedef struct LIST
{
    Node *ptLast;
    Node *ptList;
}List;

void Add2List(List **ptList, int nValue)
{
    Node *ptNew = (Node *)calloc(1, sizeof(Node));
    ptNew->nValue = nValue;

    if(NULL == *ptList)
    {
        (*ptList) = (List *)calloc(1, sizeof(List));
        (*ptList)->ptLast = (*ptList)->ptList = ptNew;
    }
    else
    {
        (*ptList)->ptLast->ptNext = ptNew;
        (*ptList)->ptLast = ptNew;
    }
}

int main()
{
    List *ptList = NULL;

    Add2List(&ptList, 1);
    Add2List(&ptList, 2);

    return 0;
}


当然,以上的代码只是大概表现了添加链表元素的操作,如需要从链表中取出元素,也要根据每种方法的特殊性考虑各自的细节,特别是在多线程中,链表操作会变得更加复杂。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值