C语言中内存管理规范
一、内存申请
1.建议使用calloc申请内存,尽量不要使用malloc。
calloc在动态分配完内存后,自动初始化该内存空间为零,而malloc不初始化,里边数据是随机的垃圾数据。
2.申请内存大小必须大于0.
(1)使用0字节长度申请内存的行为是没有定义的,在引用内存申请函数返回地址时会引发不可预知错误,对于可能出现申请0长度内存的情况非常有必要判断,避免出现这种情况。
(2)使用负数长度申请内存,负数会被当成一个很大的无符号整数,导致申请内存过大而出现失败。
3.申请内存后检查是否申请成功,即检查返回指针是否为NULL,即是否为0。
二、内存释放
1.申请的内存一定需要释放,有且仅能释放一次
2.禁止释放或函数内返回非动态申请的内存(栈中的内存,函数中的临时变量等)
3.指针释放后必须将指针指向空指针,否则会出现野指针的情况。
三、附加一个C实现的存储二叉树元素的动态栈
#include<stdio.h> #include<string.h> #include<malloc.h> #define LH_MALLOC(pMemory,Type,Size) \ if(Size > 0)\ {\ pMemory=(Type*)calloc(Size/sizeof(Type),sizeof(Type));\ }\ else\ {\ pMemory=NULL;\ }\ #define LH_FREE(p) if(NULL != p){free(p);p=NULL;} #define LH_MEMORY_MOV(dst,dstSize,src,srcSize,Type)\ LH_MALLOC(dst,Type,dstSize)\ memcpy(dst,src,srcSize);\ LH_FREE(src)\ typedef struct tagTreeNode { int v; struct tagTreeNode* pleft; struct tagTreeNode* pright; }TreeNode;
typedef struct tagLinearStack
{
TreeNode* ptrees;
int* ptags;
int maxsize;
int index;
}LinearStack;
/*获取一个栈指针*/ LinearStack* getALinearStack() { LinearStack* pstack; LH_MALLOC(pstack,LinearStack,sizeof(LinearStack)); return pstack; } /*释放栈,与getALinearStack成对使用*/ void freeLinearStack(LinearStack* pstack) { LH_FREE(pstack->ptags); LH_FREE(pstack->ptrees); LH_FREE(pstack); } /*入栈*/ void push(LinearStack* pstack,TreeNode node) { if(pstack->ptrees == 0 && pstack->ptags == 0) { LH_MALLOC(pstack->ptrees,TreeNode,sizeof(TreeNode)*5); LH_MALLOC(pstack->ptags,int,sizeof(int)*5); pstack->maxsize=5; } if(pstack->index < pstack->maxsize) { pstack->ptrees[pstack->index++]=node; } else { TreeNode* tmpTrees; int* tmptags; LH_MEMORY_MOV(tmpTrees, sizeof(TreeNode)*pstack->maxsize*2, pstack->ptrees, sizeof(TreeNode)*pstack->maxsize, TreeNode); LH_MEMORY_MOV(tmptags, sizeof(int)*pstack->maxsize*2, pstack->ptags, sizeof(int)*pstack->maxsize, int); pstack->ptrees=tmpTrees; pstack->ptags=tmptags; pstack->maxsize=pstack->maxsize*2; pstack->ptrees[pstack->index++]=node; } } /*弹出栈*/ TreeNode pop(LinearStack* pstack) { if(pstack->index > 0) { return pstack->ptrees[--pstack->index]; } } void main() { LinearStack* pstack=getALinearStack(); if(NULL == pstack) retrun; for(int i=0;i<60000;i++) { a.v=i; push(pstack,a); } for(int j=0;j<60000;j++) { TreeNode node=pop(pstack); printf("%d: %d \n",j,node.v); } freeLinearStack(pstack); }
四、二叉树非递归遍历方法
void preOrder(TreeNode* pnode) { LinearStack* pstack=getALinearStack(); while(NULL != pnode || pstack->index > 0) { while(NULL!=pnode) { printf("%c ",pnode->v); push(pstack,*pnode); pnode=pnode->pleft; } pnode=pop(pstack); pnode=pnode->pright; } freeLinearStack(pstack); } void middleOrder(TreeNode* pnode) { LinearStack* pstack=getALinearStack(); while(NULL != pnode || pstack->index > 0) { while(NULL!=pnode) { push(pstack,*pnode); pnode=pnode->pleft; } pnode=pop(pstack); printf("%c ",pnode->v); pnode=pnode->pright; } freeLinearStack(pstack); } void postOrder(TreeNode* pnode) { LinearStack* pstack=getALinearStack(); while(NULL != pnode || pstack->index > 0) { while(NULL != pnode) { push(pstack,*pnode); pstack->ptags[pstack->index-1]=0; pnode=pnode->pleft; } if(pstack->ptags[pstack->index-1]==0) { pstack->ptags[pstack->index-1]=1; pnode=pstack->ptrees[pstack->index-1].pright; } else { while(pstack->ptags[pstack->index-1]==1) { pnode=pop(pstack); printf("%c ",pnode->v); } pnode=NULL; } } freeLinearStack(pstack); } void init() { a.v='a';a.pleft=&b;a.pright=&c; b.v='b';b.pleft=&d;b.pright=&e; c.v='c';c.pleft=0;c.pright=0; d.v='d';d.pleft=0;d.pright=&f; e.v='e';e.pleft=&g;e.pright=0; f.v='f';f.pleft=0;f.pright=0; g.v='g';g.pleft=0;g.pright=0; } void main() { init(); postOrder(&a); }
五、线索二叉树
typedef enum{Link,Thread} PointerTag; typedef struct tagTreeNode { char v; PointerTag ltag,rtag; struct tagTreeNode* pleft; struct tagTreeNode* pright; }TreeNode; TreeNode a,b,c,d,e,f,g; void init() { a.v='a';a.pleft=&b;a.pright=&c; b.v='b';b.pleft=&d;b.pright=&e; c.v='c';c.pleft=0;c.pright=0; d.v='d';d.pleft=0;d.pright=&f; e.v='e';e.pleft=&g;e.pright=0; f.v='f';f.pleft=0;f.pright=0; g.v='g';g.pleft=0;g.pright=0; } TreeNode *pre; void InitThreadRootTree(TreeNode* ptree) { if(NULL != ptree) { InitThreadRootTree(ptree->pleft); if(ptree->pleft == NULL) { ptree->ltag=Thread; ptree->pleft=pre; } if(pre->pright == NULL) { pre->rtag=Thread; pre->pright=ptree; } pre=ptree; InitThreadRootTree(ptree->pright); } } void BuildThread(TreeNode* phead,TreeNode* ptreeRoot) { if(NULL == ptreeRoot) { phead->ltag=Link; phead->pleft=phead; } else { phead->ltag=Link; phead->pleft=ptreeRoot; pre=phead; InitThreadRootTree(ptreeRoot); pre->pright=phead; pre->rtag=Thread; phead->pright=pre; } } void midOrderThread(TreeNode* phead) { TreeNode* treeNode = phead->pleft; while(phead != treeNode) { while(treeNode->ltag == Link) { treeNode=treeNode->pleft; } printf("%c ",treeNode->v); while(treeNode->rtag==Thread && treeNode->pright != phead) { treeNode=treeNode->pright; printf("%c ",treeNode->v); } treeNode=treeNode->pright; } } void main() { init(); TreeNode head; head.rtag=Link; head.pright=&head; BuildThread(&head,&a); midOrderThread(&head); }