一、内存申请

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);
}

C语言中内存管理规范的更多相关文章

  1. JVM内存管理------JAVA语言的内存管理概述

    引言 内存管理一直是JAVA语言自豪与骄傲的资本,它让JAVA程序员基本上可以彻底忽略与内存管理相关的细节,只专注于业务逻辑.不过世界上不存在十全十美的好事,在带来了便利的同时,也因此引入了很多令人抓 ...

  2. JVM内存管理之JAVA语言的内存管理概述

    引言 内存管理一直是JAVA语言自豪与骄傲的资本,它让JAVA程序员基本上可以彻底忽略与内存管理相关的细节,只专注于业务逻辑.不过世界上不存在十全十美的好事,在带来了便利的同时,也因此引入了很多令人抓 ...

  3. C语言的内存管理

    C语言的内存管理 转载:http://blog.csdn.net/wind19/article/details/5964090   对于一个C语言程序而言,内存空间主要由五个部分组成代码段(.text ...

  4. C语言堆内存管理上出现的问题,内存泄露,野指针使用,非法释放指针

    C语言堆内存管理上出现的问题,内存泄露,野指针使用,非法释放指针 (1)开辟的内存没有释放,造成内存泄露 (2)野指针被使用或释放 (3)非法释放指针 (1)开辟的内存没有释放.造成内存泄露,以下的样 ...

  5. C语言中内存分配 (转)

    在任何程序设计环境及语言中,内存管理都十分重要.在目前的计算机系统或嵌入式系统中,内存资源仍然是有限的.因此在程序设计中,有效地管理内存资源是程序员首先考虑的问题. 第1节主要介绍内存管理基本概念,重 ...

  6. 【转】C语言中内存分配

    原文:C语言中内存分配 在任何程序设计环境及语言中,内存管理都十分重要.在目前的计算机系统或嵌入式系统中,内存资源仍然是有限的.因此在程序设计中,有效地管理内存资源是程序员首先考虑的问题. 第1节主要 ...

  7. R语言之内存管理

    转载于:http://blog.csdn.net/hubifeng/article/details/41113789 在处理大型数据过程中,R语言的内存管理就显得十分重要,以下介绍几种常用的处理方法. ...

  8. C#编程(七十三)----------浅析C#中内存管理

    浅析C#中内存管理 前言:个人觉得C#吸收了各种语言的优点,可谓集大成者,但是不知但,这种集所有语言于一身的情况是好是坏.C#编程的一个优点就是程序员不需要关心具体的内存管理,尤其是垃圾收集器会处理所 ...

  9. C语言中内存分配问题:

    推荐: C语言中内存分配 Linux size命令和C程序的存储空间布局 本大神感觉,上面的链接的内容,已经很好的说明了: 总结一下: 对于一个可执行文件,在linux下可以使用 size命令列出目标 ...

随机推荐

  1. LinkedBlockingQueue源码解析(1)

    此文已由作者赵计刚授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 1.对于LinkedBlockingQueue需要掌握以下几点 创建 入队(添加元素) 出队(删除元素) 2 ...

  2. 基于duilib的虚拟列表实现

    本文由作者邹启文授权网易云社区发布. 在邮箱大师选择duilib作为UI开发库后,我们面临这样一个问题.随着时间的积累,用户数据会越来越多,如何保证我们的软件在展示这些数据时依然保持非常好的体验? 原 ...

  3. OI字符串 简单学习笔记

    持续更新qwq KMP 其实是MP啦qwq 就是先自己匹配自己得到状态图,然后再在上面进行模式串的匹配. nxt数组返回的是以该节点结尾的,最长的,在前面出现过的,不相交的,字符串的最靠右的,末位位置 ...

  4. Qt使用gtest进行C++单元测试-01

    环境: win7/win10+qt5.8.0(MinGW), 1.gtest获取: 从:https://www.bogotobogo.com/cplusplus/google_unit_test_gt ...

  5. 变不可能为可能 - .NET Windows Form 改变窗体类名(Class Name)有多难?续篇

    发布<.NET Windows Form 改变窗体类名(Class Name)有多难?>转眼大半年过去了,要不是在前几天有园友对这篇文章进行评论,基本上已经很少关注它了,毕竟那只是一个解惑 ...

  6. 【zookeeper】Apache curator的使用及zk分布式锁实现

    上篇,本篇主要讲Apache开源的curator的使用,有了curator,利用Java对zookeeper的操作变得极度便捷. 其实在学之前我也有个疑虑,我为啥要学curator,撇开涨薪这些外在的 ...

  7. Flask从入门到精通之使用Flask-SQLAlchemy管理数据库

    Flask-SQLAlchemy 是一个Flask 扩展,简化了在Flask 程序中使用SQLAlchemy 的操作.SQLAlchemy 是一个很强大的关系型数据库框架,支持多种数据库后台.SQLA ...

  8. 【JavaScript】call和apply区别及使用方法

    一.方法的定义call方法: 语法:fun.call(thisArg[, arg1[, arg2[, ...]]])定义:调用一个对象的一个方法,以另一个对象替换当前对象.说明:call 方法可以用来 ...

  9. ehcache 页面整体缓存和局部缓存

    页面缓存是否有必要?. 这样说吧,几乎所有的网站的首页都是访问率最高的,而首页上的数据来源又是非常广泛的,大多数来自不同的对象,而且有可能来自不同的db ,所以给首页做缓存是很必要的.那么主页的缓存策 ...

  10. cas单点登陆系统-建立单点登陆系统的应用

    上一篇如果已经操作成功,说明casServer已经实现了,下面就是搭建casClient与casServer联合调试.代码已经上传到github上.你可以下载看看,如果自己在搭建的过程中遇到问题,你也 ...