数据结构之树和二叉树

第六章   树和二叉树

一  树

定义

树是由根结点和若干颗子树构成的。树是由一个集合以及在该集合上定义的一种关系构成的。集合中的元素称为树的结点,所定义的关系称为父子关系。父子关系在树的结点之间建立了一个层次结构。在这种层次结构中有一个结点具有特殊的地位,这个结点称为该树的根结点,或称为树根。

单个结点是一棵树,树根就是该结点本身。

二  二叉树

定义

二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。

三  实践

编写下面的函数

a.建立一棵二叉树

b.实现二叉树的三种递归的遍历

c.实现二叉树的先根,中根非递归遍历

d.求二叉树叶子结点的个数

e.求二叉树的深度

f.按层遍历二叉树

#define STACKSIZE 100
#define JIA_STACKSIZE 10
#define size 20

typedef int Status;

typedef struct treenode  //定义二叉树
{
   char data;
   struct treenode *lchild,*rchild;
}treenode,*treelink;
typedef treelink SElemtype;
typedef struct stack  //定义栈
{
	  SElemtype *top,*base;
	  int stacksize;
}SStack;
typedef struct     //定义队(循环队列)
{
   int front; 
   int rear;  
   SElemtype elem[size];
}SqQueue;

int main()
{
	treelink t=NULL;
	printf("请输入二叉树:");
	creatree(t);                            
	printf("请输出二叉树(前序遍历(递归)):");
	preorde(t);
	printf("\n请输出二叉树(中序遍历(递归)):");
	zhpreorde(t);
	printf("\n请输出二叉树(后序遍历(递归)):");
	hopreorde(t);
	printf("\n请输出二叉树(前序遍历(非递归)):");
	nopreorde(t);
	printf("\n请输出二叉树(中序遍历(非递归)):");
	nozhpreorde(t);
	printf("\n请输出二叉树(按层遍历二叉树):");
	cepreorde(t);
	printf("\n请输出二叉树叶子结点的个数:%d",leafcount(t));
	printf("\n请输出二叉树的深度:%d",depth(t));
	return 0;
}

//初始化栈
Status InitStack(SStack &S)
{
    S.base=(SElemtype *)malloc(STACKSIZE*sizeof(SElemtype)); 
    if(!S.base)  return 0;       
    S.top=S.base;
    S.stacksize=STACKSIZE;
    return 1;
}
  //进栈(插入)
Status Push(SStack &S,SElemtype e)
{
  if(S.top-S.base>=S.stacksize) 
  {
	S.base=(SElemtype*)realloc(S.base,(S.stacksize+JIA_STACKSIZE)*sizeof(SElemtype));
	if(!S.base)   return 0;   
	S.top=S.base+S.stacksize;
	S.stacksize+=JIA_STACKSIZE;
  }
  *S.top=e;               
  S.top++;
  return 1;
}
 //取栈顶元素
Status Getop(SStack S,SElemtype &e)
{
     if(S.top==S.base)  return 0;
     e=*(S.top-1);       
     return 1;
}
//出栈(删除)
Status Pop(SStack &S, SElemtype &e)
{
     if(S.top==S.base)  return 0; 
     S.top--;
     e=*S.top;
     return 1;
}
Status initQueue(SqQueue &Q)    //初始化循环队列
{
	Q.front=Q.rear=0;
	return 1;
}
Status enQueue(SqQueue &Q,SElemtype e)    //进队
{
	 if((Q.rear+1)%size==Q.front)
	     return 0;
	 Q.elem[Q.rear]=e;
	 Q.rear=(Q.rear+1)%size;
	 return 1;
}
Status deQueue(SqQueue &Q,SElemtype &e)  //出队
{
	 if(Q.front==Q.rear)
		return 0;
	 e=Q.elem[Q.front];
	 Q.front=(Q.front+1)%size;
	 return 1;
}
int creatree(treelink &T)//生成二叉树
{
	  char ch;
	  ch=getchar();
	  if(ch=='#')
	     T=NULL;
	  else
	  {
	     T=(treelink)malloc(sizeof(treenode));
	     if(!T)   return 0;        
	     T->data=ch;               
             creatree(T->lchild);      //构造左子树
             creatree(T->rchild);      //构造右子数

	  }
	  return 1;
}
void visit(treelink P)//查看
{
   printf("%c ",P->data);  
}
void preorde(treelink S)//前序遍历(递归)
{
   if(S)
   {
         visit(S);           
	 preorde(S->lchild);
	 preorde(S->rchild);
   }
}
Status nopreorde(treelink S)//前序遍历(非递归)
{
      SStack T;       
      treelink p;
      InitStack(T);     
      p=S;
      while(p||!(T.top==T.base))   
      {
	      if(p)
	      {
	           visit(p);   
		   Push(T,p);   
		   p=p->lchild; 
	      }
	      else
	      {
	          Pop(T,p);      
	          p=p->rchild;  
	      }
      }
      return 1;
}
void zhpreorde(treelink S)//中序遍历(递归)
{
   if(S)
   {
	   zhpreorde(S->lchild);
	   visit(S);              
	   zhpreorde(S->rchild);
   }
}
Status nozhpreorde(treelink S)//中序遍历(非递归)
{
	SStack T;     
	treelink p;
	InitStack(T);    
	p=S;            
	while(p||!(T.top==T.base))   
	{
	   if(p)
	   {
		   Push(T,p);       
		   p=p->lchild;     
	   }
	   else
	   {
	        Pop(T,p);     
	        visit(p);     
	        p=p->rchild;  
	   }
	}
   return 1;
}
void hopreorde(treelink S)//后序遍历(递归)
{
   if(S)
   {

	   hopreorde(S->lchild);
	   hopreorde(S->rchild);
	   visit(S);             
   }
}
Status leafcount(treelink T)//求叶子结点的个数
{
    SStack S;  
    treelink p;
    InitStack(S);  
    p=T;        
    int count=0;
    while(p||!(S.top==S.base))
    {
	   if(p)
	   {
		   if(p->lchild==NULL&&p->rchild==NULL)//左右孩子都为空
			count++;  //计数+1
		   Push(S,p);     //进栈
		   p=p->lchild;   //遍历左子树
	   }
	   else
	   {
	          Pop(S,p);        //出栈
		  p=p->rchild;     //遍历右子树
	   }
} return count; } Status depth(treelink T)//二叉树的深度 { int m,n; if(T==NULL) return 0; else { m=depth(T->lchild); //递归左子树 n=depth(T->rchild); //递归右子树 return m>=n?m+1:n+1; //输出m和n中最大的+1 } } void cepreorde(treelink T)//按层遍历二叉树 { SqQueue S;//定义队 treelink p; initQueue(S);//初始化队 p=T; if(p) enQueue(S,p);//进队 while(!(S.front==S.rear)) //队不空 { deQueue(S,p); visit(p); if(p->lchild) { enQueue(S,p->lchild);//进队 } if(p->rchild) { enQueue(S,p->rchild);//进队 } } }

  

转载于:https://www.cnblogs.com/huan0919/p/8427107.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值