(十)王道机试指南___二叉排序树

算例一

  • 题目描述

  • 解题思路

①二叉排序树:对于树上任意一个结点,其上的数值必大于等于其左子树上任意结点数值,必小于等于其右子树上任意结点的数值

②所有的二叉排序树都有一个共同的特点: 若对二叉排序树进行中序遍历,那么其遍历结果必然是一个递增序列

③对二叉排序树插入数字x:若当前树为空,则x 为其根结点;若当前结点大于x,则x 插入其左子树;若当前结点小于x,则x 插入其右子树; 若当前结点等于x,则根据具体情况选择插入左右子树或者直接忽略

  • 解题代码

#include <stdio.h>
#include <string.h>
struct Node { //二叉树结构体
	Node *lchild; //左儿子指针
	Node *rchild; //右儿子指针
	int c; //保存数字
}Tree[110]; //静态数组
int loc; //静态数组中被使用元素个数
Node *creat() { //申请未使用的结点
	Tree[loc].lchild = Tree[loc].rchild = NULL;
	return &Tree[loc++];
}
void postOrder(Node * T) { //后序遍历
	if (T->lchild != NULL) {
		postOrder(T->lchild);
	}
	if (T->rchild != NULL) {
		postOrder(T->rchild);
	}
	printf("%d ", T->c);
}
void inOrder(Node * T) { //中序遍历
	if (T->lchild != NULL) {
		inOrder(T->lchild);
	}
	printf("%d ", T->c);
	if (T->rchild != NULL) {
		inOrder(T->rchild);
	}
}
void preOrder(Node * T) { //前序遍历
	printf("%d ", T->c);
	if (T->lchild != NULL) {
		preOrder(T->lchild);
	}
	if (T->rchild != NULL) {
		preOrder(T->rchild);
	}
}
Node *Insert(Node * T, int x) { //插入数字
	if (T == NULL) { //若当前树为空
		T = creat(); //建立结点
		T->c = x; //数字直接插入其根结点
		return T; //返回根结点指针
	}
	else if (x < T->c) //若x小于根结点数值
		T->lchild = Insert(T->lchild, x); //插入到左子树上
	else if (x > T->c) //若x大于根结点数值
		T->rchild = Insert(T->rchild, x); //插入到右子树上.若根结点数值与x一样, 根据题目要求直接忽略
		return T; //返回根节点指针
}
int main() {
	int n;
	while (scanf("%d", &n) != EOF) {
		loc = 0;
		Node * T = NULL; //二叉排序树树根结点为空
		for (int i = 0; i < n;i++) { //依次输入n个数字
			int x;
			scanf("%d", &x);
			T = Insert(T, x); //插入到排序树中
		}
		preOrder(T); //前序遍历
		printf("\n"); //输出空行
		inOrder(T); //中序遍历
		printf("\n");
		postOrder(T); //后序遍历
		printf("\n");
	}
	return 0;
}
  • 注意点

①对于二叉树的基本操作:建立结构体,建立空树creat,三种顺序遍历二叉树一定给我记准了!!

②看到输入了一串数字,本能的反应就是装数组里,但是这样后期就会牵扯到数组,数组Idx,传来传去很麻烦,还会搞错。在这里最简单的就是接收一个数字立马加入二叉树

 

 

算例二

  • 题目描述

  • 解题思路

①包括中序遍历在内的两种遍历结果可以唯一确定一棵二叉树

②二叉排序树=二叉搜索树=二叉查找树

  • 解题代码

#include <stdio.h>
#include <string.h>
struct Node { //树节点结构体
	Node *lchild;
	Node *rchild;
	int c;
}Tree[110];
int loc;
Node *creat() { //申请结点空间
	Tree[loc].lchild = Tree[loc].rchild = NULL;
	return &Tree[loc++];
}
char str1[25], str2[25]; //保存二叉排序树的遍历结果,将每一棵树的前序遍历得到的字符串与中序遍历得到的字符串连接, 得到遍历结果字符串
int size1, size2; //保存在字符数组中的遍历得到字符个数
char * str; //当前正在保存字符串
int *size; //当前正在保存字符串中字符个数
void postOrder(Node * T) { //前序遍历
	str[(*size)++] = T->c + '0'; //将结点中的字符放入正在保存的字符串中
	if (T->lchild != NULL) {
		postOrder(T->lchild);
	}
	if (T->rchild != NULL) {
		postOrder(T->rchild);
	}
}
void inOrder(Node * T) { //中序遍历
	if (T->lchild != NULL) {
		inOrder(T->lchild);
	}
	str[(*size)++] = T->c + '0';
	if (T->rchild != NULL) {
		inOrder(T->rchild);
	}
}
Node *Insert(Node * T, int x) { //将数字插入二叉树
	if (T == NULL) {
		T = creat();
		T->c = x;
		return T;
	}
	else if (x < T->c)
		T->lchild = Insert(T->lchild, x);
	else if (x > T->c)
		T->rchild = Insert(T->rchild, x);
	return T;
}
int main() {
	int n;
	char tmp[12];
	while (scanf("%d", &n) != EOF && n != 0) {
		loc = 0; //初始化静态空间为未使用
		Node * T = NULL;
		scanf("%s", tmp); //输入字符串
		for (int i = 0;tmp[i] != 0; i++) {
			T = Insert(T, tmp[i] - '0'); //按顺序将数字插入二叉排序树
		}
		size1 = 0; //保存在第一个字符串中的字符初始化为0
		str = str1; //将正在保存字符串设定为第一个字符串
		size = &size1; //将正在保存字符串中的字符个数指针指向size1
		postOrder(T); //前序遍历
		inOrder(T); //中序遍历
		str1[size1] = 0; //向第一个字符串的最后一个字符后添加空字符,方便使用字符串函数
			while (n-- != 0) { //输入n个其它字符串
				scanf("%s", tmp); //输入
				Node * T2 = NULL;
				for (int i = 0;tmp[i] != 0; i++) { //建立二叉排序树
					T2 = Insert(T2, tmp[i] - '0');
				}
				size2 = 0; //第二个字符串保存字符初始化为0
				str = str2; //将正在保存字符串设定为第二个字符串
				size = &size2; //正在保存字符串中字符数量指针指向size2
				postOrder(T2); //前序遍历
				inOrder(T2); //中序遍历
				str2[size2] = 0; //字符串最后添加空字符
				puts(strcmp(str1, str2) == 0 ? "YES" : "NO"); //比较两个遍历字符串, 若相同则输出YES, 否则输出NO
			}
	}
	return 0;
}

 

  • 注意点

①这里采用一个比较巧妙的思想:把被比较的二叉树的前序、中序输入到一个字符数组str1里;把比较的二叉树的前序、中序输入到字符数组str2里,随后直接strcmp比较两个字符数组是否相等就行,简洁明了

②承接上一思路,由于不同的二叉树需要使用相同的前序、中序遍历代码,所以如何把结果传入相应的结果数组里就比较难搞,emmm我试了下结果字符指针参数什么的把我搞晕了,优秀代码里使用全局变量以及全局指针:每次遍历前,把相应的变量地址赋给相应的指针,就可以实现一个代码套用所有!

③int+‘0’=char      ||         char-'0' =int

④便利之举:方便字符数组进行比较,结束的时候加个 str[i]=0;

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值