二叉树的相关操作

来源:互联网 发布:网络都市小说大纲范例 编辑:程序博客网 时间:2024/04/27 06:57

利用先序建树,二叉树的遍历才是重点,针对这章,编写了非递归遍历的几种方法

 

习惯性操作 将一些头文件包含在头文件t11.h中

 

#include"stdio.h"
#include"string.h"
#include"ctype.h"
#include"malloc.h"
#include"stdlib.h"  //atoi(),exit();
#include"io.h"      //eof()
#include"math.h"


#define  TRUE  1
#define  FALSE  0
#define  OK   1
#define  ERROR 0

typedef int Status;
typedef int Boolean;

 

在之后就是数据结构定义了,英语没学好啊,ercs.h中

 

#define INIT_STACK 40
#define ADD 2
typedef struct Binode   //   定义二叉树节点类型
{
 char data;                 // 存入元素
    Binode *lchild,*rchild;    // 定义左孩子和右孩子的结构体指针

}Binode,*Bitree;

struct lpBitree         //  定义的存储二叉树结构体的结构体
{
 Bitree lp;
 int i;             //  方便对栈操作,而设定的,在后序非递归遍历中一个判断变量
};

typedef struct        // 定义栈结构体
{
 lpBitree *bottom;
 lpBitree *top;
 int stacksize;
}Sqstack,*linkstack;

 

之后就是具体的实现函数代码了,定义在ercs.cpp中,利用栈的操作,根据遍历顺序,采取相应的操作

 

void inittree(Bitree &T)             //  初始化二叉树
{
 T=NULL;
}

void initstack(Sqstack &L)         //  初始化栈
{
 L.bottom=(lpBitree*)malloc(INIT_STACK*sizeof(lpBitree));
 L.top=L.bottom;
 L.stacksize=INIT_STACK;
}
Status push(Sqstack &L,Bitree e)      // 入栈操作
{
 if(L.top-L.bottom >= L.stacksize)     // 栈空间不足
    {
  L.bottom=(lpBitree*)realloc(L.bottom,(L.stacksize+ADD)*sizeof(lpBitree));
  L.top=L.bottom+L.stacksize;
  L.stacksize+=ADD;
    }
 L.top->i=0;                 //  将首次入栈的元素同时表示执行次数,在gettop()函数中改变其值
 (L.top++)->lp=e;
 return OK;
}

Status pop(Sqstack &L,Bitree &e)          // 出栈操作
{
 if(L.top == L.bottom)
  return ERROR;
 else
    {
     e=(--L.top)->lp;
     return OK;
    }
}

Status emptystack(Sqstack L)             //  判断栈是否为空
{
 if(L.bottom == L.top)
  return OK;
 else
  return ERROR;
}

Status gettop(Sqstack &L,Bitree &T)       //  获取元素操作
{
 if(L.bottom == L.top)
  return ERROR;
 else
 {
  T=(L.top-1)->lp;
  ++(L.top-1)->i;                   //  每执行此函数,栈中相应的i值发生变化
  return OK;
 }
}

void Createtree(Bitree &T)           // 先序创建二叉树
{
 char ch;
 ch=getchar();
 if(ch == 10)                           //  如果是回车键置为空
  T=NULL;
 else
 {
  T=(Bitree)malloc(sizeof(Binode));
  if(!T)
  {
   printf("分配失败!");
   exit(0);
  }
  if(ch != ' ')              // 不为空格键执行递归调用
  {
   T->data=ch;
   Createtree(T->lchild);
   Createtree(T->rchild);
  }
  else
  {
   while(' ' == ch)      //  屏蔽空格键
    ch=getchar();
   T->data=ch;
   Createtree(T->lchild);
   Createtree(T->rchild);
  }
 }
}                               // 创建二叉树结束

void xianxu(Bitree T,Sqstack &S)   //  先序非递归遍历,采用的是保存右孩子的地址通过栈实现
{
 printf("先序非递归遍历输出:\n");
    if(T)
 {
  if(T->rchild)
   push(S,T->rchild);    //  专门压入右孩子指针地址
  printf("%-3c",T->data);
  T=T->lchild;            //  更新指针
 }else
  exit(0);
 
 while(T || !emptystack(S))     //  循环终止条件
 {
  if(T!= NULL)             //  始终作为一个点存在加以判断,一种情况是一直指向左孩子,另一种就是出栈弹出的右孩子
  {
   printf("%-3c",T->data);    //  输出节点的数据域
   if(T->rchild != NULL)    // 该节点存在右孩子,将右孩子入栈
    push(S,T->rchild);
   T=T->lchild;       //  更新指针,始终往左走
  }
  else
   pop(S,T);  
 }
}

void protraver(Bitree T,Sqstack &S)           // 中序非递归遍历输出
{
 printf("\n中序非递归遍历输出:\n");
 while(T||!emptystack(S))        //  中序遍历规律与相关栈的操作
 {
  if(T)           
  {
   push(S,T);
   T=T->lchild;
  }
  else
  {
   pop(S,T);
   printf("%-3c",T->data);
   T=T->rchild;
  }  
 }
 printf("\n");
}

void lasttraver(Bitree T,Sqstack &S)     // 后序非递归遍历程序 ,主要是采用i标记当一个元素左右孩子都存在,何时才应该出栈此元素
{
 printf("后序非递归遍历输出:\n");
 int   num=0;       //  记录单节点的个数
 int   leaf=0;        //  记录叶子树
 if(T)
  push(S,T);         //  头不为空,将其压入栈中
 else
  exit(0);           //  头空退出
 while(!emptystack(S))   //  判断是否栈空
 {
  if(T->lchild != NULL && (S.top-1)->i == 0)      //  往左循环,相应的i值要为0,保证往左只有一次
  {
   if(T->rchild == NULL)                   //  单节点数的个数,条件是只有一个孩子,判断条件起始为0   防止后面修改,先获取单节点数
    num++;
   T=T->lchild;
   push(S,T);
  } 
  else
  {
   if(T->rchild != NULL && (S.top-1)->i == 0)
    num++; 
   if((S.top-1)->i == 2)     //  通过gettop()函数调用而改变的i的值,当获取次数为2次时,表明此元素出栈元素
   {
    pop(S,T);
    printf("%-3c",T->data);
    gettop(S,T);        //  获取栈顶元素,并且是i值加1
   }
   else
   {
    if(T->lchild == NULL)       //  左子树为空,相应的标记加1,直接寻找右子树
     ++(S.top-1)->i;
    if(T->rchild != NULL)      // 右子树不为空,入栈
    {
     T=T->rchild;
     push(S,T);
    }
    else                     //  左右子树都为空
    {
     if(T->lchild == NULL)       //  左子树为空,相应的标记加1,直接寻找右子树
      leaf++;
     pop(S,T);            // 弹出元素
     printf("%-3c",T->data);
     gettop(S,T);       // 得到栈顶元素,并使相应的i加1
    }
   }
  }   // 循环结束
 }
 printf("\n单节点数为:%d\n叶子树为:%d\n",num,leaf);
}

 

再就是定义主函数里面调用了 定义为main_ercs.cpp中

 

#include"t11.h"
#include"ercs.h"
#include"ercs.cpp"

void main()
{
 Bitree S;         //  构建树节点的指针
 Sqstack R;        //  构建栈结构体
 initstack(R);     //  初始化栈
 inittree(S);      //  初始化树
 printf("输入数,回车构建空!\n");
    Createtree(S);     // 先序递归建树
 printf("\n创建成功!\n");
 xianxu(S,R);       //  先序非递归遍历
 protraver(S,R);      // 中序非递归遍历
 lasttraver(S,R);    // 后序非递归遍历
}

总结,不知不觉学习数据结构课程有一段时间了,自己觉得最大的进步就是,编写程序比以前有了很大进步,思想也比较成熟,学习一些算法,所以自己一直没有停下脚步,因为我相信,高手是一个坚持的过程,过程造就了高手。我会继续,不抛弃,不放弃。因为喜欢,所以热爱。我心无悔。。。。。。。留住最真的于2012.04.17-07:40写~~~~~~~~~~~

原创粉丝点击