C语言中内存管理规范
2024-09-21 08:09:10
一、内存申请
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 > )\
{\
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 == && pstack->ptags == )
{
LH_MALLOC(pstack->ptrees,TreeNode,sizeof(TreeNode)*);
LH_MALLOC(pstack->ptags,int,sizeof(int)*);
pstack->maxsize=;
} if(pstack->index < pstack->maxsize)
{
pstack->ptrees[pstack->index++]=node;
}
else
{
TreeNode* tmpTrees;
int* tmptags;
LH_MEMORY_MOV(tmpTrees,
sizeof(TreeNode)*pstack->maxsize*,
pstack->ptrees,
sizeof(TreeNode)*pstack->maxsize,
TreeNode); LH_MEMORY_MOV(tmptags,
sizeof(int)*pstack->maxsize*,
pstack->ptags,
sizeof(int)*pstack->maxsize,
int);
pstack->ptrees=tmpTrees;
pstack->ptags=tmptags;
pstack->maxsize=pstack->maxsize*;
pstack->ptrees[pstack->index++]=node;
}
} /*弹出栈*/
TreeNode pop(LinearStack* pstack)
{
if(pstack->index > )
{
return pstack->ptrees[--pstack->index];
}
} void main()
{
LinearStack* pstack=getALinearStack();
if(NULL == pstack)
retrun;
for(int i=;i<;i++)
{
a.v=i;
push(pstack,a);
}
for(int j=;j<;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 > )
{
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 > )
{
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 > )
{
while(NULL != pnode)
{
push(pstack,*pnode);
pstack->ptags[pstack->index-]=;
pnode=pnode->pleft;
}
if(pstack->ptags[pstack->index-]==)
{
pstack->ptags[pstack->index-]=;
pnode=pstack->ptrees[pstack->index-].pright;
}
else
{
while(pstack->ptags[pstack->index-]==)
{
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=;c.pright=;
d.v='d';d.pleft=;d.pright=&f;
e.v='e';e.pleft=&g;e.pright=;
f.v='f';f.pleft=;f.pright=;
g.v='g';g.pleft=;g.pright=;
} 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=;c.pright=;
d.v='d';d.pleft=;d.pright=&f;
e.v='e';e.pleft=&g;e.pright=;
f.v='f';f.pleft=;f.pright=;
g.v='g';g.pleft=;g.pright=;
}
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);
}
最新文章
- html 杂记
- 从一个Fragment跳转到另一个Fragment
- Linux&;shell 之Shell命令进阶
- web前端面试试题总结---其他
- spring mvc和web-flow的整合方案
- sqlite数据库如何远程连接?
- SQL运维
- Java爬网页数据,并存储到本地数据库中
- git从其他分支提取文件merge到当前分支
- Knockout.Js官网学习(Mapping高级用法二)
- from collections import namedtuple 使用
- 【BZOJ】2111: [ZJOI2010]Perm 排列计数 计数DP+排列组合+lucas
- C# switch-case中的或(or)操作
- 解决windows 下mysql 表名自动转成小写的问题
- Bezier曲线
- web三大组件的加载顺序
- CSS顶级技巧大放送,div+css布局必知
- Mysql数据库的增删改查
- WPF判断当前窗体是否为模态
- java容器 Map Set List