二叉树

1.递归进行二叉树的建立、遍历:

//#include<iostream>
//using namespace std;
#include<stdio.h>
#include<stdlib.h>
#define maxsize 100
typedef  char datatype;
typedef struct BNode
{
	datatype data;
	struct BNode *lchild;
	struct BNode *rchild;
}BNode;
int i=0;
void init(BNode *&b)
{
   char ch;
  // printf("请输入:\n"); 
   /* 
   {
   ch=scanf("%c",&ch);
   getchar();
   用C语言scanf进行递归建立二叉树时总是无法跳出循环 ,因为在用scanf输入时ch未接收到赋给它的值 且为防止输入回车应在scanf后加上getcharts();
   }
   */
   ch= getchar();
   //用getchar()输入字符ch可以获取到赋给它的值且回车不会被赋给ch  
  // getchar(); 
  // cin>>ch;  
   printf("ch:%c\n",ch); 
   if(ch=='#')
   		b=NULL;
	else
	{
		b=(BNode *)malloc(sizeof(BNode));
	//	b=new BNode;
		b->data=ch;
		init(b->lchild);
		init(b->rchild);
	}
}
void print_f(BNode *b)  //递归法进行先序遍历 
{
	if(b!=NULL)  
	//注意要进行判断b是否为空,因为二叉树中有节点为NULL,若不进行判断则会直接进行NULL节点的值的输出从而导致错误
	{
	printf("%c",b->data);
	printf("(");
	print_f(b->lchild);
	printf(",");
	print_f(b->rchild);
	printf(")");
	}
}
int main()
{
    BNode *b;
	init(b);
	printf("ok!\n");
	print_f(b);
	return 0;
}

2.非递归进行二叉树的建立与遍历:

后序:

void postorder(BNode *b)
 {
 	BNode *str[maxsize],*p=b;//*str[maxsize]充当顺序栈
	int top=-1;
	do
	{
		while(p!=NULL)
		{
			top++;
			str[top]=p;
			p=p->lchild;
		}
		BNode *r=NULL;
		bool flag=true;  
		while(!(top==-1)&&flag)
		{
			p=str[top];
			if(p->rchild==r)  
			//栈顶元素的右子树指针是刚刚处理过的元素/为NULL => 栈顶结点的右子树已被处理过 
			{
				printf("%c",p->data);
				top--;
				r=p;// 令r指向刚刚处理的元素 
			}
			else
			{
				p=p->rchild; 
				flag=false;  //若栈顶元素的右子树未被处理过则 flag==false 
			}
		}
	 } while(!(top==-1));
 }
#include<stdio.h>
#include<stdlib.h>
#define maxsize 100
typedef  char datatype;
typedef struct BNode
{
	datatype data;
	struct BNode *lchild;
	struct BNode *rchild;
}BNode;
void init(BNode *&b,char *str)   //非递归构建二叉链表 "A(B(D(,G)),C(E,F)"
{
	BNode *p,*st[maxsize];
	b=NULL;
	int j=0,k=0,top=-1;
	char ch=str[j];
	while(ch!='\0')
	{
		printf("ch:%c\n",ch);
		switch (ch)
		{
			case '(':
				{
					k=1;   //用来决定ch后面的字母是左子树还是右子树
					top++;
					st[top]=p;
					break;
				}
			case ')':
				{
					top--;
					break;
				}
			case ',':
				{
					k=2;
					break;
				}
			default:
				{
					p=(BNode *)malloc(sizeof(BNode));
					p->data=ch;
					p->lchild=p->rchild=NULL;
					if(b==NULL)
						b=p;
					else
					{
						if(k==1)
						{
							st[top]->lchild=p;
						}
						else
						{
							st[top]->rchild=p;
						}
					}
				}
		}
		j++;
		ch=str[j];
	}
 } 
 void destory(BNode *&b)
 {
 	if (b!=NULL)
 	{
 		destory(b->lchild);
 		destory(b->rchild);
 		free(b);
	 }
  } 
  void preorder(BNode *b)
  {
  	BNode *str[maxsize],*p;
  	int top=-1;
  	if(b!=NULL)
  	{
  		printf("%c",b->data);
  		top++;
  		str[top]=b;
  		p=b->lchild;
  		while(!(top==-1&p==NULL))
		  //top==-1&p==NULL是遍历完成的条件,缺一个就可能是遍历过程中而不是遍历结束
		  //eg:当遍历完根的左子树开始遍历根的右子树时:此时top==-1,栈为空,但p!=NULL 
  		{
  			while(p!=NULL)
  			{
  				if(top<maxsize)
  				{
					printf("%c",p->data);
					top++;
					str[top]=p;
				  }
  				else
  				{
  					printf("栈满!\n");
				  }
				p=p->lchild;
		  	}
		  	p=str[top];
		  	top--;
		  	{
			  	p=p->rchild;
			}
		}
	  }
  }
  void inorder(BNode *b)
 {
 	BNode *str[maxsize],*p=b;
 	int top=-1;
 	while(!(top==-1&&p==NULL))
 	{
 		while(p!=NULL)
 		{
 			top++;
 			str[top]=p;
 			p=p->lchild;
		 }
		 printf("%c",str[top]->data);
		 p=str[top]->rchild;
		 top--;
	 }
 }
int main()
{
	char *str="A(B(D(,G)),C(E,F)";
    BNode *b;
	init(b,str);
	printf("ok!\n");
//	print_f(b);
	preorder(b);//非递归的先序遍历
	inorder(b); 
	destory(b);
	return 0;
}

3.层次遍历:

void ALLpath(BNode *b)//层次遍历,利用队列进行 
 {
 	BNode *str[maxsize],*p;
 	int front=0,rear=0;
 	if(b!=NULL)
 	{
 		str[rear]=b;
 		rear=(rear+1)%maxsize;
	 }
	 else
	 	return;  
 	while(rear!=front)
 	{
 		p=str[front];
 		printf("%c",p->data);
 		front=(front+1)%maxsize;
 		if(p->lchild!=NULL)
		{
			str[rear]=p->lchild;
 			rear=(rear+1)%maxsize;
		 }
		 if(p->rchild!=NULL)
		{
			str[rear]=p->rchild;
 			rear=(rear+1)%maxsize;
		 }
	 }
  } 

5.插入一个节点(利用递归):

void insert(BNode *&b,char ch,char parent) //将ch插入,作为parent的左子树 
 {
 	BNode *p;
 	if(b->data==parent)
 	{
 		printf("b->data:%c",b->data);
 		if(b->lchild!=NULL)
		 {
		 	p=(BNode *)malloc(sizeof(BNode));
			p->data=ch;
			p->lchild=b->lchild;
			p->rchild=NULL;
			b->lchild=p;
		  }
		  else
		  {
		  	p=(BNode *)malloc(sizeof(BNode));
			p->data=ch;
			p->lchild=NULL;
			p->rchild=NULL;
			b->lchild=p;
		  }
		return;
	 }
	    printf("%d\n",i++);
	    if(b->lchild!=NULL)  
		 //注意要进行判断,必须在 b->lchild!=NULL条件下对b->lchild进行递归插入 
	 		insert(b->lchild,ch,parent); 
	 	if(b->rchild!=NULL)
			insert(b->rchild,ch,parent);
 }
 void preorder(BNode *b) //输出二叉树 
 {
 	if(b->lchild!=NULL||b->rchild!=NULL)
 	{
 		printf("(");
 		if(b->lchild!=NULL)   
 			preorder(b->lchild);
 		if(b->rchild!=NULL)
 		{
 			printf(",");
 			preorder(b->rchild);
		 }
		 printf(")");
	 }
 }
 int main()
{
    BNode *b;
	init(b);
	preorder(b);
	printf("\nOK!\n");
	char K='K',D='C';
	insert(b,K,D);
	preorder(b);
	destory(b);
	return 0;
}

6.查找一个固定值的结点;求树的深度

void find(BNode *b,char ch)   //查找结点
 {
 	if(b->data==ch)
 	{
 		printf("find!!\n");
 		printf("b->data:%c\n",b->data);
	 }
	 else
	 {
	 	if(b->lchild!=NULL)
	 		find(b->lchild,ch);
	 	if(b->rchild!=NULL)
	 		find(b->rchild,ch);
	 }
  } 
  int height(BNode *b)  //求子树的高度,利用递归 
  {
  	int max,l,r;
  	if (b==NULL)
  		return 0;
  	else
  	{
  		l=height(b->lchild);
  		r=height(b->rchild);
  		if(l>r)
  			max=l;
  		else
  			max=r;
  		return max+1;
	  }
   } 
  

7.递归的应用:

  1. 找叶子结点
void Displea(BNode *b)
 {
 	if(b->lchild==NULL&&b->rchild==NULL)
 		printf("%c",b->data);
 	else
 	{
 		if(b->lchild!=NULL)
 			Displea(b->lchild);
 		if(b->rchild!=NULL)
 			Displea(b->rchild);
	 }
 }
  1. 找结点的层次
bool flag=false;
 void level(BNode *b,char ch,int h)
 {
 	if (b->data==ch)
 	{
 		flag=true;
 		printf("结点深度:%d",h);	
	 }
 	else
 	{
 		if(b->lchild!=NULL)
 			level(b->lchild,ch,h+1);
 		if(flag==false&&b->rchild!=NULL)
 			level(b->rchild,ch,h+1);
	 }
 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值