二叉树题目

来源:互联网 发布:javascript 数组对象 编辑:程序博客网 时间:2024/04/30 03:27

1. 二叉树的三种遍历方式

  • 先序遍历:节点 -> left子节点(包括其子树)-> right子节点(包括其子树);
  • 后序遍历:left子节点(包括其子树)-> right子节点(包括其子树)-> 节点;
  • 中序遍历:left子节点(包括其子树)-> 节点 -> right子节点。
2. 怎样从根开始逐层打印二叉树结点数据

其实就是广度优先遍历(BFS)的思想。

  1. 使用一个队列queue,将root入队;
  2. 若queue不为空,出队一个节点,并将此节点两个儿子按从左到右顺序入栈
  3. 则出队顺序即为逐层遍历顺序。
3. 如何判断一颗二叉树是否平衡二叉树?

平衡二叉树定义:任意节点的左右子树深度相差不超过1。

只要当前节点root的left和right深度差不超过1,就递归判断left和right是否也符合条件,直到left或right为null,这意味着他们的深度为0,能走到这一步,前面必然都符合条件,所以整个二叉树都符合条件。

//先编写一个递归计算二叉树深度的函数getDepth,利用递归实现public static int getDepth(Node root){if(root == null)return 0;int leftDepth = getDepth(root.left);int rightDepth = getDepth(root.right);return (leftDepth > rightDepth? leftDepth : rightDepth) + 1;}public static boolean isBalance(Node root){if(root == null)return true;int leftDepth = getDepth(root.left);int rightDepth = getDepth(root.right);int distance = leftDepth > rightDepth ? leftDepth-rightDepth : rightDepth - leftDepth;if(distance > 1)return false;elsereturn isBalance(root.left) && isBalance(root.right);}
4. 设计一个算法,找出二叉树上任意两个节点的最近共同父节点,复杂度如果是O(N^2)则不得分。

  1. 需要两个栈,在递归遍历寻找两个节点的同时,将从根到两个节点的路径分别压栈(由于是递归,两节点父节点最先入栈,根最后入栈);
  2. 同时pop两个元素,如果相等,则继续pop,直到不等,则之前相等的元素节点就是最近共同父节点。
此解法需要两个辅助栈。

注意这里是二叉树而不是二叉查找树,如果是二叉查找树,则不需要递归查找,直接往下遍历,直到分叉位置,就是最近共同父节点。

//递归寻找节点,并将路径存入stack中pubilc static boolean getPositionByNode(Node root, Node node, Stack<E> stack){if(root == null)return false;//递归的基准情况if(root == node){stack.push(root);return true;}//递归调用if(getPositionByNode(root.left, node, stack) || getPositionByNode(root.right, node, stack)){stack.push(root);return true;}return false;}public static Node findParentNode(Node root, Node node1, Node node2){Stack stack1 = new Stack();getPositionByNode(node1, stack1);Stack stack2 = new Stack();getPositionByNode(node2, stack2);Node temp = null;//两者不相等,则同时弹栈,但是要记录弹栈元素while(stack1.peek() != stack2.peek()){temp = stack1.pop();stack2.pop();}return temp;}

5. 如何不用递归实现二叉树的三种遍历。

  • 先序遍历
//先序遍历public static void preOrder(Node root){Stack stack = new Stack();Node node = root;while(node != null || stack.size() > 0){//压入所有左节点,压入前打印while(node != null){System.out.println(node.data);stack.push(node);node = node.left;}if(stack.size() > 0){node = stack.pop();node = node.right;}}}
  • 后序遍历
//后序遍历public static void postOrder(Node root){Stack stack = new Stack();Node node = root;Node prev = node;while(node != null || stack.size() > 0){//压入所有左节点while(node != null){stack.push(node);node = node.left;}if(stack.size() > 0){Node temp = stack.peek().right;//如果右节点是null或者刚访问过if(temp == null || temp == prev){node = stack.pop();System.out.println(node.data);prev = node;node = null;}else{node = temp;}}}}
  • 中序遍历
//中序遍历public static void inOrder(Node root){Stack stack = new Stack();Node node = root;while(node != null || stack.size() > 0){//压入所有左节点while(node != null){stack.push(node);node = node.left;}if(stack.size() > 0){node = stack.pop();System.out.println(node.data);node = node.right();}}}

6. 在二叉树中找出和为某一值的所有路径

当访问某一个节点时,把该节点添加到路径上,并累加当前节点的值。如果当前节点为叶节点并且当前路径的和刚好等于输入的整数,则当前的路径符合要求,把它打印出来。如果当前节点不是叶节点,则继续访问它的子节点。当前节点访问结束后,递归函数自动回到父节点。因此,函数退出之前要在路径上删除当前节点并减去当前节点的值,以确保返回父节点时路径刚好是根节点后父节点的路径。不难看出保存路径的数据结构实际上是一个栈结构。

7. 编写一个程序,把一个有序整数数组放到二叉树中

构造一个完全二叉树,让数组第一个元素小标为1,则有左儿子是2i, 右儿子是 2i+1,这样是平衡的。

8. 判断整数序列是不是二叉查找树的后序遍历结果

在后序遍历的序列中,最后一个元素为树的根节点。从头开始扫描这个序列,比根节点小的元素都应该位于序列的左半部分,从第一个大于根节点开始到根节点前面一个元素为止,所有元素都大于根节点,因为这部分元素对应的是树的右子树。根据这样划分,把序列分为左右两部分,递归的确认序列的左右两部分是不是都是二叉查找树。

9. 求二叉树的镜像

利用遍历二叉树的方法,把访问操作修改为交换左右节点的逻辑即可。

10. 一棵二叉查找树,令 f = (最大值 + 最小值)/2,设计一个算法,找出距离 f 值最近,大于 f 值的节点。复杂度如果是O(n^2)则不得分。

//最小最大节点分别在最左下与最右下节点public static Node find(Node root){Node min = findMinNode(root);Node max = findMaxNode(root);double find = (double)(min.data + max.data)/2.0;return findNode(root, find);}//最小节点public static Node findMinNode(Node root){Node min = root;]while(min.left != null)min = min.left;return min;}//最大节点public static Node finMaxNode(Node root){Node max = root;while(max.right != null)max = max.right;return max;}//寻找节点,O(logN)public static findNode(Node root, double mid){//如果小于等于,则从右边找一个最小值if(root.data <= mid){if(root.right == null)return root;Node find = findNode(root.right, mid);//不一定找得到return find.data < mid ? root : find;}//如果大于,则找到leftelse{//root.data > findif(root.left == null)return root;Node find = findNode(root.left, mid);//不一定找到return find.data < mid ? root:find;}}

11. 把二叉查找树转变成排序的双向链表。

就是树的中序遍历。



原创粉丝点击