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