二叉树的遍历
- 前(根)序遍历:先输出父节点,再遍历左子树和右子树
- 中(根)序遍历:先输出左子树,再输出父节点,在输出右子树
- 后(根)序遍历:先输出左子树,在输出右子树,最后输出父结点
- 三种遍历方式的区别在于根节点的输出时机
代码实现
class BinaryTree{
Node root;
public BinaryTree(Node root) {
this.root = root;
}
public void preOrder() {
if(this.root==null) {
System.out.println("二叉树为空");
}
this.root.preOrder();
}
public void infixOrder() {
if(this.root==null) {
System.out.println("二叉树为空");
}
this.root.infixOrder();
}
public void postOrder() {
if(this.root==null) {
System.out.println("二叉树为空");
}
this.root.postOrder();
}
}
class Node{
int no;
String name;
Node left;
Node right;
public Node(int no,String name) {
this.no = no;
this.name = name;
}
@Override
public String toString() {
return "[no="+no+"\tname="+name+"]";
}
public void preOrder() {
System.out.println(this);
if(this.left!=null) {
this.left.preOrder();
}
if(this.right!=null) {
this.right.preOrder();
}
}
public void infixOrder() {
if(this.left!=null) {
this.left.infixOrder();
}
System.out.println(this);
if(this.right!=null) {
this.right.infixOrder();
}
}
public void postOrder() {
if(this.left!=null) {
this.left.postOrder();
}
if(this.right!=null) {
this.right.postOrder();
}
System.out.println(this);
}
}
二叉树的查找
二叉树的查找和遍历一样,也分前、中、后序查找;根据比对树中节点的顺序来区分
代码实现
class BinaryTree {
Node root;
public BinaryTree(Node root) {
this.root = root;
}
public void preOrder() {
if (this.root == null) {
System.out.println("二叉树为空");
}
this.root.preOrder();
}
public void infixOrder() {
if (this.root == null) {
System.out.println("二叉树为空");
}
this.root.infixOrder();
}
public void postOrder() {
if (this.root == null) {
System.out.println("二叉树为空");
}
this.root.postOrder();
}
public Node preSearch(int no) {
Node helper = this.root.preSearch(no);
if(helper==null) {
throw new RuntimeException("没有找到目标节点");
}
return helper;
}
public Node infixSearch(int no) {
Node helper = this.root.infixSearch(no);
if(helper==null) {
throw new RuntimeException("没有找到目标节点");
}
return helper;
}
public Node postSearch(int no) {
Node helper = this.root.postSearch(no);
if(helper==null) {
throw new RuntimeException("没有找到目标节点");
}
return helper;
}
}
class Node {
int no;
String name;
Node left;
Node right;
public Node(int no, String name) {
this.no = no;
this.name = name;
}
@Override
public String toString() {
return "[no=" + no + "\tname=" + name + "]";
}
public void preOrder() {
System.out.println(this);
if (this.left != null) {
this.left.preOrder();
}
if (this.right != null) {
this.right.preOrder();
}
}
public void infixOrder() {
if (this.left != null) {
this.left.infixOrder();
}
System.out.println(this);
if (this.right != null) {
this.right.infixOrder();
}
}
public void postOrder() {
if (this.left != null) {
this.left.postOrder();
}
if (this.right != null) {
this.right.postOrder();
}
System.out.println(this);
}
public Node preSearch(int no) {
Node helper = null;
if (this.no == no) {
helper = this;
}
if (this.left != null && helper == null) {
helper = this.left.preSearch(no);
}
if (right != null && helper == null) {
helper = this.right.preSearch(no);
}
return helper;
}
public Node infixSearch(int no) {
Node helper = null;
if (this.left != null) {
helper = this.left.infixSearch(no);
}
if (helper == null && this.no == no) {
helper = this;
}
if (helper == null && this.right != null) {
helper = this.right.infixSearch(no);
}
return helper;
}
public Node postSearch(int no) {
Node helper = null;
if (this.left != null) {
helper = this.left.postSearch(no);
}
if (helper == null && this.right != null) {
helper = this.right.postSearch(no);
}
if (helper == null && this.no == no) {
helper = this;
}
return helper;
}
}
二叉树的简单删除
- 如果删除的是叶子节点,将该叶子节点的父节点的指针置空
- 如果删除的是非叶子节点,删除该节点为根节点的整颗子树
代码实现
class BinaryTree {
Node root;
public BinaryTree(Node root) {
this.root = root;
}
public void preOrder() {
if (this.root == null) {
System.out.println("二叉树为空");
return;
}
this.root.preOrder();
}
public void infixOrder() {
if (this.root == null) {
System.out.println("二叉树为空");
return;
}
this.root.infixOrder();
}
public void postOrder() {
if (this.root == null) {
System.out.println("二叉树为空");
return;
}
this.root.postOrder();
}
public Node preSearch(int no) {
Node helper = this.root.preSearch(no);
if(helper==null) {
throw new RuntimeException("没有找到目标节点");
}
return helper;
}
public Node infixSearch(int no) {
Node helper = this.root.infixSearch(no);
if(helper==null) {
throw new RuntimeException("没有找到目标节点");
}
return helper;
}
public Node postSearch(int no) {
Node helper = this.root.postSearch(no);
if(helper==null) {
throw new RuntimeException("没有找到目标节点");
}
return helper;
}
public void delete(int no) {
if(this.root==null) {
System.out.println("树为空");
return;
}
if(root.no==no) {
root = null;
return;
}
this.root.delete(no);
}
}
class Node {
int no;
String name;
Node left;
Node right;
public Node(int no, String name) {
this.no = no;
this.name = name;
}
@Override
public String toString() {
return "[no=" + no + "\tname=" + name + "]";
}
public void preOrder() {
System.out.println(this);
if (this.left != null) {
this.left.preOrder();
}
if (this.right != null) {
this.right.preOrder();
}
}
public void infixOrder() {
if (this.left != null) {
this.left.infixOrder();
}
System.out.println(this);
if (this.right != null) {
this.right.infixOrder();
}
}
public void postOrder() {
if (this.left != null) {
this.left.postOrder();
}
if (this.right != null) {
this.right.postOrder();
}
System.out.println(this);
}
public Node preSearch(int no) {
Node helper = null;
if (this.no == no) {
helper = this;
}
if (this.left != null && helper == null) {
helper = this.left.preSearch(no);
}
if (right != null && helper == null) {
helper = this.right.preSearch(no);
}
return helper;
}
public Node infixSearch(int no) {
Node helper = null;
if (this.left != null) {
helper = this.left.infixSearch(no);
}
if (helper == null && this.no == no) {
helper = this;
}
if (helper == null && this.right != null) {
helper = this.right.infixSearch(no);
}
return helper;
}
public Node postSearch(int no) {
Node helper = null;
if (this.left != null) {
helper = this.left.postSearch(no);
}
if (helper == null && this.right != null) {
helper = this.right.postSearch(no);
}
if (helper == null && this.no == no) {
helper = this;
}
return helper;
}
public void delete(int no) {
if(this.left!=null&&this.left.no==no) {
this.left=null;
return;
}
if(this.left!=null) {
this.left.delete(no);
}
if(this.right!=null&&this.right.no==no) {
this.right=null;
return;
}
if(this.right!=null) {
this.right.delete(no);
}
}
}
顺序存储二叉树
从数据存储来看,数组存储方式和树存储方式可以相互转换;顺序存储的数组在遍历的时候使用树的遍历方式
特点
- 顺序二叉树通常只考虑完全二叉树
- 第n个元素的左子节点为2n+1
- 第n个元素的右子节点为2n+2
- 第n个元素的父节点为(n-1)/2
代码实现
class ArrayBinaryTree{
private int []arr;
public ArrayBinaryTree(int[] arr) {
this.arr = arr;
}
public void preOrder() {
preOrder(0);
}
public void infixOrder() {
infixOrder(0);
}
public void postOrder() {
postOrder(0);
}
private void preOrder(int index) {
if(arr==null||arr.length==0) {
System.out.println("空树");
return;
}
System.out.println(arr[index]);
if((2*index+1)< arr.length) {
preOrder(2*index+1);
}
if((2*index+2)<arr.length) {
preOrder(2*index+2);
}
}
private void infixOrder(int index) {
if((2*index+1)<arr.length) {
infixOrder(2*index+1);
}
System.out.println(arr[index]);
if((2*index+2)<arr.length) {
infixOrder(2*index+2);
}
}
private void postOrder(int index) {
if((2*index+1)<arr.length) {
postOrder(2*index+1);
}
if((2*index+2)<arr.length) {
postOrder(2*index+2);
}
System.out.println(arr[index]);
}
}
线索化二叉树
- 如上,在含有n个节点的二叉链表中含有n+1个空指针域(上方3,4,5三个节点的左右指针域),利用二叉链表中的空指针域,存放指向节点在某种遍历次序下的前驱和后继节点的指针(这种附加的指针称作线索),即二叉树的线索化
- 这种加上了线索的二叉链表称为线索链表,相应的二叉树称为线索二叉树。根据线索性质的不同,可以分为前序线索二叉树、中序线索二叉树、后序线索二叉树三种
- 在遍历中,某个节点前一个遍历的节点称为前驱节点,后一个称为后继节点
示意图
如上,线索化二叉树之后,Node节点的left和right有两种情况:
- left指向的是左子树,也有可能是指向前驱节点,比如1节点的left指向左子树,而5节点的left指向前驱节点
- right指向的是右子树,也有可能指向后继节点,比如1节点的right指向的是右子树,而5节点的right指向的是后继节点
代码实现(中序线索化)
class ThreadBinaryTree{
Node root;
Node pre = null;
public ThreadBinaryTree(Node root) {
this.root = root;
}
public void infixThread() {
infixThreadNodes(root);
}
public void infixThreadNodes(Node node) {
if(node==null) {
System.out.println("节点为空,不可线索化");
return;
}
if(node.left!=null) {
infixThreadNodes(node.left);
}
if(node.left==null) {
node.left=pre;
node.leftType = Node.NODE;
}
if(pre!=null&&pre.right==null) {
pre.right = node;
pre.rightType = Node.NODE;
}
pre = node;
if(node.right!=null) {
infixThreadNodes(node.right);
}
}
}
class Node {
public static final int CHILD_TREE=0;
public static final int NODE=1;
int no;
String name;
Node left;
Node right;
int leftType = Node.CHILD_TREE;
int rightType = Node.CHILD_TREE;
public Node(int no, String name) {
this.no = no;
this.name = name;
}
@Override
public String toString() {
return "[no=" + no + "\tname=" + name + "]";
}
}
中序线索化二叉树的遍历
public void infixThreadList() {
Node helper = root;
while (helper != null) {
while (helper.leftType == Node.CHILD_TREE) {
helper = helper.left;
}
System.out.println(helper);
while (helper.rightType == Node.NODE) {
helper = helper.right;
System.out.println(helper);
}
helper = helper.right;
}
}
前、中、后序线索化二叉树和遍历
class ThreadBinaryTree {
Node root;
Node pre = null;
public ThreadBinaryTree(Node root) {
this.root = root;
}
public void infixThread() {
infixThreadNodes(root);
}
public void preThread() {
preThreadNodes(root);
}
public void postThread() {
postThreadNodes(root);
}
public void infixThreadList() {
Node helper = root;
while (helper != null) {
while (helper.leftType == Node.CHILD_TREE) {
helper = helper.left;
}
System.out.println(helper);
while (helper.rightType == Node.NODE) {
helper = helper.right;
System.out.println(helper);
}
helper = helper.right;
}
}
public void preThreadList() {
Node helper = root;
while (helper != null) {
while (helper.leftType != Node.NODE) {
System.out.println(helper);
helper = helper.left;
}
System.out.println(helper);
while (helper.rightType == Node.NODE) {
helper = helper.right;
System.out.println(helper);
}
helper = helper.right;
}
}
public void postThreadList() {
postListNode(root);
}
private void postListNode(Node node) {
if(node.leftType==Node.CHILD_TREE) {
postListNode(node.left);
}
if(node.rightType==Node.CHILD_TREE) {
postListNode(node.right);
}
System.out.println(node);
}
public void infixThreadNodes(Node node) {
if (node == null) {
return;
}
infixThreadNodes(node.left);
if (node.left == null) {
node.left = pre;
node.leftType = Node.NODE;
}
if (pre != null && pre.right == null) {
pre.right = node;
pre.rightType = Node.NODE;
}
pre = node;
infixThreadNodes(node.right);
}
public void preThreadNodes(Node node) {
if (node == null) {
return;
}
boolean toLeft = true;
boolean toRight = true;
if (node.left == null) {
node.left = pre;
node.leftType = Node.NODE;
toLeft = false;
}
if (pre != null && pre.right == null) {
pre.right = node;
pre.rightType = Node.NODE;
toRight = false;
}
pre = node;
if (toLeft) {
preThreadNodes(node.left);
}
if(toRight) {
preThreadNodes(node.right);
}
}
public void postThreadNodes(Node node) {
if (node == null) {
return;
}
postThreadNodes(node.left);
postThreadNodes(node.right);
if (node.left == null) {
node.left = pre;
node.leftType = Node.NODE;
}
if (pre != null && pre.right == null) {
pre.right = node;
pre.rightType = Node.NODE;
}
pre = node;
}
}
class Node {
public static final int CHILD_TREE = 0;
public static final int NODE = 1;
int no;
String name;
Node left;
Node right;
int leftType = Node.CHILD_TREE;
int rightType = Node.CHILD_TREE;
public Node(int no, String name) {
this.no = no;
this.name = name;
}
@Override
public String toString() {
return "[no=" + no + "\tname=" + name + "]";
}
}
|