今日算法(二)
2018-03-02 18:15
106 查看
今天写写有关二叉树遍历的问题吧,这类算法都比较基础,笔试过程中都会有用到过,例如:二叉树的先序,中序,后序遍历,BFS,DFS等
第一题:二叉树的先序,中序,后序遍历(递归版本和非递归版本实现)
递归实现:
/** * 二叉树先序、中序,后序遍历的递归实现 */ public class PrintBinaryTree { public static class Node { private int value; private Node left; private Node right; public Node(int data) { this.value = data; } } //先序 根左右 public static void preOrderRecur(Node head) { if (head == null){ return; } System.out.print(head.value+" "); preOrderRecur(head.left); preOrderRecur(head.right); } //中序 左根右 public static void inOrderRecur(Node head) { if (head == null){ return; } inOrderRecur(head.left); System.out.print(head.value+" "); inOrderRecur(head.right); } //后序 左右根 public static void posOrderRecur(Node head) { if (head == null){ return; } preOrderRecur(head.left); preOrderRecur(head.right); System.out.print(head.value+" "); } }
非递归实现:
先序:是使用一个栈空间,将头节点存到栈内,然后栈顶弹出打印,只要左右节点不为空,就先将right节点压栈,再将left节点压栈,(注意左右顺序不能改变,原因是因为栈的结构特点,先进后出)
public static class Node { public int value; public Node left; public Node right; public Node(int data) { this.value = data; } } //先序 public static void preOrderUnRecur(Node head) { System.out.print("pre-order: "); if (head != null){ Stack<Node> stack = new Stack<>(); stack.push(head); while (!stack.isEmpty()){ head = stack.pop(); System.out.print(head.value+" "); if (head.right != null){ stack.push(head.right); } if (head.left != null){ stack.push(head.left); } } } }
中序:是使用一个栈空间,将头节head点存到栈内,然后一路将左子节点全部压入栈内,当head为空时,栈顶元素弹出并打印,将head赋值为head的右孩子(head.right)当我的占空间和head节点都为null时结束
//中序 public static void inOrderUnRecur(Node head) { System.out.print("in-order: "); if (head != null){ Stack<Node> stack = new Stack<>(); while (!stack.isEmpty() || head != null){ if (head != null){ stack.push(head); head = head.left; }else{ head = stack.pop(); System.out.print(head.value+" "); head = head.right; } } } System.out.println(); }
后序:是使用两个栈空间来解决,就是先序遍历的变形,先序遍历是根左右,后序是左右根,先序遍历使用栈是先压入right,在压入left,此时我们将left先压入,再将right压入,那么打印出来的就是(根右左),这是在使用另一个辅助空间栈将(根右左)压入,打印辅助栈的pop()就是结果了,也就是说先序遍历的打印变成了压入辅助栈的过程,在单独进行打印。
//后序 public static void posOrderUnRecur1(Node head) { System.out.print("pos-order: "); if (head != null){ Stack<Node> pushStack = new Stack<>(); Stack<Node> popStack = new Stack<>(); pushStack.push(head); while (!pushStack.isEmpty()){ head = pushStack.pop(); popStack.push(head); if (head.left != null){ pushStack.push(head.left); } if (head.right != null){ pushStack.push(head.right); } } while (!popStack.isEmpty()) { System.out.print(popStack.pop().value + " "); } } }
第二题:BFS宽度优先遍历,DFS广度优先遍历
这两种算法是针对图结构,但是我们经常会遇到这两种思想的变型题
BFS的思想就是一层一层的从左到右打印,使用Queue队列解决比较方便,从上往下打印二叉树就是这种思想。接下来的代码写的是图的BFS
/** * 宽度优先遍历 * 队列实现 */ public class bfs { //这里对Graph.Node做一下解释哈,这是图的节点类型, //nexts代表相邻的节点数组 public static void bfs(Graph.Node node) { if (node == null) { return; } Queue<Graph.Node> queue = new LinkedList<>(); HashSet<Graph.Node> map = new HashSet<>(); queue.add(node); map.add(node); while (!queue.isEmpty()) { Graph.Node cur = queue.poll(); System.out.println(cur.value); for (Graph.Node next : cur.nexts) { if (!map.contains(next)) { map.add(next); queue.add(next); } } } } }
DFS的思想就是一条路走到黑,直到我的next节点为null才结束,在DFS中我们需要记录下该节点是否重新走过,此时我是用的Hash表,利用Hash标的特性解决。
/** * 深度优先遍历 * 栈实现 */ public class dfs { public static void dfs(Graph.Node node) { if (node == null) { return; } Stack<Graph.Node> stack = new Stack<>(); HashSet<Graph.Node> set = new HashSet<>(); stack.add(node); set.add(node); System.out.println(node.value); while (!stack.isEmpty()) { Graph.Node cur = stack.pop(); for (Graph.Node next : cur.nexts) { if (!set.contains(next)) { stack.push(cur); stack.push(next); set.add(next); System.out.println(next.value); break; } } } } }
图的结构生成:上面的BFS和DFS都是利用该图的node点结构
//图 public class Graph { public HashMap<Integer, Node> nodes; public HashSet<Edge> edges; public Graph() { nodes = new HashMap<>(); edges = new HashSet<>(); } //边 public static class Edge { public int weight; public Node from; public Node to; public Edge(int weight, Node from, Node to) { this.weight = weight; this.from = from; this.to = to; } } //点 public static class Node { public int value; public int in;//入度 public int out;//初度 public ArrayList<Node> nexts; public ArrayList<Edge> edges; public Node(int value) { this.value = value; in = 0; out = 0; nexts = new ArrayList<>(); edges = new ArrayList<>(); } } }
相关文章推荐
- PHP版今日头条算法面试题(持续更新)
- 今日头条算法
- 今日头条推荐算法详解(PDF下载)
- 今日算法(四)
- 3分钟了解今日头条推荐算法原理(附视频+PPT)
- 今日头条2018校招算法方向(第一批)编程题1(离散+树状数组)
- 干货丨3分钟了解今日头条推荐算法原理(附视频+PPT)
- 三维重建面试13X:一些算法试题-今日头条AI-Lab
- 【算法题】2018今日头条编程题一
- 今日算法(三)
- 今日算法(十一)
- 今日头条面试算法题——确定ABCDE五个学校名次
- 今日头条算法原理(全)
- 算法面试题-今日头条2017客户端工程师实习生笔试题4:或与加
- 今日头条核心技术“个性推荐算法”揭秘
- 今日学习札记——STL通用算法(11.20)
- 今日头条研发算法岗实习生笔试题解答篇_0324晚
- 今日头条首次公布算法原理 让算法公开透明
- 今日头条公布算法原理,你认可他们的理念吗?
- 今日头条推荐算法原理全文详解