判断两序列是否为同一二叉搜索树序列
接下去一行是一个序列,序列长度小于10,包含(0~9)的数字,没有重复数字,根据这个序列可以构造出一颗二叉搜索树。
接下去的n行有n个序列,每个序列格式跟第一个序列一样,请判断这两个序列是否能组成同一颗二叉搜索树。
只有前(后)序和中序都相同才能算同一棵树,
二叉排序树的中序遍历是一样的 都是所有元素的升序排列 所有判等只需校验先序遍历是否相等即可
二叉查找树
二叉查找树(Binary Search Tree),或者是一颗空树,或者是具有下列性质的二叉树:
1、若它的左子树不空,则其左子树上的所有结点的值均小于它根结点的值;
2、若它的右子树不空,则其右子树上的所有结点的值均大于它根结点的值;
3、它的左、右子树也分别为二叉查找树。
二叉查找树是基于二叉树的,其结点数据结构定义为如下:
- static class BinaryNode
- {
- T data;
- BinaryNode left;
- BinaryNode right;
- public BinaryNode(T data) {
- this(data,null,null);
- }
- public BinaryNode( T data, BinaryNode left, BinaryNode right) {
- this.data =data;
- this.left = left;
- this.right =right;
- }
- public BinaryNode()
- {
- data =null;
- this.left = left;
- this.right =right;
- }
- }
查找操作
在二叉查找树中查找x的过程如下:
1、若二叉树是空树,则查找失败。
2、若x等于根结点的数据,则查找成功,否则。
3、若x小于根结点的数据,则递归查找其左子树,否则。
4、递归查找其右子树。
根据上述的步骤,写出其查找操作的代码:
- public boolean contains(T t)
- {
- return contains(t, rootTree);
- }
- public boolean contains(T t, BinaryNode node)
- {
- if(node==null)
- return false;//结点为空,查找失败
- int result = t.compareTo(node.data);
- if(result>0)
- return contains(t,node.right);//递归查询右子树
- else if(result<</SPAN>0)
- return contains(t, node.left);//递归查询左子树
- else
- return true;
- }
插入操作
二叉树查找树b插入操作x的过程如下:
1、若b是空树,则直接将插入的结点作为根结点插入。
2、x等于b的根结点的数据的值,则直接返回,否则。
3、若x小于b的根结点的数据的值,则将x要插入的结点的位置改变为b的左子树,否则。
4、将x要出入的结点的位置改变为b的右子树。
代码实现如下:
- public void insert(T t)
- {
- rootTree = insert(t, rootTree);
- }
- public BinaryNode insert(T t,BinaryNode node)
- {
- if(node==null)
- {
- //新构造一个二叉查找树
- return new BinaryNode(t, null, null);
- }
- int result = t.compareTo(node.data);
- if(result<</SPAN>0)
- node.left= insert(t,node.left);
- else if(result>0)
- node.right= insert(t,node.right);
- else
- ;//doNothing
- return node;
- }
删除操作
对于二叉查找树的删除操作(这里根据值删除,而非结点)分三种情况:
不过在此之前,我们应该确保根据给定的值找到了要删除的结点,如若没找到该结点
不会执行删除操作!
下面三种情况假设已经找到了要删除的结点。
1、如果结点为叶子结点(没有左、右子树),此时删除该结点不会玻化树的结构
直接删除即可,并修改其父结点指向它的引用为null.如下图:
2、如果其结点只包含左子树,或者右子树的话,此时直接删除该结点,并将其左子树
或者右子树设置为其父结点的左子树或者右子树即可,此操作不会破坏树结构。
3、 当结点的左右子树都不空的时候,一般的删除策略是用其右子树的最小数据
(容易找到)代替要删除的结点数据并递归删除该结点(此时为null),因为
右子树的最小结点不可能有左孩子,所以第二次删除较为容易。
z的左子树和右子树均不空。找到z的后继y,因为y一定没有左子树,所以可以删除y,
并让y的父亲节点成为y的右子树的父亲节点,并用y的值代替z的值.如图:
删除操作源码:
- public void remove(T t)
- {
- rootTree = remove(t,rootTree);
- }
- public BinaryNode remove(T t,BinaryNode node)
- {
- if(node == null)
- return node;//没有找到,doNothing
- int result = t.compareTo(node.data);
- if(result>0)
- node.right = remove(t,node.right);
- else if(result<</SPAN>0)
- node.left = remove(t,node.left);
- else if(node.left!=null&&node.right!=null)
- {
- node.data = findMin(node.right).data;
- node.right = remove(node.data,node.right);
- }
- else
- node = (node.left!=null)?node.left:node.right;
- return node;
- }
- //先序遍历
- public void preTraverse(TreeNode root)
- {
- if(root!=null)
- {
- System.out.print(root.getData()+" ");
- preTraverse(root.getLchild());
- preTraverse(root.getRchild());
- }
- }
- //中序遍历
- public void midTraverse(TreeNode root)
- {
- if(root!=null)
- {
- midTraverse(root.getLchild());
- System.out.print(root.getData()+" ");
- midTraverse(root.getRchild());
- }
- }
- //后序遍历
- public void postTraverse(TreeNode root)
- {
- if(root!=null)
- {
- postTraverse(root.getLchild());
- postTraverse(root.getRchild());
- System.out.print(root.getData()+" ");
- }
- }
- //层次遍历
- public void levelTraverse(TreeNode root)
- {
- System.out.print(root.getData()+" ");
- queue.enQueue(root);
- int level=1;
- while(!queue.isEmpty())
- {
- List<TreeNode> list=new ArrayList<TreeNode>();
- while(!queue.isEmpty())
- {
- list.add(queue.deQueue());
- }
- boolean tag=false;
- for(int i=0;i<list.size();i++)
- {
- if(list.get(i).getLchild()!=null)
- {
- System.out.print(list.get(i).getLchild().getData()+" ");
- queue.enQueue(list.get(i).getLchild());
- tag=true;
- }
- if(list.get(i).getRchild()!=null)
- {
- System.out.print(list.get(i).getRchild().getData()+" ");
- queue.enQueue(list.get(i).getRchild());
- tag=true;
- }
- }
- if(tag)
- {
- level++;
- }
- }
- System.out.println("二叉树共"+level+"层");
- }
此题正确代码如下:
import java.util.Scanner; public class BinarySearch { /** * @param args */ public static void main(String[] args) { Scanner sin=new Scanner(System.in); int n=Integer.parseInt(sin.nextLine()); String s=sin.nextLine(); TreeNode t=buildTree(s); String a=preVisit(t); int count=0; while(count<n){ String ss=sin.nextLine(); count++; TreeNode t2=buildTree(ss); //这个地方一定记得用t2把返回值接住,否则值没有返回,后面会有空指针异常 String b=preVisit(t2); //System.out.println(b); if(a.equals(b)) System.out.println("YES"); else System.out.println("NO"); } } private static String preVisit(TreeNode t) { StringBuilder sb=new StringBuilder(); if(t==null) return null; else{ sb.append(t.data); sb.append(preVisit(t.left)); //和前面一样,一定要把结果加入sb,利用sb.append,否则直接写preVisit(t.left)的话, //结果没有加入sb,只有根节点加入sb了,不对! sb.append(preVisit(t.right)); } return sb.toString(); } private static TreeNode buildTree(String s) { TreeNode t=null; for(int i=0;i<s.length();i++){ t=insert(t,s.charAt(i)-'0'); } return t; } public static TreeNode insert(TreeNode t,int data){ if(t==null) return new TreeNode(data); if(data<t.data) t.left=insert(t.left, data); else if(data>t.data) t.right=insert(t.right,data); else ; return t; } } class TreeNode{ int data; TreeNode left; TreeNode right; public TreeNode(int data){ this.data=data; } }