一、内存申请

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. Elasticsearch 核心插件Kibana 本地文件包含漏洞分析(CVE-2018-17246)

    不久前Elasticsearch发布了最新安全公告, Elasticsearch Kibana 6.4.3之前版本和5.6.13之前版本中的Console插件存在严重的本地文件包含漏洞可导致拒绝服务攻 ...

  2. 开源项目之ASP.NET Core + Vue.js 的前后端分离的通用后台管理系统框架

    年前看了这个开源项目感觉很不错,这个小项目对于传统的.net 开发人员,想做技术提升是一个很不错的参考案例. 开源项目演示地址:https://dnczeus.codedefault.com/logi ...

  3. 《ASP.NET MVC 5 破境之道》:第一境 ASP.Net MVC5项目初探 — 第三节:View层简单改造

    第一境 ASP.Net MVC5项目初探 — 第三节:View层简单改造 MVC默认模板的视觉设计从MVC1到MVC3都没有改变,比较陈旧了:在MVC4中做了升级,好看些,在不同的分辨率下,也能工作得 ...

  4. .net core2.0 codefirst 创建数据库的问题!

    appsettings.json和Startup.cs就不记录了,网上很多!! 1.必须在有DbContext类的项目里添加这3个NuGet引用 Microsoft.EntityFrameworkCo ...

  5. event 自定义事件

    自定义事件 1 public class Program 2 { 3 public event EventHandler ehdl=null; 4 public Program() 5 { 6 ehd ...

  6. Flask系列01--flask认识, 启动, 响应

    一. 四款python web框架简单总结 Django : 优点 - 大而全所有组件都是有组织内部开发高度定制化 教科书级别的框架 缺点 - 浪费资源,请求的时候需要的资源较高 Flask : 优势 ...

  7. Android四种数据存储方式

    一.SharedPreference数据存储篇 1.作用范围 (1).它是一种轻型的数据存储方式 (2).本质是基于XML文件存储key-value键值对数据 (3).通常用来存储一些简单的配置方式 ...

  8. Python 将一个时间戳格式化为(格林威治时间或者本地时区时间)

    时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数. 获取一个时间戳 import time times = time. ...

  9. C/C++ 语言 Hello world

    #include <stdio.h> void main() { int x,i; ; scanf("%d",&x); if(x>y) printf(&q ...

  10. centos6安装最新syslog-ng推送hdfs

    可参考以下网址: installhttps://www.syslog-ng.com/community/b/blog/posts/latest-syslog-ng-available-rhel-6-c ...