假设来到当前节点cur,开始时cur来到头节点位置、
1) 如果cur没有左孩子,cur向右移动(cur = cur.right)
2) 如果cur有左孩子,找到左子树上最右的节点mostRight:
a.如果mostRight的右指针指向空,让其指向cur,然后cur向左移动(cur = cur.left)
b.如果mostRgiht的右指针指向cur,让其指向null,然后cur向右移动(cur = cur.right)
3) cur为空时遍历停止
Java代码如下:
public static void morris(Node head){
if (head == null){
return;
}
Node cur = head;
Node mostRight = null;
while (cur != null){ // 3) cur为空时遍历停止
mostRight = head.left; //mostRight是cur的左孩子
if (mostRight != null){//有左子树,如果没有,1)就把指针指向右孩子
while (mostRight.right != null && mostRight.right != cur){
mostRight = mostRight.right;//找到左子树上最有的节点
}
//mostRight变成了cur左子树上最右的节点
if (mostRight.right == null){// 2).a 如果左子树的最右节点的右指针为空,让其指向cur,然后cur向左移动(cur = cur.left)
mostRight.right = cur;
cur = cur.left;
continue;
}else {//mostRight.right == cur 2).b 如果mostRgiht的右指针指向cur,让其指向null,然后cur向右移动(cur = cur.right)
mostRight.right = null;
}
}
cur = cur.right;
}
Morris遍历改造成为先序遍历
只出现一次的,直接打印。出现两次的,打印第一次出现的。
public static void morrisPre(Node head){
if (head == null){
return;
}
Node cur = head;
Node mostRight = null;
while (cur != null){ // 3) cur为空时遍历停止
mostRight = head.left; //mostRight是cur的左孩子
if (mostRight != null){//有左子树,如果没有,1)就把指针指向右孩子
while (mostRight.right != null && mostRight.right != cur){
mostRight = mostRight.right;//找到左子树上最有的节点
}
//mostRight变成了cur左子树上最右的节点
if (mostRight.right == null){// 2).a 如果左子树的最右节点的右指针为空,让其指向cur,然后cur向左移动(cur = cur.left)
System.out.println(cur.value);//第一次来到cur,打印。
mostRight.right = cur;
cur = cur.left;
continue;
}else {//mostRight.right == cur 2).b 如果mostRgiht的右指针指向cur,让其指向null,然后cur向右移动(cur = cur.right)
mostRight.right = null;
}
}else {
System.out.println(cur.value);//没有左子树直接打印
}
cur = cur.right;
}
}
Morris遍历改造成为中序遍历
只出现一次的,直接打印。出现两次的,打印第二次出现的。
public static void morrisIn(Node head){
if (head == null){
return;
}
Node cur = head;
Node mostRight = null;
while (cur != null){ // 3) cur为空时遍历停止
mostRight = head.left; //mostRight是cur的左孩子
if (mostRight != null){//有左子树,如果没有,1)就把指针指向右孩子
while (mostRight.right != null && mostRight.right != cur){
mostRight = mostRight.right;//找到左子树上最有的节点
}
//mostRight变成了cur左子树上最右的节点
if (mostRight.right == null){// 2).a 如果左子树的最右节点的右指针为空,让其指向cur,然后cur向左移动(cur = cur.left)
System.out.println(cur.value);//第一次来到cur,打印。
mostRight.right = cur;
cur = cur.left;
continue;
}else {//mostRight.right == cur 2).b 如果mostRgiht的右指针指向cur,让其指向null,然后cur向右移动(cur = cur.right)
mostRight.right = null;
}
}else {
System.out.println(cur.value);//没有左子树直接打印
}
System.out.println(cur.value);//只加了这一句。如果没有左子树,直接打印,如果是第一次去到cur不打印,第二次到的时候打印,也会跳到这一句来
cur = cur.right;
}
}
Morris遍历改造成为逆序遍历
第一来的位置不打印,到第二次的位置的时候逆序打印它的左子树的右边界。然后最后再打印整颗树的右边界
判断一颗二叉树是否为搜索二叉树
中序遍历进行判断当前节点是否比之前节点的值要大。
public static boolean isBST(Node head) {
if (head == null) {
return true;
}
Node cur = head;
Node mostRight = null;
int preValue = Integer.MIN_VALUE;
while (cur != null) { // 3) cur为空时遍历停止
mostRight = head.left; //mostRight是cur的左孩子
if (mostRight != null) {//有左子树,如果没有,1)就把指针指向右孩子
while (mostRight.right != null && mostRight.right != cur) {
mostRight = mostRight.right;//找到左子树上最有的节点
}
//mostRight变成了cur左子树上最右的节点
if (mostRight.right == null) {// 2).a 如果左子树的最右节点的右指针为空,让其指向cur,然后cur向左移动(cur = cur.left)
System.out.println(cur.value);//第一次来到cur,打印。
mostRight.right = cur;
cur = cur.left;
continue;
} else {//mostRight.right == cur 2).b 如果mostRgiht的右指针指向cur,让其指向null,然后cur向右移动(cur = cur.right)
mostRight.right = null;
}
}
if (cur.value <= preValue) {
return false;
}
preValue = cur.value;
cur = cur.right;
}
return true;
}