一、内存申请

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. asp.net—自定义轻量级ORM

    大型项目中ORM的使用已经是相当的频繁.目前.NET(C#)中比较流行的ORM框架也有很多,比如SqlSugar,Dapper,Entity Framework(EF)等. 相信很多有2年以上工作经验 ...

  2. C#委托总结-入门篇

    1,概念:委托类型表示对具有特定参数列表和返回类型的方法的引用. 通过委托,可以将方法视为可分配给变量并可作为参数传递的实体. 委托是引用类型,可以把它看作是用来存方法的一种类型.比如说类型strin ...

  3. .net core获取appsettings CustomSettings

    private static string GetCustomSettings(string key) { var config = new ConfigurationBuilder() .AddIn ...

  4. 如何实现session跨服务器共享

    Session共享有多种解决方法,常用的有四种:客户端Cookie保存.服务器间Session同步.使用集群管理Session.把Session持久化到数据库. 1.客户端Cookie保存 以cook ...

  5. sql语句_2

    数据表如下 一个user_id对应多个user_name,现在要求是:如果某个用户对应的user_name中存在一个a,打印user_id,a出来:如果不存在,打印user_id,0.打印时候user ...

  6. 二,PHP会话机制---session的基本使用

    1,思考:登录网站后,在每个网页都能拿到用户信息 (1) 使用超链接传递用户名,这样太繁琐了,不建议使用 . (2) 使用数据库,每打开一个页面都查询一次用户信息表,这样网页加载速度变慢,用户体验变差 ...

  7. Get Requests with Json Data && Get Requests with Url Parameters

  8. AndroidManifest.xml文件安全探索

    本文作者:i春秋签约作家——icq8756c1a2 最近在做一些apk的安全检测,对AndroidManifest.xml文件进行了研究和探讨,介绍AndroidManifest.xml文件的作用和架 ...

  9. Maven+SSM框架项目实例——IDEA

    一.项目环境 开发系统:Window10 开发工具:IDEA JDK:1.8 框架:Maven+Spring+SpringMVC+Mybatis 数据库:Mysql 二.项目结构 项目文件架构:  三 ...

  10. SVN常用操作介绍

    SVN:全称subversion,开源代码版本控制系统,也就是常说的“版本控制工具”,实现代码.文档等的历史版本保存.共享和权限管理.常用于软件开发项目中,开发将最新的代码放到svn,其他同事可在这个 ...