二叉树和堆

本文主要介绍了二叉树和堆的相关算法面试题,包括二叉树的查找、插入、删除、遍历等操作,以及堆的插入、删除和排序过程。重点讨论了二叉树的各种遍历方法,如广度优先遍历、深度优先遍历,以及如何判断二叉树是否为平衡或完全二叉树。此外,还探讨了堆排序的建堆和排序过程,以及堆在实际开发中的应用,如优先队列和求Top N问题。
摘要由CSDN通过智能技术生成

算法面试题

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:第一章 Python 机器学习入门之pandas的使用


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档

二叉树和堆

写在前面:由于水平有限,有些可能不是最优解,但是我觉得是我自己的能够更好理解的答案~

目录

目录

算法面试题

二叉树和堆

前言

一、二叉树

二叉树的查找

二叉树的插入

二叉树的删除

二叉树的遍历        二叉树的广度优先遍历   

二叉树的层序遍历

二叉树的深度优先遍历

二叉搜索树的后序遍历序列

二叉树节点个数

二叉树叶子节点个数

判断二叉树是否为平衡二叉树

判断二叉树是否为完全二叉树

两个二叉树是否完全相同

两个二叉树是否互为镜像

二叉搜索树的最近公共祖先

二叉树的最近公共祖先

翻转二叉树     

判断二叉树是否对称

求二叉树的深度(最大深度、最小深度)

求二叉树的直径

求二叉树的宽度

二叉树最大宽度

二叉树的所有路径

二叉树中和为某一值的路径

二叉搜索树的范围和

验证二叉搜索树

二叉树中第二小的结点

重建二叉树

根据前序遍历和后序遍历构建二叉树

二、堆

往堆中插入数据

删除堆顶元素

堆排序的过程(建堆和排序的过程)

小结

总结




前言

介绍二叉树和堆的最基本的考点


提示:以下是本篇文章正文内容,下面案例可供参考

一、二叉树

二叉树的查找


public class BinarySearchTree {
  private Node tree;

  public Node find(int data) {
    Node p = tree;
    while (p != null) {
      if (data < p.data) p = p.left;
      else if (data > p.data) p = p.right;
      else return p;
    }
    return null;
  }

  public static class Node {
    private int data;
    private Node left;
    private Node right;

    public Node(int data) {
      this.data = data;
    }
  }
}


二叉树的插入


public void insert(int data) {
  if (tree == null) {
    tree = new Node(data);
    return;
  }

  Node p = tree;
  while (p != null) {
    if (data > p.data) {
      if (p.right == null) {
        p.right = new Node(data);
        return;
      }
      p = p.right;
    } else { // data < p.data
      if (p.left == null) {
        p.left = new Node(data);
        return;
      }
      p = p.left;
    }
  }
}


二叉树的删除


public void delete(int data) {
  Node p = tree; // p指向要删除的节点,初始化指向根节点
  Node pp = null; // pp记录的是p的父节点
  while (p != null && p.data != data) {
    pp = p;
    if (data > p.data) p = p.right;
    else p = p.left;
  }
  if (p == null) return; // 没有找到

  // 要删除的节点有两个子节点
  if (p.left != null && p.right != null) { // 查找右子树中最小节点
    Node minP = p.right;
    Node minPP = p; // minPP表示minP的父节点
    while (minP.left != null) {
      minPP = minP;
      minP = minP.left;
    }
    p.data = minP.data; // 将minP的数据替换到p中
    p = minP; // 下面就变成了删除minP了
    pp = minPP;
  }

  // 删除节点是叶子节点或者仅有一个子节点
  Node child; // p的子节点
  if (p.left != null) child = p.left;
  else if (p.right != null) child = p.right;
  else child = null;

  if (pp == null) tree = child; // 删除的是根节点
  else if (pp.left == p) pp.left = child;
  else pp.right = child;
}

二叉树的遍历
        二叉树的广度优先遍历   

我们用二元组来存储最终遍历的节点,其中每一层的结果存入到level中,该层遍历完成后将level在存入外层的数组ret中;queue是将遍历到的node存入其中并按照先入先出的原则进行读取

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> ret = new ArrayList<List<Integer>>();
        if (root == null) {
            return ret;
        }

        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            List<Integer> level = new ArrayList<Integer>();
            int currentLevelSize = queue.size();
            for (int i = 1; i <= currentLevelSize; ++i) {
                TreeNode node = queue.poll();
                level.add(node.val);
                if (node.left != null) {
                    queue.offer(node.left);
                }
                if (node.right != null) {
                    queue.offer(node.right);
                }
            }
            ret.add(level);
        }
        
        return ret;
    }
}


二叉树的层序遍历

给定一个二叉树,返回其节点值自底向上的层序遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历) 

思路:这个和普通层序遍历的区别是它需要返回的是自底向上的层序(运用list.add(postion,val)即可,在规定位置进行插入节点)

public List<List<Integer>> levelOrderBottom(TreeNode root) {
        List<List<Integer>> listAll = new ArrayList<List<Integer>>();
        if(root==null)
            return listAll;
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.offer(root);
        while(!queue.isEmpty()){
            int size = queue.size();
            List<Integer> list = new ArrayList<Integer>();
            while(size-- !=0){
                TreeNode node = queue.poll();
                list.add(node.val);
                if(node.left!=null)
                    queue.offer(node.left);
                if(node.right!=null)
                    queue.offer(node.right);
            }
            listAll.add(0,list);
        }
        return listAll;
    }

二叉树的深度优先遍历

   递归遍历


void preOrder(Node* root) {
  if (root == null) return;
  print root // 此处为伪代码,表示打印root节点
  preOrder(root->left);
  preOrder(root->right);
}

void inOrder(Node* root) {
  if (root == null) return;
  inOrder(root->left);
  print root // 此处为伪代码,表示打印root节点
  inOrder(root->right);
}

void postOrder(Node* root) {
  if (root == null) return;
  postOrder(root->left);
  postOrder(root->right);
  print root // 此处为伪代码,表示打印root节点
}

非递归遍历

非递归先序遍历(申请一个栈,压入头结点,然后弹出栈节点,打印出来,再将弹出节点的右孩子压入,左孩子压入,不断重复这个过程,直到栈为空)

   public void preOrderUnRecur(Node head){
        if (head!=null){
            Stack<Node> stack=new Stack<Node>();
            stack.add(head);
            while(!stack.isEmpty()){
                head=stack.pop();
                System.out.printf(head.value+" ");
                if (head.right!=null){
                    stack.push(head.right);
                }
                if (head.left!=null){
                    stack.push(head.left);
                }
            }
        }
    }

非递归中序遍历

思路:中序是左,根,右,因此考虑将左边界都压入栈,直到节点为空,则从栈中拿出一个打印,当前节点右移,若当前节点不为空,则压入栈,当前节点为左【跟着程序可以走通,但是还是不太理解】

 `public void inOrderUnRecur(Node head){
        if(head!=null){
            Stack<Node> stack=new Stack<Node>();
            while (!stack.isEmpty()||head!=null){
                if (head!=null){
                    stack.push(head);
                    head=head.left;
                }
                else {
                    head=stack.pop();
                    System.out.println(head.value+" ");
                    head =head.right;
                }
            }
        }
    }

非递归后续遍历(需要建立两个stack,第一个stack的入栈是中、左右、第二个是中右左,保证出栈的时候是左右中)
 

 public void posOrderUnRecur(Node head){
        if (head!=null){
            Stack<Node> stack1=new Stack<Node>();
            Stack<Node> stack2=new Stack<Node>();
            stack1.add(head);
            while(!stack1.isEmpty()){
                head=stack1.pop();
                stack2.push(head);
                if (head.left!=null){
                    stack1.push(head.left);
                }
                if (head.right!=null){
                    stack1.push(head.right);
                }
            }
            while(!stack2.isEmpty()){
                System.out.printf(stack2.pop().value+" ");
            }
        }
    }

二叉搜索树的后序遍历序列

输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。

  public boolean verifyPostorder(int[] postorder) {
        return verify(postorder,0,postorder.length-1);

    }
    public boolean verify(int[]postorder,int i,int j){
        if(i>j)
            return t
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值