二叉树的相关操作(C语言版)

本文主要介绍二叉树的相关基础操作,参考教材数据结构严慧敏版。

一.前期准备

(1)定义二叉树的存储结构


#include"stdio.h"
#include"stdlib.h"
#include"conio.h"
#include"string.h"
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -1 
#define INFEASIBLE -2 
#define Max_ Tree_SIZE 20
#define StackInitSize 100
#define Maxsize 100
typedef void Status;
typedef char TElemType;
typedef struct BiTNode {
	TElemType data;
	struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
typedef BiTree SElemType;

(2)栈结构的初始化及相关操作

typedef struct Stack{
	SElemType *top;
	SElemType *base;
	int size;
}Stack;

bool EmptyStack(Stack S){
	if(S.base==S.top)
	return true;
	return false;
}
Status Pop(Stack &S,SElemType &e){
	if (EmptyStack(S))return; 
	e=*S.top;
	S.top--;
	
}
Status Push(Stack &S,SElemType e){
	if(S.top-S.base>=99)return;
	S.top++;
	*(S.top)=e;
}
Status GetTop(Stack S,SElemType &e){
	if (EmptyStack(S))return; 
	e=*S.top;
}
Status InitStack(Stack &S){
	S.base=S.top=(SElemType *)malloc(StackInitSize*sizeof(SElemType));
	if(!S.base)
	return;
	S.size=StackInitSize;
}

(3)队列结构的初始化及相关操作


typedef struct{
	SElemType data[Maxsize];
	int front,rear;
}Queue;
bool EmptyQueue(Queue &a){
	if(a.front==a.rear)
	return true;
	return false;
}

void DeQueue(Queue &a,SElemType &b){//不要疑惑这种写法,这种写法没问题 
	a.front++;
	b=a.data[a.front];
} 
void EnQueue(Queue &a,SElemType &b){//EnterQueue
	a.rear++;
	a.data[a.rear]=b;
}
void InitQueue(Queue &a){
	a.front=a.rear=-1;
}

(4)二叉树的函数声明及相关操作

Status InitBiTree(BiTree &BT);
Status CreateBiTree(BiTree *BT);//先序递归创建二叉树 
Status PreOrder(BiTree BT);
Status InOrder(BiTree BT);
Status PostOrder(BiTree BT);
int TreeDepth(BiTree BT);
int TreeWidth(BiTree BT,Queue &Q);//求宽度 
Status NRPreOrder(BiTree BT,Stack &S);
Status NRInOrder(BiTree BT,Stack &S);
Status NRPostOrder(BiTree BT,Stack &S);
Status LevelOrder(BiTree BT,Queue &Q);
int Count0(BiTree BT);
int Count1(BiTree BT);
int Count2(BiTree BT);
int Count_two(BiTree BT,Stack &S);//求双分支结点数目 非递归算法
int Count_two2(BiTree BT,Stack &S);//这是求双分支结点数目 非递归算法 利用中序遍历 
int Count_two3(BiTree BT,Stack &S);//利用后序非递归遍历二叉树 来求双分支结点数目
Status ChangeTree(BiTree BT);
void visit(BiTree a);

void visit(BiTree a){
	printf("%c",a->data);
}
Status InitBiTree(BiTree &BT){
	BT=(BiTNode*)malloc(sizeof(BiTNode));
	BT=NULL;
}

二.相关常用的基础操作

1.构造二叉树

        (1)输入先序序列构造二叉树

             

Status CreateBiTree(BiTree *BT){ //status <=> void
    char c;  
    scanf(" %c", &c); // 注意这里的空格,可以读取空格后的字符  
    if (c == '#'){  
        *BT = NULL;  
    }
	else{  
        *BT=(BiTree)malloc(sizeof(BiTNode));   // 这里应该分配的是BiTNode的大小,我假设BiTNode是一个包含左右子树指针和数据字段的结构体  
        printf("----\n");  
        (*BT)->data = c;  
        CreateBiTree(&((*BT)->lchild));  
        CreateBiTree(&((*BT)->rchild));	  
	}
}

        (2)输入广义表构造二叉树

void CreateTreeByList(BiTree &BT,Stack &S){
	int flag=1;
	char ch;
	BiTree p,e;
	BT=NULL;
	scanf("%c",&ch);
	while(ch!='#'){
		switch(ch){
			case'(':flag=1;Push(S,p);break;//遇到左括号让flag=1表示准备构建当前栈顶结点的左子树 
			case',':flag=0;break;//遇到右括号让flag=0表示准备构建当前栈顶的右子树 
			case')':Pop(S,p);break;
			default:                                //对于A(B,C) 
				p=(BiTree)malloc(sizeof(BiTNode));//第二次是指向一处新的空间(左孩子),原来的A结点仍然在那里,第三次则指向右孩子 
				p->lchild=p->rchild=NULL;
				p->data=ch;
				if(BT==NULL) BT=p;
				else{
					GetTop(S,e);
					if(flag){
						e->lchild=p;
					}
					else{
						e->rchild=p;
					}
				}
		}
		scanf("%c",&ch);
	}
}

2.遍历二叉树(递归版)

(1)先序递归遍历

Status PreOrder(BiTree BT){ // 先序递归遍历 
	if(BT){//BT不为空时执行以下语句 
		visit(BT);
		PreOrder(BT->lchild);
		PreOrder(BT->rchild);
	}
}

(2)中序递归遍历

Status InOrder(BiTree BT){// 中序递归遍历 
	if(BT){//BT不为空时执行以下语句 
		InOrder(BT->lchild);
		visit(BT);
		InOrder(BT->rchild);
	}
}

(3)后序递归遍历

Status PostOrder(BiTree BT){// 后序递归遍历 
	if(BT){//BT不为空时执行以下语句 
		PostOrder(BT->lchild);
		PostOrder(BT->rchild);
		visit(BT);
	}
}

3.遍历二叉树(非递归版)

(1)先序非递归遍历

//先序非递归遍历二叉树
Status NRPreOrder(BiTree BT,Stack &S)
{
	BiTNode *p;
	p=BT;
	while(p|| !EmptyStack(S)){
		if(p){
			printf("%c",p->data);
			Push(S,p);
			p=p->lchild;
		}
		else{
			Pop(S,p);
			p=p->rchild;
		}
	}

}

(2)中序非递归遍历

//中序非递归遍历二叉树
Status NRInOrder(BiTree BT,Stack &S)
{
	BiTNode *p;
	p=BT;
	while(p|| !EmptyStack(S)){
		if(p){
			Push(S,p);
			p=p->lchild;
		}
		else{
			Pop(S,p);
			printf("%c",p->data);
			p=p->rchild;
		}
	}

}

(3)后序非递归遍历

//后序非递归遍历二叉树
Status NRPostOrder(BiTree BT,Stack &S)
{
	BiTNode *p,*r;
	p=BT;
	while(p|| !EmptyStack(S)){
		if(p){
			Push(S,p);
			p=p->lchild;
		}
		else{
			GetTop(S,p);	//读栈顶节点(非出栈) 
			if(p->rchild&&p->rchild!=r){	//若右子树存在,且未被访问过 
				p=p->rchild;	//转向右 	
			}
			else{				//否则弹出结点并访问 
				Pop(S,p);
				printf("%c",p->data); //访问该结点
				r=p;			//记录最近访问的结点 
				p=NULL;			//结点访问完后,重置p指针
			}
		}
	}

}

4.二叉树的层次遍历以及求二叉树宽度和深度

        (1)二叉树的层次遍历

Status LevelOrder(BiTree BT,Queue &Q){//按层次非递归遍历二叉树 
	BiTNode *p;
	p=BT;
	EnQueue(Q,BT);
	while(!EmptyQueue(Q)){ // 队列不为空则进入循环
		DeQueue(Q,p);  // 出队,即将队头结点出队,因为队列先进先出
		visit(p);  // 并访问,即加入到最终遍历序列中
		if(p->lchild!=NULL)  // 如果有左孩子
			EnQueue(Q,p->lchild);  // 就将左孩子入队
		if(p->rchild!=NULL)  // 如果有右孩子
			EnQueue(Q,p->rchild);  // 就将右孩子入队
	}
}

        (2)求二叉树宽度(使用队列)

//求二叉树的宽度
int TreeWidth(BiTree BT,Queue &Q){
	if(BT==NULL) return 0;
	int width,max,i,max_i;
	BiTree p;
	i=1;max_i=i;
	width=1;max=width;
	EnQueue(Q,BT);
	while(!EmptyQueue(Q)){
		DeQueue(Q,p);
		width--;
		if(p -> lchild != NULL) //出队节点的左孩子如果存在则进队
			EnQueue(Q, p -> lchild);
		if(p -> rchild != NULL)
			EnQueue(Q, p -> rchild); //出队节点的右孩子如果存在则进队
		if(width==0){//width == 0,表示当前层次i所有节点已遍历完毕,此时队列元素个数即为下一层次 i + 1 的节点个数
			width = (Q.rear - Q.front + Maxsize) % Maxsize;  //更新宽度
			i++;
			if(width>max){
				max=width;//更新max
				max_i=i;  //并记录最大宽度所在层次
			}
		}
	}
	printf("二叉树第 %d 层的宽度最大\n", max_i);
	return max;
	
} 

        (3)求二叉树深度(跟高度是一样的)(使用递归)

int TreeDepth(BiTree BT){// 求二叉树的深度 
	if(BT==NULL) return 0; 
    else  
    { 
        int m = TreeDepth(BT->lchild ); 
        int n = TreeDepth(BT->rchild); 
        return (m > n) ? (m+1) : (n+1);  
    } 
}

5.求不同类型的结点数目(递归版)

 (1)求叶子结点的数目

int LeafNumber(BiTree BT){// 求叶子结点数目 
	if(BT==NULL){
		return 0;
	}
	else{
		int num1=Count1(BT->lchild);
		int num2=Count1(BT->rchild);
		if((!BT->lchild)&&(!BT->rchild)){
			return num1+num2+1;
		}
		else{
			return num1+num2;
		}
	}
}

(2)求单分支结点的数目

int Count1(BiTree BT){//求单分支结点数目 
	if(BT==NULL){
		return 0;
	}
	else{
		int num1=Count1(BT->lchild);
		int num2=Count1(BT->rchild);
		if((!BT->lchild&&BT->rchild)||(BT->lchild&&!BT->rchild)){
			return num1+num2+1;
		}
		else{
			return num1+num2;
		}
	}
	
}

(3)求双分支结点的数目

int Count2(BiTree BT){//求双分支结点数目 递归算法 
	if(BT==NULL){
		return 0;
	}
	else{
		int num1=Count2(BT->lchild);
		int num2=Count2(BT->rchild);
		if(BT->lchild&&BT->rchild){
			return num1+num2+1;
		}
		else{
			return num1+num2;
		}
	}
}

6.求不同类型的结点数目(非递归版)

就以求双分支结点数目为例

1.利用先序遍历

int Count_two(BiTree BT,Stack &S){//这是求双分支结点数目 非递归算法
	BiTNode *p;                    
	p=BT;
	int num=0;
	while(p|| !EmptyStack(S)){
		if(p){
			if(p->lchild&&p->rchild) num++;
			Push(S,p);
			p=p->lchild;
		}
		else{
			Pop(S,p);
			p=p->rchild;
		}
	}
	return num;

}

2.利用中序遍历

int Count_two(BiTree BT,Stack &S){//这是求双分支结点数目 非递归算法
	BiTNode *p;                    
	p=BT;
	int num=0;
	while(p|| !EmptyStack(S)){
		if(p){
			Push(S,p);
			p=p->lchild;
		}
		else{
			Pop(S,p);
			if(p->lchild&&p->rchild) num++;
			p=p->rchild;
		}
	}
	return num;

}

3.利用后序遍历

//利用后序非递归遍历二叉树 来求双分支结点数目 
int Count_two3(BiTree BT,Stack &S)
{
	BiTNode *p,*r;
	p=BT;
	int num=0;
	while(p|| !EmptyStack(S)){
		if(p){
			Push(S,p);
			p=p->lchild;
		}
		else{
			GetTop(S,p);	//读栈顶节点(非出栈) 
			if(p->rchild&&p->rchild!=r){	//若右子树存在,且未被访问过 
				p=p->rchild;	//转向右 	
			}
			else{				//否则弹出结点并访问 
				Pop(S,p);
				if(p->lchild&&p->rchild) num++;
				r=p;			//记录最近访问的结点 
				p=NULL;			//结点访问完后,重置p指针
			}
		}
	}
	return num;

}

因为求单分支结点和叶子结点的方法与之类似(就是将Push函数上面的或者Pop函数下面的if语句里的判断条件改一改就行了),所以这里就不多说了。

三.不常用的操作

1.交换左右子树(递归)

Status ChangeTree(BiTree BT){// 交换左右子树 
	BiTNode* temp;
	temp=BT->lchild;
	BT->lchild=BT->rchild;
	BT->rchild=temp;
	if(BT->lchild){
		ChangeTree(BT->lchild);
	}
	if(BT->rchild){
		ChangeTree(BT->rchild);
	}
}

2.求二叉树的结点总数

        (1)递归版

int Count_All(BiTree BT){//求所有结点数目 递归算法 
	if(BT==NULL){
		return 0;
	}
	else{
		int num1=Count_All(BT->lchild);
		int num2=Count_All(BT->rchild);
		return num1+num2+1;
	}
}

        (2)非递归版(利用先序遍历)

int Count_All2(BiTree BT,Stack &S){//这是求所有结点数目 非递归算法 利用先序遍历 
	BiTNode *p;                    
	p=BT;
	int num=0;
	while(p|| !EmptyStack(S)){
		if(p){
			num++;
			Push(S,p);
			p=p->lchild;
		}
		else{
			Pop(S,p);
			p=p->rchild;
		}
	}
	return num;

}

四.总结

总体代码应该就这么多了,接下来是完整代码(这里因为使用的是输入先序序列构造二叉树的方法,所以这个代码里没有写输入广义表建树的代码):


#include"stdio.h"
#include"stdlib.h"
#include"conio.h"
#include"string.h"
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -1 
#define INFEASIBLE -2 
#define Max_ Tree_SIZE 20
#define StackInitSize 100
#define Maxsize 100
typedef void Status;
typedef char TElemType;
typedef struct BiTNode {
	TElemType data;
	struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
typedef BiTree SElemType;



typedef struct Stack{
	SElemType *top;
	SElemType *base;
	int size;
}Stack;

bool EmptyStack(Stack S){
	if(S.base==S.top)
	return true;
	return false;
}
Status Pop(Stack &S,SElemType &e){
	if (EmptyStack(S))return; 
	e=*S.top;
	S.top--;
	
}
Status Push(Stack &S,SElemType e){
	if(S.top-S.base>=99)return;
	S.top++;
	*(S.top)=e;
}
Status GetTop(Stack S,SElemType &e){
	if (EmptyStack(S))return; 
	e=*S.top;
}
Status InitStack(Stack &S){
	S.base=S.top=(SElemType *)malloc(StackInitSize*sizeof(SElemType));
	if(!S.base)
	return;
	S.size=StackInitSize;
}

typedef struct{
	SElemType data[Maxsize];
	int front,rear;
}Queue;
bool EmptyQueue(Queue &a){
	if(a.front==a.rear)
	return true;
	return false;
}

void DeQueue(Queue &a,SElemType &b){//不要疑惑这种写法,这种写法没问题 
	a.front++;
	b=a.data[a.front];
} 
void EnQueue(Queue &a,SElemType &b){//EnterQueue
	a.rear++;
	a.data[a.rear]=b;
}
void InitQueue(Queue &a){
	a.front=a.rear=-1;
}




Status InitBiTree(BiTree &BT);
Status CreateBiTree(BiTree *BT);//先序递归创建二叉树 
Status PreOrder(BiTree BT);
Status InOrder(BiTree BT);
Status PostOrder(BiTree BT);
int TreeDepth(BiTree BT);
int TreeWidth(BiTree BT,Queue &Q);//求宽度 
Status NRPreOrder(BiTree BT,Stack &S);
Status NRInOrder(BiTree BT,Stack &S);
Status NRPostOrder(BiTree BT,Stack &S);
Status LevelOrder(BiTree BT,Queue &Q);
int Count0(BiTree BT);
int Count1(BiTree BT);
int Count2(BiTree BT);
int Count_two(BiTree BT,Stack &S);//求双分支结点数目 非递归算法
int Count_two2(BiTree BT,Stack &S);//这是求双分支结点数目 非递归算法 利用中序遍历 
int Count_two3(BiTree BT,Stack &S);//利用后序非递归遍历二叉树 来求双分支结点数目
Status ChangeTree(BiTree BT);
void visit(BiTree a);

void visit(BiTree a){
	printf("%c",a->data);
}
Status InitBiTree(BiTree &BT){
	BT=(BiTNode*)malloc(sizeof(BiTNode));
	BT=NULL;
}
Status CreateBiTree(BiTree *BT){ //status <=> void
    char c;  
    scanf(" %c", &c); // 注意这里的空格,可以读取空格后的字符  
    if (c == '#'){  
        *BT = NULL;  
    }
	else{  
        *BT=(BiTree)malloc(sizeof(BiTNode));   // 这里应该分配的是BiTNode的大小,我假设BiTNode是一个包含左右子树指针和数据字段的结构体  
        printf("----\n");  
        (*BT)->data = c;  
        CreateBiTree(&((*BT)->lchild));  
        CreateBiTree(&((*BT)->rchild));	  
	}
}
Status PreOrder(BiTree BT){ // 先序递归遍历 
	if(BT){//BT不为空时执行以下语句 
		visit(BT);
		PreOrder(BT->lchild);
		PreOrder(BT->rchild);
	}
}
Status InOrder(BiTree BT){// 中序递归遍历 
	if(BT){//BT不为空时执行以下语句 
		InOrder(BT->lchild);
		visit(BT);
		InOrder(BT->rchild);
	}
}
Status PostOrder(BiTree BT){// 后序递归遍历 
	if(BT){//BT不为空时执行以下语句 
		PostOrder(BT->lchild);
		PostOrder(BT->rchild);
		visit(BT);
	}
}
//int LeafNumber(BiTree BT){// 求叶子结点数目 
//	if(BT==NULL){
//		return 0;
//	}
//	else{
//		if((!BT->lchild)&&(!BT->rchild)) {//左右子树均为空说明是叶子结点 
//			return 1;
//		}
//		else{
//			return LeafNumber(BT->lchild)+LeafNumber(BT->rchild);
//		}
//	}
//}

int TreeDepth(BiTree BT){// 求二叉树的深度 
	if(BT==NULL) return 0; 
    else  
    { 
        int m = TreeDepth(BT->lchild ); 
        int n = TreeDepth(BT->rchild); 
        return (m > n) ? (m+1) : (n+1);  
    } 
}
//求二叉树的宽度
int TreeWidth(BiTree BT,Queue &Q){
	if(BT==NULL) return 0;
	int width,max,i,max_i;
	BiTree p;
	i=1;max_i=i;
	width=1;max=width;
	EnQueue(Q,BT);
	while(!EmptyQueue(Q)){
		DeQueue(Q,p);
		width--;
		if(p -> lchild != NULL) //出队节点的左孩子如果存在则进队
			EnQueue(Q, p -> lchild);
		if(p -> rchild != NULL)
			EnQueue(Q, p -> rchild); //出队节点的右孩子如果存在则进队
		if(width==0){//width == 0,表示当前层次i所有节点已遍历完毕,此时队列元素个数即为下一层次 i + 1 的节点个数
			width = (Q.rear - Q.front + Maxsize) % Maxsize;  //更新宽度
			i++;
			if(width>max){
				max=width;//更新max
				max_i=i;  //并记录最大宽度所在层次
			}
		}
	}
	printf("二叉树第 %d 层的宽度最大\n", max_i);
	return max;
	
} 


Status LevelOrder(BiTree BT,Queue &Q){//按层次非递归遍历二叉树 
	BiTNode *p;
	p=BT;
	EnQueue(Q,BT);
	while(!EmptyQueue(Q)){ // 队列不为空则进入循环
		DeQueue(Q,p);  // 出队,即将队头结点出队,因为队列先进先出
		visit(p);  // 并访问,即加入到最终遍历序列中
		if(p->lchild!=NULL)  // 如果有左孩子
			EnQueue(Q,p->lchild);  // 就将左孩子入队
		if(p->rchild!=NULL)  // 如果有右孩子
			EnQueue(Q,p->rchild);  // 就将右孩子入队
	}
}
//!EmptyQueue(Q)
//!EmptyStack(S)

//先序非递归遍历二叉树
Status NRPreOrder(BiTree BT,Stack &S)
{
	BiTNode *p;
	p=BT;
	while(p|| !EmptyStack(S)){
		if(p){
			printf("%c",p->data);
			Push(S,p);
			p=p->lchild;
		}
		else{
			Pop(S,p);
			p=p->rchild;
		}
	}

}

//中序非递归遍历二叉树
Status NRInOrder(BiTree BT,Stack &S)
{
	BiTNode *p;
	p=BT;
	while(p|| !EmptyStack(S)){
		if(p){
			Push(S,p);
			p=p->lchild;
		}
		else{
			Pop(S,p);
			printf("%c",p->data);
			p=p->rchild;
		}
	}

}

//后序非递归遍历二叉树
Status NRPostOrder(BiTree BT,Stack &S)
{
	BiTNode *p,*r;
	p=BT;
	while(p|| !EmptyStack(S)){
		if(p){
			Push(S,p);
			p=p->lchild;
		}
		else{
			GetTop(S,p);	//读栈顶节点(非出栈) 
			if(p->rchild&&p->rchild!=r){	//若右子树存在,且未被访问过 
				p=p->rchild;	//转向右 	
			}
			else{				//否则弹出结点并访问 
				Pop(S,p);
				printf("%c",p->data); //访问该结点
				r=p;			//记录最近访问的结点 
				p=NULL;			//结点访问完后,重置p指针
			}
		}
	}

}

int Count0(BiTree BT){// 求叶子结点数目 
	if(BT==NULL){
		return 0;
	}
	else{
		int num1=Count0(BT->lchild);
		int num2=Count0(BT->rchild);
		if((!BT->lchild)&&(!BT->rchild)){
			return num1+num2+1;
		}
		else{
			return num1+num2;
		}
	}
}
int Count1(BiTree BT){//求单分支结点数目 
	if(BT==NULL){
		return 0;
	}
	else{
		int num1=Count1(BT->lchild);
		int num2=Count1(BT->rchild);
		if((!BT->lchild&&BT->rchild)||(BT->lchild&&!BT->rchild)){
			return num1+num2+1;
		}
		else{
			return num1+num2;
		}
	}
	
}
int Count2(BiTree BT){//求双分支结点数目 递归算法 
	if(BT==NULL){
		return 0;
	}
	else{
		int num1=Count2(BT->lchild);
		int num2=Count2(BT->rchild);
		if(BT->lchild&&BT->rchild){
			return num1+num2+1;
		}
		else{
			return num1+num2;
		}
	}
}


//求单分支结点和叶子结点数目的非递归算法跟这个差不多


int Count_two(BiTree BT,Stack &S){//这是求双分支结点数目 非递归算法
	BiTNode *p;                    
	p=BT;
	int num=0;
	while(p|| !EmptyStack(S)){
		if(p){
			if(p->lchild&&p->rchild) num++;
//			printf("%c",p->data);
			Push(S,p);
			p=p->lchild;
		}
		else{
			Pop(S,p);
			p=p->rchild;
		}
	}
	return num;

}

int Count_two2(BiTree BT,Stack &S){//这是求双分支结点数目 非递归算法 利用中序遍历 
	BiTNode *p;                    
	p=BT;
	int num=0;
	while(p|| !EmptyStack(S)){
		if(p){
			Push(S,p);
			p=p->lchild;
		}
		else{
			Pop(S,p);
			if(p->lchild&&p->rchild) num++;
			p=p->rchild;
		}
	}
	return num;

}

//利用后序非递归遍历二叉树 来求双分支结点数目 
int Count_two3(BiTree BT,Stack &S)
{
	BiTNode *p,*r;
	p=BT;
	int num=0;
	while(p|| !EmptyStack(S)){
		if(p){
			Push(S,p);
			p=p->lchild;
		}
		else{
			GetTop(S,p);	//读栈顶节点(非出栈) 
			if(p->rchild&&p->rchild!=r){	//若右子树存在,且未被访问过 
				p=p->rchild;	//转向右 	
			}
			else{				//否则弹出结点并访问 
				Pop(S,p);
				if(p->lchild&&p->rchild) num++;
				r=p;			//记录最近访问的结点 
				p=NULL;			//结点访问完后,重置p指针
			}
		}
	}
	return num;

}


Status ChangeTree(BiTree BT){// 交换左右子树 
	BiTNode* temp;
	temp=BT->lchild;
	BT->lchild=BT->rchild;
	BT->rchild=temp;
	if(BT->lchild){
		ChangeTree(BT->lchild);
	}
	if(BT->rchild){
		ChangeTree(BT->rchild);
	}
}

int Count_All(BiTree BT){//求所有结点数目 递归算法 
	if(BT==NULL){
		return 0;
	}
	else{
		int num1=Count_All(BT->lchild);
		int num2=Count_All(BT->rchild);
		return num1+num2+1;
	}
}
int Count_All2(BiTree BT,Stack &S){//这是求所有结点数目 非递归算法 利用先序遍历 
	BiTNode *p;                    
	p=BT;
	int num=0;
	while(p|| !EmptyStack(S)){
		if(p){
			num++;
			Push(S,p);
			p=p->lchild;
		}
		else{
			Pop(S,p);
			p=p->rchild;
		}
	}
	return num;

}






int main(){
BiTree BT;
Stack S;
Queue Q;
InitQueue(Q);
InitStack(S);
InitBiTree(BT);
TElemType ch;
int flag=1,select;
printf("To Creat Binary Tree, Please Input PreOrder with '#':");
CreateBiTree(&BT);
//int b=Count_two3(BT,S);
//printf("\n%d",b);
//int a=TreeWidth(BT,Q);
//printf("\n%d",a);
//创建二叉树,返回根结点BT
while (flag){
printf("\nPlease select:\n");
printf("1. PreOrder Traversal\n");
printf("2. InOrder Traversal\n");
printf("3. PostOrder Traversal\n");
printf("4. LevelOrder Traversal\n");
printf("5. NRPreOrder Traversal\n");
printf("6. TreeDepth\n");
printf("7. LeafNumber\n");
printf("8. 求单分支节点数\n");
printf("9. 求双分支节点数\n");
printf("10. 交换左右子树\n");
printf("else. Exit\n");
printf("请输入您的选择:"); 
scanf("%d",&select);
switch (select){
case 1: printf("The PreOrder Traversal of Binary Tree is: \n ");
PreOrder(BT);
break;
//先序递归遍历
case 2: printf("The InOrder Traversal of Binary Tree is:\n ");
InOrder(BT);
break;
//中序递归遍历
case 3: printf("The PostOrder Traversal of Binary Tree is:\n ");
PostOrder(BT);
break;
//后序递归遍历
case 4: printf("The LevelOrder Traversal of Binary Tree is:\n ");
LevelOrder(BT,Q);
break;
//按层次非递归遍历
case 5: printf("The NRPreOrder Traversal of Binary Tree is:\n ");
NRPreOrder(BT,S);
break;
//先序非递归遍历
case 6: printf("The Depth of Binary Tree is:%d\n ",TreeDepth(BT));
break;
//求高度
case 7: printf("The Number of leaf is:%d \n ",Count0(BT));
break;
//求叶结点数
case 8: printf("单分支节点数目为:%d \n ",Count1(BT));
break;
//求单分支节点 
case 9: printf("双分支节点数目为:%d \n ",Count_two(BT,S));
break;
//求双分支节点
case 10:printf("原来树的先序结构为:");
PreOrder(BT);
printf("\n交换后为:");
ChangeTree(BT);
PreOrder(BT);
break;
//交换左右子树 
default:printf("您已成功退出,谢谢您的使用!\n");flag=0;
}
}//while
}//main
//ab##c##
//abd##e##cf##g## 

完整代码总体代码大概就是这样了,如果有什么写的不好的地方请指正,谢谢各位!

  • 12
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
GeoPandas是一个开源的Python库,旨在简化地理空间数据的处理和分析。它结合了Pandas和Shapely的能力,为Python用户提供了一个强大而灵活的工具来处理地理空间数据。以下是关于GeoPandas的详细介绍: 一、GeoPandas的基本概念 1. 定义 GeoPandas是建立在Pandas和Shapely之上的一个Python库,用于处理和分析地理空间数据。 它扩展了Pandas的DataFrame和Series数据结构,允许在其中存储和操作地理空间几何图形。 2. 核心数据结构 GeoDataFrame:GeoPandas的核心数据结构,是Pandas DataFrame的扩展。它包含一个或多个列,其中至少一列是几何列(geometry column),用于存储地理空间几何图形(如点、线、多边形等)。 GeoSeries:GeoPandas中的另一个重要数据结构,类似于Pandas的Series,但用于存储几何图形序列。 二、GeoPandas的功能特性 1. 读取和写入多种地理空间数据格式 GeoPandas支持读取和写入多种常见的地理空间数据格式,包括Shapefile、GeoJSON、PostGIS、KML等。这使得用户可以轻松地从各种数据源中加载地理空间数据,并将处理后的数据保存为所需的格式。 2. 地理空间几何图形的创建、编辑和分析 GeoPandas允许用户创建、编辑和分析地理空间几何图形,包括点、线、多边形等。它提供了丰富的空间操作函数,如缓冲区分析、交集、并集、差集等,使得用户可以方便地进行地理空间数据分析。 3. 数据可视化 GeoPandas内置了数据可视化功能,可以绘制地理空间数据的地图。用户可以使用matplotlib等库来进一步定制地图的样式和布局。 4. 空间连接和空间索引 GeoPandas支持空间连接操作,可以将两个GeoDataFrame按照空间关系(如相交、包含等)进行连接。此外,它还支持空间索引,可以提高地理空间数据查询的效率。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值