Morris算法
morris遍历算法可以将空间复杂度将为 O(1),从而实现时间复杂度为O(n),而空间复杂度为O(1)的遍历算法。
morris算法实现规则:
代码实现:
主函数类:
package Supplement;
import Tree.TreeNode;
public class MorrisMain {
public static void main(String[] args){
TreeNode root = new TreeNode(1);
TreeNode rootLeft = new TreeNode(2);
TreeNode rootRight = new TreeNode(3);
root.left= rootLeft;
root.right = rootRight;
TreeNode rootLeftLeft = new TreeNode(4);
TreeNode rootLeftRight = new TreeNode(5);
rootLeft.left = rootLeftLeft;
rootLeft.right = rootLeftRight;
TreeNode rootRightLeft = new TreeNode(6);
TreeNode rootRightRight = new TreeNode(7);
rootRight.left = rootRightLeft;
rootRight.right = rootRightRight;
//morris遍历
MorrisPractice morrisPractice = new MorrisPractice();
System.out.print("morris遍历: ");
}
}
实现类:
package Supplement;
import Tree.TreeNode;
public class MorrisPractice {
/**
* morris遍历基础代码
* 无需额外空间遍历
* */
public void morris(TreeNode head){
if(head == null) return;;
TreeNode cur = head;
TreeNode mostRight = null;
while (cur != null){
mostRight = cur.left;
if(mostRight != null){
while (mostRight.right != null && mostRight.right != cur){
mostRight = mostRight.right;
}
if(mostRight.right == null){ //第一次来到这个结点
System.out.print(cur.value+" ");
mostRight.right = cur;
cur = cur.left;
continue;
}else {
mostRight.right = null;
System.out.print(cur.value+" ");
}
}else{
System.out.print(cur.value+" ");
}
cur = cur.right;
}
System.out.println();
}
}
代码运行过程:
morris算法实现先序遍历:在第一次经过节点和无左节点时打印
//morris - 先序遍历
public void morrisPre(TreeNode head){
if(head == null) return;
TreeNode cur = head;
TreeNode mostRight = null;
while (cur != null){
mostRight = cur.left;
if(mostRight != null){ //有左节点
while (mostRight.right != null && mostRight.right != cur){
mostRight = mostRight.right;
}
if(mostRight.right == null){ //第一次结点
System.out.print(cur.value+" ");
mostRight.right = cur;
cur = cur.left;
continue;
}else { //第二次
mostRight.right = null;
}
}else { //无左节点 -- 叶子结点
System.out.print(cur.value+" ");
}
cur = cur.right;
}
System.out.println();
}
中序遍历:
//morris - 中序遍历
public void morrisIn(TreeNode head){
if(head == null) return;
TreeNode cur = head;
TreeNode mostRight = null;
while (cur != null){
mostRight = cur.left;
if(mostRight != null){
while (mostRight.right != null && mostRight.right != cur){
mostRight = mostRight.right;
}
if(mostRight.right == null) {
mostRight.right = cur;
cur = cur.left;
continue;
}else{
mostRight.right = null;
}
}
System.out.print(cur.value+" ");
cur = cur.right;
}
System.out.println();
}
后序遍历:第二次进过节点时,倒序打印节点的右边界,最后在倒序打印整棵树的右边界
//morris - 后续遍历
public void morrisPos(TreeNode head){
if(head == null) return;
TreeNode cur = head;
TreeNode mostRight = null;
while (cur != null){
mostRight = cur.left;
if(mostRight != null){
while (mostRight.right != null && mostRight.right != cur){
mostRight = mostRight.right;
}
if(mostRight.right == null){
mostRight.right = cur;
cur = cur.left;
continue;
}else {
mostRight.right = null;
printRightNode(cur.left);
}
}
cur = cur.right;
}
printRightNode(head); //打印最后的根节点的右边界
}
//逆向打印树的右边界(树的所有右节点)
public void printRightNode(TreeNode node){
if(node == null) return;
TreeNode cur = reverseNode(node); //逆转结点
TreeNode tmp = cur;
while (tmp != null){
System.out.print(tmp.value+" ");
tmp = tmp.right;
}
reverseNode(cur); //恢复结点
}
//反转结点指向(类反转链表
public TreeNode reverseNode(TreeNode node){
TreeNode next = null;
TreeNode cur = null;
while (node != null){
next = node.right;
node.right = cur;
cur = node;
node = next;
}
return cur;
}