您的位置:首页 > 编程语言 > Java开发

JAVA二叉树的遍历和序列化

2017-04-09 13:03 148 查看

二叉树实体类

public class TreeNode {
private int val = 0;
private TreeNode left = null;
private TreeNode right = null;

public TreeNode(int val) {
this.val = val;
}

public int getVal() {
return val;
}

public void setVal(int val) {
this.val = val;
}

public TreeNode getLeft() {
return left;
}

public void setLeft(TreeNode left) {
this.left = left;
}

public TreeNode getRight() {
return right;
}

public void setRight(TreeNode right) {
this.right = right;
}
}


递归遍历

/**
* 前序遍历(根左右)
*/
public void DLR(TreeNode head) {
if (head == null) return;
System.out.print(head.getVal());
if (head.getLeft() != null) DLR(head.getLeft());
if (head.getRight() != null) DLR(head.getRight());
}

/**
* 中序遍历(左根右)
*/
public void LDR(TreeNode head) {
if (head == null) return;
if (head.getLeft() != null) LDR(head.getLeft());
System.out.print(head.getVal());
if (head.getRight() != null) LDR(head.getRight());
}

/**
* 后序遍历(左右根)
*/
public void LRD(TreeNode head) {
if (head == null) return;
if (head.getLeft() != null) LRD(head.getLeft());
if (head.getRight() != null) LRD(head.getRight());
System.out.print(head.getVal());
}


递归遍历没什么好说的,比较简单,下面介绍非递归遍历

非递归遍历

/**
* 前序遍历(非递归)
*/
public void dlr_by_stack(TreeNode head) {
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(head);
while (!stack.isEmpty()) {
TreeNode node = stack.pop();
System.out.print(node.getVal());
if (node.getRight() != null) {
stack.push(node.getRight());
}
if (node.getLeft() != null) {
stack.push(node.getLeft());
}
}
}


1:准备一个栈,头节点先入栈。

2:弹出栈顶节点,打印节点的值,然后当前结点的右孩子和左孩子依次入栈

3:重复步骤2直到栈为空

由于栈的结构是先进后出,所以每次先弹出的都是左孩子。弹出左孩子后又将该节点的右孩子和左孩子依次入栈。这样就实现了根左右的遍历顺序。

/**
* 中序遍历(非递归)
*/
public void ldr_by_stack(TreeNode head) {
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode cur = head;
while (!stack.isEmpty() || cur != null) {
if (cur != null) {
stack.push(cur);//左孩子依次入栈
cur = cur.getLeft();
} else {//左孩子为空时,打印节点值
cur = stack.pop();
System.out.print(cur.getVal());
cur = cur.getRight();
}
}
}


1:同样先准备一个栈,令头节点先入栈

2:将整颗树的左孩子依次入栈,当没有左孩子时,右孩子入栈

3:重复步骤2直到栈为空或者当前结点为空

/**
* 后序遍历(非递归)
*/
public void lrd_by_stack(TreeNode head) {
Stack<TreeNode> s1 = new Stack<>();
Stack<TreeNode> s2 = new Stack<>();
s1.push(head);
while (!s1.isEmpty()) {
TreeNode node = s1.pop();
s2.push(node);
if (node.getLeft() != null) s1.push(node.getLeft());
if (node.getRight() != null) s1.push(node.getRight());
}

while (!s2.isEmpty()) {
System.out.print(s2.pop().getVal());
}
}


1:准备两个栈s1和s2,头节点进入s1

2:弹出s1的栈顶节点,计为node,node入栈s2,node的左右节点依次入s1

3:重复步骤2直到s2为空,这是s2的出栈顺序就是后序遍历的结果

层序遍历

/**
* 层序遍历
*/
public void printTree(TreeNode head) {
LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
TreeNode node;
TreeNode last = head;
TreeNode nlast = last;
queue.offer(head);

while (!queue.isEmpty()) {
node = queue.poll();
System.out.print(node.getVal());
if (node.getLeft() != null) {
queue.offer(node.getLeft());
nlast = node.getLeft();
}
if (node.getRight() != null) {
queue.offer(node.getRight());
nlast = node.getRight();
}
if (node == last) {
last = nlast;
System.out.println();
}
}
}


序列化

将一颗二叉树序列化成字符串,空节点用#!表示

/**
* 前序序列化
*/
private void serialize_dlr(TreeNode head, StringBuilder builder) {
builder.append(head.getVal());
builder.append("!");
if (head.getLeft() != null) {
serialize_dlr(head.getLeft(), builder);
} else {
builder.append("#!");
}
if (head.getRight() != null) {
serialize_dlr(head.getRight(), builder);
} else {
builder.append("#!");
}
}


/**
* 中序序列化
*/
private void serialize_ldr(TreeNode head, StringBuilder builder) {
if (head.getLeft() != null) {
serialize_ldr(head.getLeft(), builder);

e620
} else {
builder.append("#!");
}
builder.append(head.getVal());
builder.append("!");
if (head.getRight() != null) {
serialize_ldr(head.getRight(), builder);
} else {
builder.append("#!");
}
}


/**
* 后序序列化
*/
private void serialize_lrd(TreeNode head, StringBuilder builder) {
if (head.getLeft() != null) {
serialize_lrd(head.getLeft(), builder);
} else {
builder.append("#!");
}
if (head.getRight() != null) {
serialize_lrd(head.getRight(), builder);
} else {
builder.append("#!");
}
builder.append(head.getVal());
builder.append("!");
}


完整代码

/**
* Created by Clanner on 2017/10/25.
* 二叉树工具类
*/
public class TreeUtil {

public static final int DLR = 1;
public static final int LDR = 2;
public static final int LRD = 3;

private TreeUtil() {
}

public static final TreeUtil getInstance() {
return Holder.instance;
}

private static final class Holder {
private static final TreeUtil instance = new TreeUtil();
}

/**
* 层序遍历
*/
public void printTree(TreeNode head) {
LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
TreeNode node;
TreeNode last = head;
TreeNode nlast = last;
queue.offer(head);

while (!queue.isEmpty()) {
node = queue.poll();
System.out.print(node.getVal());
if (node.getLeft() != null) {
queue.offer(node.getLeft());
nlast = node.getLeft();
}
if (node.getRight() != null) {
queue.offer(node.getRight());
nlast = node.getRight();
}
if (node == last) {
last = nlast;
System.out.println();
}
}
}

/**
* 前序反序列化
*
* @param head
* @param values
* @param index
*/
private void deserialize_dlr(TreeNode head, String[] values, int index) {

}

/**
* 前序序列化
*/
private void serialize_dlr(TreeNode head, StringBuilder builder) {
builder.append(head.getVal());
builder.append("!");
if (head.getLeft() != null) {
serialize_dlr(head.getLeft(), builder);
} else {
builder.append("#!");
}
if (head.getRight() != null) {
serialize_dlr(head.getRight(), builder);
} else {
builder.append("#!");
}
}

/**
* 中序序列化
*/
private void serialize_ldr(TreeNode head, StringBuilder builder) {
if (head.getLeft() != null) {
serialize_ldr(head.getLeft(), builder);
} else {
builder.append("#!");
}
builder.append(head.getVal());
builder.append("!");
if (head.getRight() != null) {
serialize_ldr(head.getRight(), builder);
} else {
builder.append("#!");
}
}

/**
* 后序序列化
*/
private void serialize_lrd(TreeNode head, StringBuilder builder) {
if (head.getLeft() != null) {
serialize_lrd(head.getLeft(), builder);
} else {
builder.append("#!");
}
if (head.getRight() != null) {
serialize_lrd(head.getRight(), builder);
} else {
builder.append("#!");
}
builder.append(head.getVal());
builder.append("!");
}

/**
* 前序遍历(根左右)
*/
public void DLR(TreeNode head) {
if (head == null) return;
System.out.print(head.getVal());
if (head.getLeft() != null) DLR(head.getLeft());
if (head.getRight() != null) DLR(head.getRight());
}

/**
* 前序遍历(非递归)
*/
public void dlr_by_stack(TreeNode head) {
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(head);
while (!stack.isEmpty()) {
TreeNode node = stack.pop();
System.out.print(node.getVal());
if (node.getRight() != null) {
stack.push(node.getRight());
}
if (node.getLeft() != null) {
stack.push(node.getLeft());
}
}
}

/**
* 中序遍历(左根右)
*/
public void LDR(TreeNode head) {
if (head == null) return;
if (head.getLeft() != null) LDR(head.getLeft());
System.out.print(head.getVal());
if (head.getRight() != null) LDR(head.getRight());
}

/**
* 中序遍历(非递归)
*/
public void ldr_by_stack(TreeNode head) {
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode cur = head;
while (!stack.isEmpty() || cur != null) {
if (cur != null) {
stack.push(cur);//左孩子依次入栈
cur = cur.getLeft();
} else {//左孩子为空时,打印节点值
cur = stack.pop();
System.out.print(cur.getVal());
cur = cur.getRight();
}
}
}

/**
* 后序遍历(左右根)
*/
public void LRD(TreeNode head) {
if (head == null) return;
if (head.getLeft() != null) LRD(head.getLeft());
if (head.getRight() != null) LRD(head.getRight());
System.out.print(head.getVal());
}

/**
* 后序遍历(非递归)
*/
public void lrd_by_stack(TreeNode head) {
Stack<TreeNode> s1 = new Stack<>();
Stack<TreeNode> s2 = new Stack<>();
s1.push(head);
while (!s1.isEmpty()) {
TreeNode node = s1.pop();
s2.push(node);
if (node.getLeft() != null) s1.push(node.getLeft());
if (node.getRight() != null) s1.push(node.getRight());
}

while (!s2.isEmpty()) {
System.out.print(s2.pop().getVal());
}
}

/**
* 判断两个树是否相同
*/
public boolean isSameTree(TreeNode p, TreeNode q) {
if (p == null && q == null) return true;
if (p == null || q == null) return false;
if (p.getVal() != q.getVal()) return false;
return isSameTree(p.getLeft(), q.getLeft()) && isSameTree(p.getRight(), q.getRight());
}

/**
* 序列化
*
* @param head 树的根节点
* @param type 序列化方式
*/
public String serialize(TreeNode head, int type) {
StringBuilder builder = new StringBuilder();
builder.append("type_id:");
builder.append(type);
builder.append(":");
switch (type) {
case DLR:
serialize_dlr(head, builder);
return builder.toString();
case LDR:
serialize_ldr(head, builder);
return builder.toString();
case LRD:
serialize_lrd(head, builder);
return builder.toString();
default:
return "序列化类型错误";
}
}

/**
* 层序构造,构建完全二叉树
*
* @param values
*/
public TreeNode createTree(int[] values) {
TreeNode head = new TreeNode(values[0]);
LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
TreeNode node;
TreeNode last = head;
TreeNode nlast = last;
queue.offer(head);

int i = 1;
while (i + 1 < values.length) {
node = queue.poll();
if (node.getLeft() == null) {
node.setLeft(new TreeNode(values[i++]));
queue.offer(node.getLeft());
nlast = node.getLeft();
}
if (node.getRight() == null) {
node.setRight(new TreeNode(values[i++]));
queue.offer(node.getRight());
nlast = node.getRight();
}
if (node == last) {
last = nlast;
}
}
return head;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: