目录
7.输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表
1.检验两棵树是否是相同的树
public boolean isSameTree(TreeNode p,TreeNode q){
if((p == null && q != null) || (p != null && q == null)){
return false;
}
if(p == null && q == null){
return true;
}
if(p.val != q.val){
return false;
}
return isSameTree(p.left,q.left) && isSameTree(p.right,q.right);
}
2.判断一棵树是否是另一棵树的子树
public boolean isSameTree(TreeNode p, TreeNode q) {
if ((p == null && q != null) || (p != null && q == null)) {
return false;
}
if (p == null && q == null) {
return true;
}
if (p.val != q.val) {
return false;
}
return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
}
public boolean isSubTree(TreeNode root, TreeNode subRoot) {
if (root == null || subRoot == null) {
return false;
}
if (isSameTree(root, subRoot)) {
return true;
}
if (isSameTree(root.left, subRoot)) {
return true;
}
if (isSameTree(root.right, subRoot)) {
return true;
}
return false;
}
3.判断一棵树是否是平衡二叉树.
public int height(TreeNode root){
if(root == null){
return 0;
}
int leftHeight = height(root.left);
int rightHeight = height(root.right);
if(leftHeight >=0 && rightHeight >=0 && Math.abs(leftHeight-rightHeight) <= 1){
return Math.max(leftHeight,rightHeight)+1;
}else{
return -1;
}
}
public boolean isBalanced(TreeNode root){
if(root == null){
return true;
}
return height(root) > 0;
}
4.对称二叉树
public boolean isSymmetricChild(TreeNode leftTree,TreeNode rightTree){
if((leftTree == null && rightTree != null)||(leftTree != null && rightTree == null)){
return false;
}
//空节点也是对称
if(leftTree == null && rightTree == null){
return true;
}
if(leftTree.val != rightTree.val){
return false;
}
return isSymmetricChild(leftTree.left,rightTree.right) && isSymmetricChild(leftTree.right,rightTree.left);
}
//对称二叉树
public boolean isSymmetric(TreeNode root){
if(root == null){
return true;
}
return isSymmetricChild(root.left,root.right);
}
5.1层序遍历
public void levelOrder1(TreeNode root){
Queue<TreeNode> queue = new LinkedList<>();
if(root == null){
return;
}
queue.offer(root);
while (! queue.isEmpty()){
TreeNode cur = queue.poll();
System.out.println(cur.val+" ");
if(cur.left != null){
queue.offer(cur.left);
}
if(cur.right != null){
queue.offer(cur.right);
}
}
}
5.2层序遍历返回每一层的节点
public List<List<Integer>> levelOrder2(TreeNode root){
List<List<Integer>> ret = new ArrayList<>();
Queue<TreeNode> queue = new LinkedList<>();
if(root == null){
return ret;
}
queue.offer(root);
while (! queue.isEmpty()){
int size = queue.size();
List<Integer> list = new ArrayList<>();
while (size != 0){
TreeNode cur = queue.poll();
list.add(cur.val);
if(cur.left != null){
queue.offer(cur.left);
}
if(cur.right != null){
queue.offer(cur.right);
}
size--;
}
ret.add(list);、//每层的节点走完之后放在list中
}
return ret;
}
6.1二叉树的最近公共祖先
方法一:
//找公共祖先方法1之将其看成二叉搜索树
public TreeNode lowestCommonAncestor1(TreeNode root,TreeNode p,TreeNode q){
if(root == null){
return null;
}
if(root == p || root == q){
return root;
}
TreeNode leftT = lowestCommonAncestor1(root.left,p,q);
TreeNode rightT = lowestCommonAncestor1(root.right,p,q);
if(leftT != null && rightT != null){
return root;
}else if(leftT != null){
return leftT;
}else {
return rightT;
}
}
6.2求最近公共祖先方法2求链表的交点:
//root: 根节点 node:指定的节点 stack:存放从根节点到指定节点的路径
public boolean getPath(TreeNode root,TreeNode node,Stack<TreeNode> stack){
if(root == null || node == null){
return false;
}
stack.push(root);
if(root == node){
return true;
}
boolean flg = getPath(root.left,node,stack);
if(flg == true){
return true;
}
flg = getPath(root.right,node,stack);
if(flg == true){
return true;
}
stack.pop();
return false;
}
public TreeNode lowestCommonAncestor2(TreeNode root,TreeNode p,TreeNode q){
if(root == null){
return null;
}
Stack<TreeNode> stack1 = new Stack<>();
getPath(root,p,stack1);
Stack<TreeNode> stack2 = new Stack<>();
getPath(root,p,stack2);
int size1 = stack1.size();
int size2 = stack2.size();
if(size1 > size2){
int size = size1 - size2;
while (size != 0){
stack1.pop();
size--;
}
while (!stack1.isEmpty() && !stack2.isEmpty()){
//判断两个的地址
if(stack1.peek() == stack2.peek()){
return stack1.pop();
}else {
stack1.pop();
stack2.pop();
}
}
}else{
int size = size2 - size1;
while (size != 0){
stack2.pop();
size--;
}
while (!stack1.isEmpty() && !stack2.isEmpty()){
//判断两个的地址是否相同
if(stack1.peek() == stack2.peek()){
return stack1.pop();
}else {
stack1.pop();
stack2.pop();
}
}
}
return null;
}
7.输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表
//输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表
//中序遍历
TreeNode prev = null;
public void inorder(TreeNode pCur){
if(pCur == null){
return;
}
inOrder(pCur.left);
pCur.left = prev;
if(prev != null){
prev.right = pCur;
}
prev = pCur;
//打印
//System.out.println(pCur.val+" ");
inorder(pCur.right);
}
public TreeNode Convert(TreeNode pRootOfTree){
if(pRootOfTree == null){
return null;
}
inorder(pRootOfTree);
TreeNode head = pRootOfTree;
while (head.left != null){
head = head.left;
}
return head;
}
8.通过前序遍历和中序遍历构建二叉树
注意:下面的preIndex应该写在外面,防止循环结束,回去之后记不住当前位置
//通过前序遍历和中序遍历构建二叉树
public int preIndex = 0;
public TreeNode createTreeByPandI(int[] preorder,int[] inorder,int inbegin,int inend ){
//递归终止条件,如果满足这个条件,说明没有左树或者右树了
if(inbegin > inend){
return null;
}
TreeNode root = new TreeNode(preorder[preIndex]);//构建前序遍历第一个节点
int rootIndex = findIndexOfI(inorder,inbegin,inend,preorder[preIndex]);//在中序遍历中查找根节点的位置
if(rootIndex == -1){
return null;
}
preIndex++;
root.left = createTreeByPandI(preorder,inorder,inbegin,rootIndex-1);
root.right = createTreeByPandI(preorder,inorder,rootIndex+1,inend);
return root;
}
private int findIndexOfI(int[] inorder,int inbegin,int inend,int key){
for (int i = inbegin; i <=inend ; i++) {
if(inorder[i] == key){
return i;
}
}
return -1;
}
public TreeNode buildTree(int[] preorder,int[] inorder){
if(preorder == null || inorder == null){
return null;
}
return createTreeByPandI(preorder,inorder,0,inorder.length-1);
}
9.通过后序遍历和中序遍历构建二叉树
和上面的类似,只需要简单修改即可:
//根据后序遍历和中序遍历构建二叉树
public int postIndex = 0;
public TreeNode createTreeByPandI(int[] inorder, int[] postorder,int inbegin,int inend){
if(inbegin > inend){
return null;
}
//在前序遍历中定义第一个节点
TreeNode root = new TreeNode(postorder[postIndex]);
//在中序遍历中找到根节点的位置
int rootIndex = findIndex(inorder,inbegin,inend,postorder[postIndex]);
if(rootIndex == -1){
return null;
}
postIndex--;
//先遍历右边,再遍历左边
root.right = createTreeByPandI(inorder,postorder,rootIndex+1,inend);
root.left = createTreeByPandI(inorder,postorder,inbegin,rootIndex-1);
return root;
}
public int findIndex(int[] inorder,int begin,int inend,int key){
for(int i = begin;i <= inend;i++){
if(inorder[i] == key){
return i;
}
}
return -1;
}
public TreeNode buildTree(int[] postorder, int[] inorder) {
if(postorder == null || inorder == null){
return null;
}
postIndex = inorder.length-1;
return createTreeByPandI(postorder,inorder,0,inorder.length-1);
}
}
10.二叉树的构建和遍历
import java.util.*;
//构建节点
class TreeNode{
public char val;
public TreeNode left;
public TreeNode right;
public TreeNode(char val){
this.val = val;
}
}
public class Main{
public static int i =0;
public static TreeNode createNode(String str){
//新建一个根节点root,因为每次回来都要重新建一个新的节点。因此让其为空
TreeNode root = null;
if(str.charAt(i) != '#'){
root = new TreeNode(str.charAt(i));
i++;
root.left = createNode(str);
root.right = createNode(str);
}else{
i++;
}
return root;
}
//中序遍历
public static void inOrder(TreeNode root){
if(root == null){
return;
}
inOrder(root.left);
System.out.print(root.val+" ");
inOrder(root.right);
}
public static void main(String[] arg){
Scanner in = new Scanner(System.in);
//hasNextLine遇到空格不结束
//hasNext遇到空格就结束
while(in.hasNextLine()){
String str = in.nextLine();
TreeNode root = createNode(str);
inOrder(root);
}
}
}
11.非递归实现前序遍历
void preOrderNor(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while (cur != null || !stack.isEmpty()) {
while (cur != null) {
stack.push(cur);
System.out.print(cur.val + " ");
cur = cur.left;
}
TreeNode top = stack.pop();
cur = top.right;
}
}
12.非递归实现中序遍历
void inOrderNor(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while (cur != null || !stack.isEmpty()) {
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
TreeNode top = stack.pop();
System.out.print(top.val+" ");
cur = top.right;
}
}
13.非递归实现后序遍历
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> ret = new ArrayList();
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
TreeNode prev = null;
while(cur != null || !stack.isEmpty()){
while(cur != null){
stack.push(cur);
cur = cur.left;
}
TreeNode top = stack.peek();
if(top.right == null || top.right == prev){
stack.pop();
ret.add(top.val);
prev = top;//指向弹出过的节点
}else{
cur = top.right;
}
}
return ret;
}