树、内存、栈

来源:互联网 发布:qq音乐数据库 api接口 编辑:程序博客网 时间:2024/06/08 15:38


#include <stdio.h>
#include <string.h>
#define MEMORY_SIZE 102400

typedef unsigned char BYte;
typedef void* PTr;
typedef PTr (*NOdefunc)(void);     //函数指针NOdefunc
typedef void (*DOfunc)(int n, PTr p);   //函数指针DOfunc

typedef struct _MEmory* PCmemory;
typedef struct _MEmory
{
 BYte amem[MEMORY_SIZE];     //存储数据
 int nmem_point;       //存数的字节数
} CMemory;

typedef struct _STack* PCstack;
typedef struct _STack
{
 PTr pcontent;        //树的当前结点
 PCstack pnext;        //指向上一个栈
} CStack;

typedef struct _Tree* PCtree;
typedef struct _Tree
{
 PTr pcontent;        //结点的内容
 PCtree pson;       //指向孩子结点的指针
 PCtree pbrother;       //指向兄弟结点的指针
} CTree;

void Minit(PCmemory pmem);
PTr Malloc(PCmemory pmem, int size);
PCstack Snew(void);
PCstack Spush(PCstack pstk, PTr p);
PCstack Spop(PCstack pstk, PTr* p);
PCtree Tnew(void);
void Taddson(PCtree ptree, NOdefunc f);
void Taddbrother(PCtree ptree, NOdefunc f);
void Tbrowse(PCtree ptree,DOfunc f, int n);
void Tbrowse_Satck(PCtree ptree, DOfunc f, int n);
PTr Node(void);
void Out(int n,PTr p);

static CMemory mem;       //静态区分配的内存,用于存储数据及字节数
PCmemory xpmem = &mem;       //指向该内存的指针

static char* aanode[28]=
 { "1","2","3",NULL,"4",NULL,"5", NULL,NULL,
   "6",NULL,"7","8",NULL, "9","10",NULL,"11",NULL,"12",NULL,NULL,
   NULL,NULL,NULL,NULL,NULL,NULL};
static int nnode=0;       //aanode[nnode]

int main(int argc, char* argv[])
{
 //printf("sizeof(aanode)/sizeof(aanode[0]) = %d\n", sizeof(aanode)/sizeof(aanode[0]));
 //printf("aanode[sizeof(aanode)/sizeof(aanode[0])] = %p\n", aanode[sizeof(aanode)/sizeof(aanode[0])]);
  
 Minit(xpmem);        //初始化分配的静态区内存
 PCtree ptree = Tnew();      //建立一个带虚根结点的空树
 Taddson(ptree, Node);      //为该树添加结点并赋予数据
 Tbrowse(ptree->pson, Out, 0);    //遍历该树
 Tbrowse_Satck(ptree->pson, Out, 0);   //遍历栈空间
}

/******************************************************************************/
void Minit(PCmemory pmem)     //内存空间初始化函数
{
 pmem->nmem_point = 0;      //初始字节数为0
}

/******************************************************************************/
PTr Malloc(PCmemory pmem, int size)   //在已申请的内存空间里分配空间
{
 int n_cur_mem_p;
 n_cur_mem_p = pmem->nmem_point;
 pmem->nmem_point += size;
 //return (PTr)(&(pmem->amem[n_cur_mem_p]));
 //进行内存边界检查
 return (pmem->nmem_point > n_cur_mem_p)&& (pmem->nmem_point < MEMORY_SIZE)?
   (PTr)(pmem->amem+n_cur_mem_p):NULL;
}

/******************************************************************************/
PCstack Snew(void)        //建立空栈
{
 return NULL;
}

/******************************************************************************/
PCstack Spush(PCstack pstk, PTr p)   //压栈操作,也在申请的内存空间分配
{
 PCstack pstknew;
 pstknew = (PCstack)Malloc(xpmem, sizeof(CStack));  //新申请一个栈单元空间
 pstknew->pcontent = p;      //将树的当前结点的数据压栈
 pstknew->pnext = pstk;      //
 return pstknew;       //重新定位栈的头指针,并返回(前插型)
}

/******************************************************************************/
PCstack Spop(PCstack pstk, PTr* pp)   //出栈操作
{
 if(pstk!=NULL)
 {
  *pp = pstk->pcontent;     //将当前栈单元的数据赋给树结点指针
  pstk = pstk->pnext;     //
  return pstk;       //重新定位栈的头指针,并返回
 }
 else
  return NULL;
}

/******************************************************************************/
PCtree Tnew(void)       //建立带虚根节点的空树
{
 PCtree proot;
 proot = (PCtree)Malloc(xpmem, sizeof(CTree));
 proot->pcontent = "ROOT";
 proot->pson=NULL;      //无孩子
 proot->pbrother=NULL;     //无兄弟
 return proot;        //返回该虚根节点的指针
}

/******************************************************************************/
void Taddson(PCtree ptree, NOdefunc f)  //添加孩子结点函数
{
 PTr p = f();
 if(p==NULL)
 {
  Taddbrother(ptree,f);    //若当前结点无孩子,则添加兄弟结点
 }
 else
 {
  PCtree ptreenew = (PCtree)Malloc(xpmem,sizeof(CTree));
  ptreenew->pson=NULL;
  ptreenew->pbrother=NULL;
  ptreenew->pcontent = p;
  ptree->pson = ptreenew;    //当前结点添加好了孩子结点
  Taddson(ptreenew,f);    //为该孩子结点添加孩子结点
           //(实现的操作:有孩子结点添加,无孩子则添加兄弟结点)
  Taddbrother(ptree,f);    //为当前结点添加兄弟结点
 }
}

/******************************************************************************/
void Taddbrother(PCtree ptree, NOdefunc f) //添加兄弟结点函数
{
 PTr p = f();
 if(p==NULL)
  return;        //若也无兄弟结点,则结束
 else
 {
  PCtree ptreenew = (PCtree)Malloc(xpmem,sizeof(CTree));
  ptreenew->pson=NULL;
  ptreenew->pbrother=NULL;
  ptreenew->pcontent = p;
  ptree->pbrother = ptreenew;   //当前结点添加好了兄弟结点
  Taddson(ptreenew,f);    //为该兄弟结点添加孩子结点
 }
}

/******************************************************************************/
void Tbrowse(PCtree ptree,DOfunc f, int n) //遍历树
{
 if(ptree!=NULL)
 {
  f(n,ptree->pcontent);    //先结点
  Tbrowse(ptree->pson,f,n+1);   //接着孩子结点
  Tbrowse(ptree->pbrother,f,n);  //最后兄弟结点
 }
}

/******************************************************************************/
void Tbrowse_Satck(PCtree ptree, DOfunc f, int n)//遍历栈空间,n=0
{
 PCstack pstk;
 pstk = Snew();        //新建一个空栈
 while(1)
 {
  f(n, ptree->pcontent);     //打印当前栈单元的内容
  //这个分支里,栈的首指针没有移动
  if(ptree->pson==NULL)     //当前结点无孩子结点,则转向其兄弟结点
  {
   while(ptree->pbrother==NULL)  //若无兄弟结点
   {
    pstk = Spop(pstk,(PTr*)&ptree); //出栈
    n--;       //深度-1
    if(pstk == NULL)
     return;      //出口:栈为空
   } 
   ptree = ptree->pbrother;   //取当前结点的兄弟结点
  }
  //这个分支里,栈的首指针有移动
  else   
  {
   pstk = Spush(pstk,ptree);   //压栈
   n++;        //深度+1
   ptree = ptree->pson;    //取当前结点的孩子结点
  } 
 }
}
/*
总结:栈的首指针在求取孩子结点过程中有变化(pstk = Spush(pstk,ptree);),而在求取兄弟结点过程中无改变.
 所以,求取孩子结点1,2,到这里栈的内容指针指向的是结点2;此后求取3,4,5,栈的内容指针都没有发生改变;
 到结点5时,其没有兄弟结点,则对ptree重新定位为结点2(pstk = Spop(pstk,(PTr*)&ptree);),
 而栈的内容指针也重新定位为结点1;
 接着再继续...直到栈为空为止。
*/

/******************************************************************************/
PTr Node(void)
{
 return aanode[nnode++];
}

/******************************************************************************/
void Out(int n,PTr p)
{
 int i;
 for(i=0; i<n; i++)
 {
  printf("_");
 }
 printf("%s\n",p);
}

0 1
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 中通快递到达一天就是不派送怎么办 顺丰派送员把快递寄错了怎么办 顺丰快递把户籍卡弄丢了怎么办 金立手机不小心设置成英文了怎么办 三星手机不小心设置成英文了怎么办 手游方舟国际版渡渡鸟跟丢了怎么办 一打电话4g变2g怎么办 手机4g突然变2g怎么办 江湖风云录八卦门任务拒绝了怎么办 百度网盘下载时显示违规信息怎么办 在海马助手下载的游戏闪退怎么办 手机版百度云盘不能普通下载怎么办 手机版百度云盘一直加载中怎么办 登别人的网盘单同步通讯录了怎么办 被培训公司骗了贷款之后该怎么办 乐教乐学孩子登陆你那忘记了怎么办 脸擦破了痂掉了留斑怎么办 挤黑头后鼻子又红又疼怎么办 香奈儿邂逅清新淡香水不喷怎么办 脚面被压了肿起来了怎么办 每天加班很累反而失眠严重怎么办 减肥药吃了口臭嘴巴苦怎么办 上火引起的牙疼怎么办吃什么药 舌苔厚口气重怎么办应该吃什么药 宝宝老是额头热四肢不热怎么办 考老师考砸了心理崩溃了怎么办 苹果手机一会白屏一会黑屏怎么办 360云盘的东西删不了怎么办 手机邮箱打开的文件疑似病毒怎么办 电脑qq发送的文件失效了怎么办 小米4c温控文件打开是乱码怎么办 超星尔雅用学号登录密码忘了怎么办 全脸做激光去黄褐斑后脸发红怎么办 上传到微云中的视频下载不了怎么办 微云保存的小电影下载不了怎么办 苹果手机下载有云朵下载不了怎么办 手机下载登录忘了密码了怎么办 软软件被手机加密忘了密码怎么办 苹果手机想下载东西忘了密码怎么办 已经不念书几年了突然想上学怎么办 江湖风云录把王老爷子杀了怎么办