最近发现服务器上一些服务进程一直处于长时间高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;
}
当然,以上的代码只是大概表现了添加链表元素的操作,如需要从链表中取出元素,也要根据每种方法的特殊性考虑各自的细节,特别是在多线程中,链表操作会变得更加复杂。