给定两个值n1和n2(其中n1 先决条件:遍历Morris |线程二叉树 顺序遍历使用递归或占用O(n)空间的堆栈/队列。但是,有一种有效的方法可以使用基于线程二叉树的Morris遍历进行有序树遍历。 Morris遍历不使用递归或堆栈/队列,而只是将一些重要信息存储在浪费的NULL指针中。莫里斯遍历消耗不变的额外内存O(1),因为它不使用递归或堆栈/队列。因此,在本教程中介绍的算法中,我们将使用Morris遍历进行有序遍历,以在给定范围内打印BST的键,这是有效的存储方式。 线程二叉树的概念很简单,它们在浪费的NULL指针中存储了一些有用的信息。在具有n个节点的普通二叉树中,n + 1个NULL指针浪费了内存。 方法: Morris遍历是一种非常好的内存有效技术,可以在不基于线程二叉树的常量内存O(1)中使用堆栈或递归的情况下进行树遍历。 Morris遍历可用于解决使用有序树遍历的问题,尤其是在顺序统计中,例如BST中的第K个最大元素,BST中的第K个最小元素等。因此,在这里Morris遍历将成为更有效的有序方法在常量O(1)中进行遍历,而无需使用任何堆栈或递归。 算法 下面是上述方法的实现。 时间复杂度: O(n)1) Initialize Current as root.
2) While current is not NULL :
2.1) If current has no left child
a) Check if current lies between n1 and n2.
1)If so, then visit the current node.
b)Otherwise, Move to the right child of current.
3) Else, here we have 2 cases:
a) Find the inorder predecessor of current node.
Inorder predecessor is the right most node
in the left subtree or left child itself.
b) If the right child of the inorder predecessor is NULL:
1) Set current as the right child of its inorder predecessor.
2) Move current node to its left child.
c) Else, if the threaded link between the current node
and it's inorder predecessor already exists :
1) Set right pointer of the inorder predecessor as NULL.
2) Again check if current node lies between n1 and n2.
a)If so, then visit the current node.
3)Now move current to it's right child.
C++
// CPP code to print BST keys in given Range in
// constant space using Morris traversal.
#include
Java
// Java code to print BST keys in given Range in
// constant space using Morris traversal.
class GfG {
static class node {
int data;
node left, right;
}
// Function to print the keys in range
static void RangeTraversal(node root, int n1, int n2)
{
if (root == null)
return;
node curr = root;
while (curr != null) {
if (curr.left == null)
{
// check if current node
// lies between n1 and n2
if (curr.data <= n2 && curr.data >= n1)
{
System.out.print(curr.data + " ");
}
curr = curr.right;
}
else {
node pre = curr.left;
// finding the inorder predecessor-
// inorder predecessor is the right
// most in left subtree or the left
// child, i.e in BST it is the
// maximum(right most) in left subtree.
while (pre.right != null && pre.right != curr)
pre = pre.right;
if (pre.right == null)
{
pre.right = curr;
curr = curr.left;
}
else {
pre.right = null;
// check if current node lies
// between n1 and n2
if (curr.data <= n2 && curr.data >= n1)
{
System.out.print(curr.data + " ");
}
curr = curr.right;
}
}
}
}
// Helper function to create a new node
static node newNode(int data)
{
node temp = new node();
temp.data = data;
temp.right = null;
temp.left = null;
return temp;
}
// Driver Code
public static void main(String[] args)
{
/* Constructed binary tree is
4
/ \
2 7
/ \ / \
1 3 6 10
*/
node root = newNode(4);
root.left = newNode(2);
root.right = newNode(7);
root.left.left = newNode(1);
root.left.right = newNode(3);
root.right.left = newNode(6);
root.right.right = newNode(10);
RangeTraversal(root, 4, 12);
}
}
Python3
# Python3 code to print BST keys in given Range
# in constant space using Morris traversal.
# Helper function to create a new node
class newNode:
# Constructor to create a new node
def __init__(self, data):
self.data = data
self.left = None
self.right = None
# Function to print the keys in range
def RangeTraversal(root, n1, n2):
if root == None:
return
curr = root
while curr:
if curr.left == None:
# check if current node lies
# between n1 and n2
if curr.data <= n2 and curr.data >= n1:
print(curr.data, end = " ")
curr = curr.right
else:
pre = curr.left
# finding the inorder predecessor-
# inorder predecessor is the right
# most in left subtree or the left
# child, i.e in BST it is the
# maximum(right most) in left subtree.
while (pre.right != None and
pre.right != curr):
pre = pre.right
if pre.right == None:
pre.right = curr;
curr = curr.left
else:
pre.right = None
# check if current node lies
# between n1 and n2
if curr.data <= n2 and curr.data >= n1:
print(curr.data, end = " ")
curr = curr.right
# Driver Code
if __name__ == '__main__':
# Constructed binary tree is
# 4
# / \
# 2 7
# / \ / \
# 1 3 6 10
root = newNode(4)
root.left = newNode(2)
root.right = newNode(7)
root.left.left = newNode(1)
root.left.right = newNode(3)
root.right.left = newNode(6)
root.right.right = newNode(10)
RangeTraversal(root, 4, 12)
# This code is contributed by PranchalK
C#
// C# code to print BST keys in given Range in
// constant space using Morris traversal.
using System;
public class GfG
{
public class node
{
public int data;
public node left, right;
}
// Function to print the keys in range
static void RangeTraversal(node root, int n1, int n2)
{
if (root == null)
return;
node curr = root;
while (curr != null)
{
if (curr.left == null)
{
// check if current node
// lies between n1 and n2
if (curr.data <= n2 && curr.data >= n1)
{
Console.Write(curr.data + " ");
}
curr = curr.right;
}
else
{
node pre = curr.left;
// finding the inorder predecessor-
// inorder predecessor is the right
// most in left subtree or the left
// child, i.e in BST it is the
// maximum(right most) in left subtree.
while (pre.right != null && pre.right != curr)
pre = pre.right;
if (pre.right == null)
{
pre.right = curr;
curr = curr.left;
}
else
{
pre.right = null;
// check if current node lies
// between n1 and n2
if (curr.data <= n2 && curr.data >= n1)
{
Console.Write(curr.data + " ");
}
curr = curr.right;
}
}
}
}
// Helper function to create a new node
static node newNode(int data)
{
node temp = new node();
temp.data = data;
temp.right = null;
temp.left = null;
return temp;
}
// Driver Code
public static void Main(String[] args)
{
/* Constructed binary tree is
4
/ \
2 7
/ \ / \
1 3 6 10
*/
node root = newNode(4);
root.left = newNode(2);
root.right = newNode(7);
root.left.left = newNode(1);
root.left.right = newNode(3);
root.right.left = newNode(6);
root.right.right = newNode(10);
RangeTraversal(root, 4, 12);
}
}
// This code has been contributed by 29AjayKumar
4 6 7 10
辅助空间: O(1)