您的位置:首页 > Web前端

今日算法(二)

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<>();
}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  剑指offer