课程设计 树的应用与实现

任务概述:
(1)采用孩子双亲表示法,创建一棵一般的树,初始化树后添加孩子及其双亲结点,要求从键盘输入树中结点,并且结点数不少于五个;
(2)将树转成对应的二叉树,将结点的第一个孩子作为其左孩子,其余孩子作为其左孩子的右孩子;
(3)实现转换后二叉树的前序、中序、后序的递归遍历算法的实现;
(4)利用栈实现转换后二叉树的前序、中序、后序的非递归遍历算法的实现。
存储结构:
在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>
#define OVERFLOW -2
#define OK 0
#define ERROR 0
#define STACK_INIT_SIZE 100//存储空间初始分配量 
#define STACKINCREMENT 10//存储空间分配增量 
#define MAX_TREE_SIZE 21//树的结点数目最大值 
//>>>>>>>>>>>>>>>>>>>>>>>>>>>自定义数据类型<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
typedef int Status;//函数返回值状态码类型 
typedef char  ElemType;//树中结点元素类型 
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>结构体定义<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 
//孩子结构 
typedef struct CTNode
{
    int child;//孩子结点的下标
    struct CTNode *next;//指向下一个结点的指针
}*ChildPtr;
//表头结构
typedef struct 
{
    ElemType data;//存放在树中的结点的数据
    int parent;//存放双亲的下标
    ChildPtr firstchild;//指向第一个孩子的指针
}CTBox;
//树结构
typedef struct 
{
    CTBox tree[MAX_TREE_SIZE];//结点数组
    int n;//结点数目 
}CTree;
//二叉树结点,左孩子,右孩子 
typedef struct BTNode
{
 ElemType data;
 struct BTNode *lchild,*rchild;
}BTNode,*BTree;
typedef BTree SElemType;
//栈的结构体 
typedef struct{
 SElemType *base;//在栈构造和销毁之后,base的值为NULL 
 SElemType *top;//栈顶指针 
 int stacksize;//当前已分配的存储空间 
}Stack;
//--------------------------------1.采用孩子双亲表示法创建一棵一般的树------------------------------- 
void InitCtree(CTree &T)
{//初始化树 
    int i;
    printf("请输入树的结点个数:");
    scanf("\n%d",&T.n);
    printf("依次输入各个结点:\n"); 
    for(i=0; i<T.n; i++)
    {
      fflush(stdin);//清理标准输入流,把多余的未被保存的数据丢掉 
      T.tree[i].data = getchar();
      T.tree[i].parent = 0;
      T.tree[i].firstchild = NULL; 
    }
}
void AddChild(CTree &T)
{//添加孩子
    int i,j,k;
    printf("-----------------------添加孩子及其双亲结点------------------------------------------\n");           
    for(k=0; k<T.n; k++)
    {
      fflush(stdin); //清理标准输入流,把多余的未被保存的数据丢掉
      printf("请输入孩子结点及其双亲结点的序号:(用空格隔开)\n");
      scanf("%d %d",&i,&j); 
      fflush(stdin);
      CTNode *p = (CTNode *)malloc(sizeof(CTNode));
      p->child = i;
      p->next = NULL;
     T.tree[i].parent = j;//找到双亲 
      if(!T.tree[j].firstchild)
          T.tree[j].firstchild = p;
      else
       {
         CTNode *temp = T.tree[j].firstchild;
         while(temp->next )
          temp = temp->next ;
        temp->next  = p;
       }
    }
}
//---------------------------------------2.将树转换成对应的二叉树------------------------------------------
Status ExchangeTree(BTree &BT,CTree &T)
{
 BTNode *p,*q,*t,*pre;//pre指向p的双亲结点 
 CTNode *temp;
 int m=T.n ;
 if(!(p=(BTNode*)malloc(sizeof(BTNode))))
  exit (OVERFLOW);
 int i=0;
 p->data =T.tree [i].data;
 p->lchild =NULL;
 p->rchild =NULL;
 BT=p;
 for(i=0;i<m;i++)
 {
  if(p->data !=T.tree [i].data)
  {
   if(!p->lchild &&!p->rchild )
   p=pre;//p没有孩子时,p指向双亲结点 
   if(p->lchild )
         {
    if(T.tree [i].data==p->lchild->data  )
    pre=p;
       p=p->lchild ;
    }
    if(p->rchild )
      if(T.tree [i].data==p->rchild ->data)
       pre=p;
    p=p->rchild ;
     }//寻找要转化的根结点 ,让p指向此时要转换的根节点 
  if(T.tree [i].firstchild)
   {
    int k=T.tree [i].firstchild->child;
    q=(BTNode*)malloc(sizeof(BTNode));//为第一个孩子即左孩子分配空间 
    q->data =T.tree [k].data;
    q->lchild =NULL;
    q->rchild =NULL;
    p->lchild =q;//p指向其左孩子 
    temp=T.tree [i].firstchild;
    while(temp->next )//判断是否有兄弟结点 
   {
    t=(BTNode*)malloc(sizeof(BTNode));
    int s=temp->next ->child;
    t->data =T.tree [s].data;
    t->lchild =NULL;
    t->rchild =NULL;
    q->rchild =t;//右孩子为其兄弟结点 
    q=q->rchild ; 
    temp=temp->next ; //后移判断是否还有兄弟结点 
   }
  }
 }
}
//-------------------------------------3.遍历二叉树的递归算法-----------------------------------------------
/*先序遍历的递归算法*/
 void PreOrderTraverse(BTree BT)
 {
  if(BT){
   printf("%c ",BT->data );
   PreOrderTraverse(BT->lchild );
   PreOrderTraverse(BT->rchild );
  }
  }
/*中序遍历的递归算法*/
void InOrderTraverse(BTree BT)
{
 if(BT){
  InOrderTraverse(BT->lchild );
  printf("%c ",BT->data );
  InOrderTraverse(BT->rchild );
 }
 } 
/*后序遍历的递归算法*/
void PostOrderTraverse(BTree BT)
{
 if(BT){
  PostOrderTraverse(BT->lchild );
  PostOrderTraverse(BT->rchild );
  printf("%c ",BT->data );
 }
 }
//----------------------------------------4.遍历的非递归算法--------------------------------------------------
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>栈的相关算法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 Status InitStack(Stack &S){
  //构造一个空栈
  S.base =(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));
  if(!S.base ) exit(OVERFLOW);
  S.top =S.base ;
  S.stacksize = STACK_INIT_SIZE;
  return OK;
 }  
 Status Push(Stack &S,SElemType e)
 {
  //入栈
  if(S.top -S.base >=S.stacksize ){
   //栈满
   S.base =(SElemType*)realloc(S.base ,(S.stacksize+STACKINCREMENT)*sizeof(SElemType));
   if(!S.base ) exit (OVERFLOW);
   S.top =S.base +S.stacksize ;
   S.stacksize += STACKINCREMENT;
  } 
  *S.top++=e;
  return OK;
 } 
 Status Pop(Stack &S,SElemType &e){
  //出栈
  if(S.top ==S.base ) return ERROR; 
  e=*--S.top ;
  return OK;
 }
 Status GetTop(Stack S,SElemType &e)
 {//若栈不空,则用e返回S的栈顶元素,并返回OK,否则返回ERROR
    if(S.top ==S.base ) return ERROR; 
    e=*(S.top -1);
    return OK;
 }
 Status StackEmpty(Stack S){
  return (S.base ==S.top )?true:false;
 }
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>栈的相关算法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>遍历的非递归算法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
/*先序遍历的非递归算法*/ 
 void PreOrder(BTree BT)
 {
  Stack S;
    BTree p=BT;
    InitStack(S);
    while(p||!StackEmpty(S))
 {
      if(p)
     {
        Push(S,p);
        printf("%c ",p->data );
        p=p->lchild ;
     }
     else
  {
          Pop(S,p );
          p=p->rchild ;
     }
   }  
 }
/*中序遍历的非递归算法*/ 
void InOrder(BTree BT)
 {
  Stack S;
    BTree p=BT;
    InitStack(S);
    while(p||!StackEmpty(S))
 {
      if(p)
     {
        Push(S,p );
        p=p->lchild ;
     }
     else
  {
          Pop(S,p );
         printf("%c ",p->data );
          p=p->rchild ;
     }
   }  
 }
/*后序遍历的非递归算法*/ 
/*步骤:
对于树中任意一个访问的节点p可以分情况讨论
1. p如果是叶子节点,直接输出
2. p如果有孩子,且孩子没有被访问过,则按照右孩子,左孩子的顺序依次入栈
3. p如果有孩子,而且孩子都已经访问过,则访问p节点*/
void PostOrder(BTree BT)
 {
  Stack S;
  SElemType e;
    BTree p=BT;
    BTree mark;
    mark=p;
    InitStack(S);
    Push(S,p);
    while(!StackEmpty(S))
 {
  GetTop(S,p);//p等于栈顶指针 
  if( (p->lchild  == NULL && p->rchild  == NULL) || (p->rchild  == NULL && mark == p->lchild ) || (mark == p->rchild ) )
  //入栈时按照右孩子,左孩子顺序入栈,则右孩子被标记,左孩子没有或被标记 
  {
   printf("%c ",p->data );
   mark=p;
   Pop(S,p);
   } 
   else
   {
    if(p->rchild )
    Push(S,p->rchild );
    if(p->lchild )
    Push(S,p->lchild );
   }
 } 
 }
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>遍历的非递归算法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//----------------------------------------------主函数--------------------------------------------------------------
main()
{
 BTree BT;
 CTree T;
 SElemType e;
 printf("--------------------------孩子双亲表示法表示一棵一般的树---------------------------\n");
 InitCtree(T);
 AddChild(T);
 printf("---------------------------------树的创建已完成-------------------------------------\n");
 ExchangeTree(BT,T);
 printf("-------------------------------二叉树的转换已完成-----------------------------------\n");
 printf("------------------------------二叉树的递归遍历算法----------------------------------\n");
 printf("前序遍历:"); 
 PreOrderTraverse(BT);
 printf("\n");
 printf("中序遍历:");
 InOrderTraverse(BT);
 printf("\n");
 printf("后序遍历:");
 PostOrderTraverse(BT);
 printf("\n");
 printf("------------------------------二叉树的非递归遍历算法---------------------------------\n");
 printf("前序遍历:"); 
 PreOrder(BT);
 printf("\n");
 printf("中序遍历:");
 InOrder(BT);
 printf("\n");
 printf("后序遍历:");
 PostOrder(BT);
 printf("\n");
 return 0;
 }

运行结果:
在这里插入图片描述

  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值