作为引入,这边将一个题目作为引入,然后这个问题将会涉及二叉搜索树的大部分内容。
本文将全部知识点贯穿其中,用以讲解二叉搜索树的一些内容。
题目如下
一棵二叉搜索树可被递归地定义为具有下列性质的二叉树:对于任一结点,
- 其左子树中所有结点的键值小于该结点的键值;
- 其右子树中所有结点的键值大于等于该结点的键值;
- 其左右子树都是二叉搜索树。
所谓二叉搜索树的“镜像”,即将所有结点的左右子树对换位置后所得到的树。
给定一个整数键值序列,现请你编写程序,判断这是否是对一棵二叉搜索树或其镜像进行前序遍历的结果。
输入格式:
输入的第一行给出正整数 N(≤1000)。随后一行给出 N 个整数键值,其间以空格分隔。
输出格式:
如果输入序列是对一棵二叉搜索树或其镜像进行前序遍历的结果,则首先在一行中输出 YES
,然后在下一行输出该树后序遍历的结果。数字间有 1 个空格,一行的首尾不得有多余空格。若答案是否,则输出 NO
。
输入样例 1:
7
8 6 5 7 10 8 11
输出样例 1:
YES
5 7 6 8 11 10 8
输入样例 2:
7
8 10 11 8 6 7 5
输出样例 2:
YES
11 8 10 7 5 6 8
输入样例 3:
7
8 6 8 5 10 9 11
输出样例 3:
NO
如下,题目的意思很清楚,无非就是输入一个数组,然后判断他是不是二叉搜索树,如果是的话,那么就进行后缀输出。
大伙看到这里可以相应的停下来一下,相应的想想,如果是你的话,你会怎么做这样的一个题目。
那么我就先把代码丢上来,然后解题思路放在后面。
import java.io.*;
import java.util.*;
/*
* 忆林
* Data: 2022年3月13日22:24:18
*
*/
public class Mainx03 {
static class FastScanner
{// 用于快速读入大量数据
BufferedReader br;
StringTokenizer st;
public FastScanner(InputStream in)
{
br = new BufferedReader(new InputStreamReader(in), 16384);
eat("");
}
public void eat(String s)
{
st = new StringTokenizer(s);
}
public String nextLine()
{
try
{
return br.readLine();
} catch (IOException e)
{
return null;
}
}
public boolean hasNext()
{
while (!st.hasMoreTokens())
{
String s = nextLine();
if (s == null)
return false;
eat(s);
}
return true;
}
public String next()
{
hasNext();
return st.nextToken();
}
public int nextInt()
{
return Integer.parseInt(next());
}
}
static FastScanner in = new FastScanner(System.in);// 快读
static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));// 快速输出
public static void main(String[] args) {
// TODO 自动生成的方法存根
while(in.hasNext()) {
int number = in.nextInt();
int[] arr = new int[number];
/*
* 数据初始化
* 大于后面加上-1
* 对于要对比的数据还要进行一个处理
*
*/
String duibi = "";
for(int i=0;i<number;i++) {
arr[i] = in.nextInt();
duibi+=arr[i]+" ";
}
Data tem = new Data(arr);tem.diao();
// &&tem.qianxudui()
if(tem.qianxu().equals(duibi)) {
String temm = tem.houxu();
System.out.println("YES");
System.out.println(temm.substring(0, temm.length()-1));
}else {
tem = new Data(arr);tem.diao2();
//对于覆盖性的函数多次调用的话,需要在方法内赋初值
String teee = tem.qianxu();
// &&tem.houxudui()
if(teee.equals(duibi)) {
String temm = tem.houxu();
System.out.println("YES");
System.out.println(temm.substring(0, temm.length()-1));
}else {
System.out.println("NO");
}
}
}
}
}
/*
* 建立一个类用来进行一个实现二叉树的创建
*
*/
class Da{
int data;
Da left;
Da right;
public Da(int da) {
this.data = da;
this.left = null;
this.right = null;
}
}
class Data{
int[] arr;
String qianxu;
String houxu;
// String qianxu2;
// String qianxu21;
// String qianxu22;
Da root;
int i;
boolean qiandui = true;
boolean houdui = true;
boolean dui = false;
public Data(int[] arr) {
this.arr = arr;
qianxu ="";
houxu = "";
}
public void diao() {
i=0;
root = bstFromPreorder(arr);
}
public void diao2() {
i=0;
root = bstFromPreorder2(arr);
}
public Da bstFromPreorder(int[] preorder) {
Da root = null;
for (int i = 0; i < preorder.length; i++){
root = helper(root, preorder[i]);
}
return root;
}
private Da helper(Da root, int val){
if (root == null){
return new Da(val);
}
if (root.data > val){
root.left = helper(root.left, val);
}else{
root.right = helper(root.right, val);
}
return root;
}
public Da bstFromPreorder2(int[] preorder) {
Da root = null;
for (int i = 0; i < preorder.length; i++){
root = helper2(root, preorder[i]);
}
return root;
}
private Da helper2(Da root, int val){
if (root == null){
return new Da(val);
}
if (root.data <= val){
root.left = helper2(root.left, val);
}else{
root.right = helper2(root.right, val);
}
return root;
}
/*
* 错误的
*/
public Da establish() {
Da p = null;
if(i<arr.length) {
int elem = arr[i++];
if(elem!=-112345) {
p = new Da(elem);
p.left = establish();
if(dui) {
dui = false;
return p;
}
p.right = establish();
}else {
dui = true;
}
}
return p;
}
public String qianxu() {
qianxu = "";
qianxu(root);
return qianxu;
}
public void qianxu(Da p) {
if(p!=null) {
qianxu+=p.data+" ";
qianxu(p.left);
qianxu(p.right);
}
}
public boolean qianxudui() {
qianxudui(root,0);
return qiandui;
}
public void qianxudui(Da p,int max) {
if(p!=null) {
qianxudui(p.left,max);
if(max<=p.data) {
max = p.data;
}else {
qiandui = false;
return;
}
qianxudui(p.right,max);
}
}
public boolean houxudui() {
houxudui(root,0);
return houdui;
}
public void houxudui(Da p,int max) {
if(p!=null) {
houxudui(p.right,max);
if(max<=p.data) {
max = p.data;
}else {
houdui = false;
return;
}
houxudui(p.left,max);
}
}
public String houxu() {
houxu(root);
return houxu;
}
public void houxu(Da p) {
if(p!=null) {
houxu(p.left);
houxu(p.right);
houxu+=p.data+" ";
}
}
}
这边考虑到大伙的英语水平,然后我这边的很多命名都是偏中文,但是,这只是为了让大伙,更方便的看代码,实际上不建议这样奥。
然后对于一个快速输入输出,这样对于比赛的时候也会快很多。经过题主的测试,这个快速输入输出的话,至少是可以快一半的呢。
然后接下来就是相应的解题思路了。
首先无非是接受相应的数据,然后对数据进行一个处理,处理这一方面的话,我是将输入的数据进行一个按照二叉搜索树的形式构建的二叉树,又因为题目给的是这个前缀,所以我只需要将这个与我建树的前缀进行一个匹配,若匹配成功的话,说明这个是符合条件的,其次,输出它的后缀就好了。然后镜像的话,只是他的构建二叉树的条件进行一个改变就可以了,其他的话都没有什么很主要的了。
然后对于这个二叉树的性质,除了上面代码里面的,我还想补充一点:
就是我标准二叉搜索树按照中序遍历以后你会发现它的值是有一定规律的。
最后,希望。
每一个整装待发的开始,都能在匆匆岁月中为时不晚!!!