给定一个二进制搜索树(BST)和一个正整数k,请在二进制搜索树中找到第k个最小的元素。
例如,在下面的BST中,如果k = 3,则输出应为10,如果k = 5,则输出应为14。
在本文中,我们讨论了两种方法,在本文中,讨论了一种方法。所有以前的方法都需要额外的空间。如何在没有多余空间的情况下找到第k个最大元素?
这个想法是使用Morris Traversal。在此遍历中,我们首先创建到Inorder后继程序的链接,并使用这些链接打印数据,最后还原所做的更改以还原原始树。有关更多详细信息,请参见此内容。
以下是该想法的实现。
C++
// C++ program to find k'th largest element in BST
#include
using namespace std;
// A BST node
struct Node
{
int key;
Node *left, *right;
};
// A function to find
int KSmallestUsingMorris(Node *root, int k)
{
// Count to iterate over elements till we
// get the kth smallest number
int count = 0;
int ksmall = INT_MIN; // store the Kth smallest
Node *curr = root; // to store the current node
while (curr != NULL)
{
// Like Morris traversal if current does
// not have left child rather than printing
// as we did in inorder, we will just
// increment the count as the number will
// be in an increasing order
if (curr->left == NULL)
{
count++;
// if count is equal to K then we found the
// kth smallest, so store it in ksmall
if (count==k)
ksmall = curr->key;
// go to current's right child
curr = curr->right;
}
else
{
// we create links to Inorder Successor and
// count using these links
Node *pre = curr->left;
while (pre->right != NULL && pre->right != curr)
pre = pre->right;
// building links
if (pre->right==NULL)
{
//link made to Inorder Successor
pre->right = curr;
curr = curr->left;
}
// While breaking the links in so made temporary
// threaded tree we will check for the K smallest
// condition
else
{
// Revert the changes made in if part (break link
// from the Inorder Successor)
pre->right = NULL;
count++;
// If count is equal to K then we found
// the kth smallest and so store it in ksmall
if (count==k)
ksmall = curr->key;
curr = curr->right;
}
}
}
return ksmall; //return the found value
}
// A utility function to create a new BST node
Node *newNode(int item)
{
Node *temp = new Node;
temp->key = item;
temp->left = temp->right = NULL;
return temp;
}
/* A utility function to insert a new node with given key in BST */
Node* insert(Node* node, int key)
{
/* If the tree is empty, return a new node */
if (node == NULL) return newNode(key);
/* Otherwise, recur down the tree */
if (key < node->key)
node->left = insert(node->left, key);
else if (key > node->key)
node->right = insert(node->right, key);
/* return the (unchanged) node pointer */
return node;
}
// Driver Program to test above functions
int main()
{
/* Let us create following BST
50
/ \
30 70
/ \ / \
20 40 60 80 */
Node *root = NULL;
root = insert(root, 50);
insert(root, 30);
insert(root, 20);
insert(root, 40);
insert(root, 70);
insert(root, 60);
insert(root, 80);
for (int k=1; k<=7; k++)
cout << KSmallestUsingMorris(root, k) << " ";
return 0;
}
Java
// Java program to find k'th largest element in BST
import java.util.*;
class GfG {
// A BST node
static class Node
{
int key;
Node left, right;
}
// A function to find
static int KSmallestUsingMorris(Node root, int k)
{
// Count to iterate over elements till we
// get the kth smallest number
int count = 0;
int ksmall = Integer.MIN_VALUE; // store the Kth smallest
Node curr = root; // to store the current node
while (curr != null)
{
// Like Morris traversal if current does
// not have left child rather than printing
// as we did in inorder, we will just
// increment the count as the number will
// be in an increasing order
if (curr.left == null)
{
count++;
// if count is equal to K then we found the
// kth smallest, so store it in ksmall
if (count==k)
ksmall = curr.key;
// go to current's right child
curr = curr.right;
}
else
{
// we create links to Inorder Successor and
// count using these links
Node pre = curr.left;
while (pre.right != null && pre.right != curr)
pre = pre.right;
// building links
if (pre.right== null)
{
//link made to Inorder Successor
pre.right = curr;
curr = curr.left;
}
// While breaking the links in so made temporary
// threaded tree we will check for the K smallest
// condition
else
{
// Revert the changes made in if part (break link
// from the Inorder Successor)
pre.right = null;
count++;
// If count is equal to K then we found
// the kth smallest and so store it in ksmall
if (count==k)
ksmall = curr.key;
curr = curr.right;
}
}
}
return ksmall; //return the found value
}
// A utility function to create a new BST node
static Node newNode(int item)
{
Node temp = new Node();
temp.key = item;
temp.left = null;
temp.right = null;
return temp;
}
/* A utility function to insert a new node with given key in BST */
static Node insert(Node node, int key)
{
/* If the tree is empty, return a new node */
if (node == null) return newNode(key);
/* Otherwise, recur down the tree */
if (key < node.key)
node.left = insert(node.left, key);
else if (key > node.key)
node.right = insert(node.right, key);
/* return the (unchanged) node pointer */
return node;
}
// Driver Program to test above functions
public static void main(String[] args)
{
/* Let us create following BST
50
/ \
30 70
/ \ / \
20 40 60 80 */
Node root = null;
root = insert(root, 50);
insert(root, 30);
insert(root, 20);
insert(root, 40);
insert(root, 70);
insert(root, 60);
insert(root, 80);
for (int k=1; k<=7; k++)
System.out.print(KSmallestUsingMorris(root, k) + " ");
}
}
Python3
# Python 3 program to find k'th
# largest element in BST
# A BST node
class Node:
# Constructor to create a new node
def __init__(self, data):
self.key = data
self.left = None
self.right = None
# A function to find
def KSmallestUsingMorris(root, k):
# Count to iterate over elements
# till we get the kth smallest number
count = 0
ksmall = -9999999999 # store the Kth smallest
curr = root # to store the current node
while curr != None:
# Like Morris traversal if current does
# not have left child rather than
# printing as we did in inorder, we
# will just increment the count as the
# number will be in an increasing order
if curr.left == None:
count += 1
# if count is equal to K then we
# found the kth smallest, so store
# it in ksmall
if count == k:
ksmall = curr.key
# go to current's right child
curr = curr.right
else:
# we create links to Inorder Successor
# and count using these links
pre = curr.left
while (pre.right != None and
pre.right != curr):
pre = pre.right
# building links
if pre.right == None:
# link made to Inorder Successor
pre.right = curr
curr = curr.left
# While breaking the links in so made
# temporary threaded tree we will check
# for the K smallest condition
else:
# Revert the changes made in if part
# (break link from the Inorder Successor)
pre.right = None
count += 1
# If count is equal to K then we
# found the kth smallest and so
# store it in ksmall
if count == k:
ksmall = curr.key
curr = curr.right
return ksmall # return the found value
# A utility function to insert a new
# node with given key in BST
def insert(node, key):
# If the tree is empty,
# return a new node
if node == None:
return Node(key)
# Otherwise, recur down the tree
if key < node.key:
node.left = insert(node.left, key)
elif key > node.key:
node.right = insert(node.right, key)
# return the (unchanged) node pointer
return node
# Driver Code
if __name__ == '__main__':
# Let us create following BST
# 50
# / \
# 30 70
# / \ / \
# 20 40 60 80
root = None
root = insert(root, 50)
insert(root, 30)
insert(root, 20)
insert(root, 40)
insert(root, 70)
insert(root, 60)
insert(root, 80)
for k in range(1,8):
print(KSmallestUsingMorris(root, k),
end = " ")
# This code is contributed by PranchalK
C#
// C# program to find k'th largest element in BST
using System;
class GfG
{
// A BST node
public class Node
{
public int key;
public Node left, right;
}
// A function to find
static int KSmallestUsingMorris(Node root, int k)
{
// Count to iterate over elements till we
// get the kth smallest number
int count = 0;
int ksmall = int.MinValue; // store the Kth smallest
Node curr = root; // to store the current node
while (curr != null)
{
// Like Morris traversal if current does
// not have left child rather than printing
// as we did in inorder, we will just
// increment the count as the number will
// be in an increasing order
if (curr.left == null)
{
count++;
// if count is equal to K then we found the
// kth smallest, so store it in ksmall
if (count==k)
ksmall = curr.key;
// go to current's right child
curr = curr.right;
}
else
{
// we create links to Inorder Successor and
// count using these links
Node pre = curr.left;
while (pre.right != null && pre.right != curr)
pre = pre.right;
// building links
if (pre.right == null)
{
// link made to Inorder Successor
pre.right = curr;
curr = curr.left;
}
// While breaking the links in so made temporary
// threaded tree we will check for the K smallest
// condition
else
{
// Revert the changes made in if part (break link
// from the Inorder Successor)
pre.right = null;
count++;
// If count is equal to K then we found
// the kth smallest and so store it in ksmall
if (count == k)
ksmall = curr.key;
curr = curr.right;
}
}
}
return ksmall; //return the found value
}
// A utility function to create a new BST node
static Node newNode(int item)
{
Node temp = new Node();
temp.key = item;
temp.left = null;
temp.right = null;
return temp;
}
/* A utility function to insert a new node with given key in BST */
static Node insert(Node node, int key)
{
/* If the tree is empty, return a new node */
if (node == null) return newNode(key);
/* Otherwise, recur down the tree */
if (key < node.key)
node.left = insert(node.left, key);
else if (key > node.key)
node.right = insert(node.right, key);
/* return the (unchanged) node pointer */
return node;
}
// Driver Program to test above functions
public static void Main(String[] args)
{
/* Let us create following BST
50
/ \
30 70
/ \ / \
20 40 60 80 */
Node root = null;
root = insert(root, 50);
insert(root, 30);
insert(root, 20);
insert(root, 40);
insert(root, 70);
insert(root, 60);
insert(root, 80);
for (int k = 1; k <= 7; k++)
Console.Write(KSmallestUsingMorris(root, k) + " ");
}
}
// This code has been contributed by 29AjayKumar
输出:
20 30 40 50 60 70 80