线程二叉树节点如下所示。
CPP
struct Node {
struct Node *left, *right;
int info;
// True if left pointer points to predecessor
// in Inorder Traversal
bool lthread;
// True if right pointer points to predecessor
// in Inorder Traversal
bool rthread;
};
Java
static class Node {
Node left, right;
int info;
// True if left pointer points to predecessor
// in Inorder Traversal
boolean lthread;
// True if right pointer points to predecessor
// in Inorder Traversal
boolean rthread;
};
// This code contributed by aashish1995
C#
public
class Node
{
public
Node left,
right;
public
int info;
// True if left pointer points to predecessor
// in Inorder Traversal
public
bool lthread;
// True if right pointer points to predecessor
// in Inorder Traversal
public
bool rthread;
};
// This code is contributed by aashish1995
CPP
// Deletes a key from threaded BST with given root and
// returns new root of BST.
struct Node* delThreadedBST(struct Node* root, int dkey)
{
// Initialize parent as NULL and ptrent
// Node as root.
struct Node *par = NULL, *ptr = root;
// Set true if key is found
int found = 0;
// Search key in BST : find Node and its
// parent.
while (ptr != NULL) {
if (dkey == ptr->info) {
found = 1;
break;
}
par = ptr;
if (dkey < ptr->info) {
if (ptr->lthread == false)
ptr = ptr->left;
else
break;
}
else {
if (ptr->rthread == false)
ptr = ptr->right;
else
break;
}
}
if (found == 0)
printf("dkey not present in tree\n");
// Two Children
else if (ptr->lthread == false && ptr->rthread == false)
root = caseC(root, par, ptr);
// Only Left Child
else if (ptr->lthread == false)
root = caseB(root, par, ptr);
// Only Right Child
else if (ptr->rthread == false)
root = caseB(root, par, ptr);
// No child
else
root = caseA(root, par, ptr);
return root;
}
CPP
// Here 'par' is pointer to parent Node and 'ptr' is
// pointer to current Node.
struct Node* caseA(struct Node* root, struct Node* par,
struct Node* ptr)
{
// If Node to be deleted is root
if (par == NULL)
root = NULL;
// If Node to be deleted is left
// of its parent
else if (ptr == par->left) {
par->lthread = true;
par->left = ptr->left;
}
else {
par->rthread = true;
par->right = ptr->right;
}
// Free memory and return new root
free(ptr);
return root;
}
Java
// Here 'par' is pointer to parent Node and 'ptr' is
// pointer to current Node.
Node caseA(Node root, Node par,
Node ptr)
{
// If Node to be deleted is root
if (par == null)
root = null;
// If Node to be deleted is left
// of its parent
else if (ptr == par.left) {
par.lthread = true;
par.left = ptr.left;
}
else {
par.rthread = true;
par.right = ptr.right;
}
return root;
}
// This code is contributed by gauravrajput1
CPP
// Here 'par' is pointer to parent Node and 'ptr' is
// pointer to current Node.
struct Node* caseB(struct Node* root, struct Node* par,
struct Node* ptr)
{
struct Node* child;
// Initialize child Node to be deleted has
// left child.
if (ptr->lthread == false)
child = ptr->left;
// Node to be deleted has right child.
else
child = ptr->right;
// Node to be deleted is root Node.
if (par == NULL)
root = child;
// Node is left child of its parent.
else if (ptr == par->left)
par->left = child;
else
par->right = child;
// Find successor and predecessor
Node* s = inSucc(ptr);
Node* p = inPred(ptr);
// If ptr has left subtree.
if (ptr->lthread == false)
p->right = s;
// If ptr has right subtree.
else {
if (ptr->rthread == false)
s->left = p;
}
free(ptr);
return root;
}
Java
// Here 'par' is pointer to parent Node and 'ptr' is
// pointer to current Node.
static Node caseB(Node root, Node par,
Node ptr)
{
Node child;
// Initialize child Node to be deleted has
// left child.
if (ptr.lthread == false)
child = ptr.left;
// Node to be deleted has right child.
else
child = ptr.right;
// Node to be deleted is root Node.
if (par == null)
root = child;
// Node is left child of its parent.
else if (ptr == par.left)
par.left = child;
else
par.right = child;
// Find successor and predecessor
Node s = inSucc(ptr);
Node p = inPred(ptr);
// If ptr has left subtree.
if (ptr.lthread == false)
p.right = s;
// If ptr has right subtree.
else {
if (ptr.rthread == false)
s.left = p;
}
return root;
}
// This code is contributed by gauravrajput1
CPP
// Here 'par' is pointer to parent Node and 'ptr' is
// pointer to current Node.
struct Node* caseC(struct Node* root, struct Node* par,
struct Node* ptr)
{
// Find inorder successor and its parent.
struct Node* parsucc = ptr;
struct Node* succ = ptr->right;
// Find leftmost child of successor
while (succ->left != NULL) {
parsucc = succ;
succ = succ->left;
}
ptr->info = succ->info;
if (succ->lthread == true && succ->rthread == true)
root = caseA(root, parsucc, succ);
else
root = caseB(root, parsucc, succ);
return root;
}
C++
// Complete C++ program to demonstrate deletion
// in threaded BST
#include
using namespace std;
struct Node {
struct Node *left, *right;
int info;
// True if left pointer points to predecessor
// in Inorder Traversal
bool lthread;
// True if right pointer points to predecessor
// in Inorder Traversal
bool rthread;
};
// Insert a Node in Binary Threaded Tree
struct Node* insert(struct Node* root, int ikey)
{
// Searching for a Node with given value
Node* ptr = root;
Node* par = NULL; // Parent of key to be inserted
while (ptr != NULL) {
// If key already exists, return
if (ikey == (ptr->info)) {
printf("Duplicate Key !\n");
return root;
}
par = ptr; // Update parent pointer
// Moving on left subtree.
if (ikey < ptr->info) {
if (ptr->lthread == false)
ptr = ptr->left;
else
break;
}
// Moving on right subtree.
else {
if (ptr->rthread == false)
ptr = ptr->right;
else
break;
}
}
// Create a new Node
Node* tmp = new Node;
tmp->info = ikey;
tmp->lthread = true;
tmp->rthread = true;
if (par == NULL) {
root = tmp;
tmp->left = NULL;
tmp->right = NULL;
}
else if (ikey < (par->info)) {
tmp->left = par->left;
tmp->right = par;
par->lthread = false;
par->left = tmp;
}
else {
tmp->left = par;
tmp->right = par->right;
par->rthread = false;
par->right = tmp;
}
return root;
}
// Returns inorder successor using left
// and right children (Used in deletion)
struct Node* inSucc(struct Node* ptr)
{
if (ptr->rthread == true)
return ptr->right;
ptr = ptr->right;
while (ptr->lthread == false)
ptr = ptr->left;
return ptr;
}
// Returns inorder successor using rthread
// (Used in inorder)
struct Node* inorderSuccessor(struct Node* ptr)
{
// If rthread is set, we can quickly find
if (ptr->rthread == true)
return ptr->right;
// Else return leftmost child of right subtree
ptr = ptr->right;
while (ptr->lthread == false)
ptr = ptr->left;
return ptr;
}
// Printing the threaded tree
void inorder(struct Node* root)
{
if (root == NULL)
printf("Tree is empty");
// Reach leftmost Node
struct Node* ptr = root;
while (ptr->lthread == false)
ptr = ptr->left;
// One by one print successors
while (ptr != NULL) {
printf("%d ", ptr->info);
ptr = inorderSuccessor(ptr);
}
}
struct Node* inPred(struct Node* ptr)
{
if (ptr->lthread == true)
return ptr->left;
ptr = ptr->left;
while (ptr->rthread == false)
ptr = ptr->right;
return ptr;
}
// Here 'par' is pointer to parent Node and 'ptr' is
// pointer to current Node.
struct Node* caseA(struct Node* root, struct Node* par,
struct Node* ptr)
{
// If Node to be deleted is root
if (par == NULL)
root = NULL;
// If Node to be deleted is left
// of its parent
else if (ptr == par->left) {
par->lthread = true;
par->left = ptr->left;
}
else {
par->rthread = true;
par->right = ptr->right;
}
// Free memory and return new root
free(ptr);
return root;
}
// Here 'par' is pointer to parent Node and 'ptr' is
// pointer to current Node.
struct Node* caseB(struct Node* root, struct Node* par,
struct Node* ptr)
{
struct Node* child;
// Initialize child Node to be deleted has
// left child.
if (ptr->lthread == false)
child = ptr->left;
// Node to be deleted has right child.
else
child = ptr->right;
// Node to be deleted is root Node.
if (par == NULL)
root = child;
// Node is left child of its parent.
else if (ptr == par->left)
par->left = child;
else
par->right = child;
// Find successor and predecessor
Node* s = inSucc(ptr);
Node* p = inPred(ptr);
// If ptr has left subtree.
if (ptr->lthread == false)
p->right = s;
// If ptr has right subtree.
else {
if (ptr->rthread == false)
s->left = p;
}
free(ptr);
return root;
}
// Here 'par' is pointer to parent Node and 'ptr' is
// pointer to current Node.
struct Node* caseC(struct Node* root, struct Node* par,
struct Node* ptr)
{
// Find inorder successor and its parent.
struct Node* parsucc = ptr;
struct Node* succ = ptr->right;
// Find leftmost child of successor
while (succ->lthread==false) {
parsucc = succ;
succ = succ->left;
}
ptr->info = succ->info;
if (succ->lthread == true && succ->rthread == true)
root = caseA(root, parsucc, succ);
else
root = caseB(root, parsucc, succ);
return root;
}
// Deletes a key from threaded BST with given root and
// returns new root of BST.
struct Node* delThreadedBST(struct Node* root, int dkey)
{
// Initialize parent as NULL and ptrent
// Node as root.
struct Node *par = NULL, *ptr = root;
// Set true if key is found
int found = 0;
// Search key in BST : find Node and its
// parent.
while (ptr != NULL) {
if (dkey == ptr->info) {
found = 1;
break;
}
par = ptr;
if (dkey < ptr->info) {
if (ptr->lthread == false)
ptr = ptr->left;
else
break;
}
else {
if (ptr->rthread == false)
ptr = ptr->right;
else
break;
}
}
if (found == 0)
printf("dkey not present in tree\n");
// Two Children
else if (ptr->lthread == false && ptr->rthread == false)
root = caseC(root, par, ptr);
// Only Left Child
else if (ptr->lthread == false)
root = caseB(root, par, ptr);
// Only Right Child
else if (ptr->rthread == false)
root = caseB(root, par, ptr);
// No child
else
root = caseA(root, par, ptr);
return root;
}
// Driver Program
int main()
{
struct Node* root = NULL;
root = insert(root, 20);
root = insert(root, 10);
root = insert(root, 30);
root = insert(root, 5);
root = insert(root, 16);
root = insert(root, 14);
root = insert(root, 17);
root = insert(root, 13);
root = delThreadedBST(root, 20);
inorder(root);
return 0;
}
Java
// Complete Java program to demonstrate deletion
// in threaded BST
import java.util.*;
class solution {
static class Node {
Node left, right;
int info;
// True if left pointer points to predecessor
// in Inorder Traversal
boolean lthread;
// True if right pointer points to predecessor
// in Inorder Traversal
boolean rthread;
};
// Insert a Node in Binary Threaded Tree
static Node insert(Node root, int ikey)
{
// Searching for a Node with given value
Node ptr = root;
Node par = null; // Parent of key to be inserted
while (ptr != null) {
// If key already exists, return
if (ikey == (ptr.info)) {
System.out.printf("Duplicate Key !\n");
return root;
}
par = ptr; // Update parent pointer
// Moving on left subtree.
if (ikey < ptr.info) {
if (ptr.lthread == false)
ptr = ptr.left;
else
break;
}
// Moving on right subtree.
else {
if (ptr.rthread == false)
ptr = ptr.right;
else
break;
}
}
// Create a new Node
Node tmp = new Node();
tmp.info = ikey;
tmp.lthread = true;
tmp.rthread = true;
if (par == null) {
root = tmp;
tmp.left = null;
tmp.right = null;
}
else if (ikey < (par.info)) {
tmp.left = par.left;
tmp.right = par;
par.lthread = false;
par.left = tmp;
}
else {
tmp.left = par;
tmp.right = par.right;
par.rthread = false;
par.right = tmp;
}
return root;
}
// Returns inorder successor using left
// and right children (Used in deletion)
static Node inSucc(Node ptr)
{
if (ptr.rthread == true)
return ptr.right;
ptr = ptr.right;
while (ptr.lthread == false)
ptr = ptr.left;
return ptr;
}
// Returns inorder successor using rthread
// (Used in inorder)
static Node inorderSuccessor(Node ptr)
{
// If rthread is set, we can quickly find
if (ptr.rthread == true)
return ptr.right;
// Else return leftmost child of right subtree
ptr = ptr.right;
while (ptr.lthread == false)
ptr = ptr.left;
return ptr;
}
// Printing the threaded tree
static void inorder(Node root)
{
if (root == null)
System.out.printf("Tree is empty");
// Reach leftmost Node
Node ptr = root;
while (ptr.lthread == false)
ptr = ptr.left;
// One by one print successors
while (ptr != null) {
System.out.printf("%d ", ptr.info);
ptr = inorderSuccessor(ptr);
}
}
static Node inPred(Node ptr)
{
if (ptr.lthread == true)
return ptr.left;
ptr = ptr.left;
while (ptr.rthread == false)
ptr = ptr.right;
return ptr;
}
// Here 'par' is pointer to parent Node and 'ptr' is
// pointer to current Node.
static Node caseA(Node root, Node par,
Node ptr)
{
// If Node to be deleted is root
if (par == null)
root = null;
// If Node to be deleted is left
// of its parent
else if (ptr == par.left) {
par.lthread = true;
par.left = ptr.left;
}
else {
par.rthread = true;
par.right = ptr.right;
}
return root;
}
// Here 'par' is pointer to parent Node and 'ptr' is
// pointer to current Node.
static Node caseB(Node root, Node par,
Node ptr)
{
Node child;
// Initialize child Node to be deleted has
// left child.
if (ptr.lthread == false)
child = ptr.left;
// Node to be deleted has right child.
else
child = ptr.right;
// Node to be deleted is root Node.
if (par == null)
root = child;
// Node is left child of its parent.
else if (ptr == par.left)
par.left = child;
else
par.right = child;
// Find successor and predecessor
Node s = inSucc(ptr);
Node p = inPred(ptr);
// If ptr has left subtree.
if (ptr.lthread == false)
p.right = s;
// If ptr has right subtree.
else {
if (ptr.rthread == false)
s.left = p;
}
return root;
}
// Here 'par' is pointer to parent Node and 'ptr' is
// pointer to current Node.
static Node caseC(Node root, Node par,
Node ptr)
{
// Find inorder successor and its parent.
Node parsucc = ptr;
Node succ = ptr.right;
// Find leftmost child of successor
while (succ.lthread == false) {
parsucc = succ;
succ = succ.left;
}
ptr.info = succ.info;
if (succ.lthread == true && succ.rthread == true)
root = caseA(root, parsucc, succ);
else
root = caseB(root, parsucc, succ);
return root;
}
// Deletes a key from threaded BST with given root and
// returns new root of BST.
static Node delThreadedBST(Node root, int dkey)
{
// Initialize parent as null and ptrent
// Node as root.
Node par = null, ptr = root;
// Set true if key is found
int found = 0;
// Search key in BST : find Node and its
// parent.
while (ptr != null) {
if (dkey == ptr.info) {
found = 1;
break;
}
par = ptr;
if (dkey < ptr.info) {
if (ptr.lthread == false)
ptr = ptr.left;
else
break;
}
else {
if (ptr.rthread == false)
ptr = ptr.right;
else
break;
}
}
if (found == 0)
System.out.printf("dkey not present in tree\n");
// Two Children
else if (ptr.lthread == false && ptr.rthread == false)
root = caseC(root, par, ptr);
// Only Left Child
else if (ptr.lthread == false)
root = caseB(root, par, ptr);
// Only Right Child
else if (ptr.rthread == false)
root = caseB(root, par, ptr);
// No child
else
root = caseA(root, par, ptr);
return root;
}
// Driver Program
public static void main(String args[])
{
Node root = null;
root = insert(root, 20);
root = insert(root, 10);
root = insert(root, 30);
root = insert(root, 5);
root = insert(root, 16);
root = insert(root, 14);
root = insert(root, 17);
root = insert(root, 13);
root = delThreadedBST(root, 20);
inorder(root);
}
}
// This code is contributed by Arnab Kundu
C#
// Complete C# program to demonstrate deletion
// in threaded BST
using System;
class GFG {
public class Node {
public Node left, right;
public int info;
// True if left pointer points to predecessor
// in Inorder Traversal
public bool lthread;
// True if right pointer points to predecessor
// in Inorder Traversal
public bool rthread;
};
// Insert a Node in Binary Threaded Tree
static Node insert(Node root, int ikey)
{
// Searching for a Node with given value
Node ptr = root;
Node par = null; // Parent of key to be inserted
while (ptr != null) {
// If key already exists, return
if (ikey == (ptr.info)) {
Console.Write("Duplicate Key !\n");
return root;
}
par = ptr; // Update parent pointer
// Moving on left subtree.
if (ikey < ptr.info) {
if (ptr.lthread == false)
ptr = ptr.left;
else
break;
}
// Moving on right subtree.
else {
if (ptr.rthread == false)
ptr = ptr.right;
else
break;
}
}
// Create a new Node
Node tmp = new Node();
tmp.info = ikey;
tmp.lthread = true;
tmp.rthread = true;
if (par == null) {
root = tmp;
tmp.left = null;
tmp.right = null;
}
else if (ikey < (par.info)) {
tmp.left = par.left;
tmp.right = par;
par.lthread = false;
par.left = tmp;
}
else {
tmp.left = par;
tmp.right = par.right;
par.rthread = false;
par.right = tmp;
}
return root;
}
// Returns inorder successor using left
// and right children (Used in deletion)
static Node inSucc(Node ptr)
{
if (ptr.rthread == true)
return ptr.right;
ptr = ptr.right;
while (ptr.lthread == false)
ptr = ptr.left;
return ptr;
}
// Returns inorder successor using rthread
// (Used in inorder)
static Node inorderSuccessor(Node ptr)
{
// If rthread is set, we can quickly find
if (ptr.rthread == true)
return ptr.right;
// Else return leftmost child of right subtree
ptr = ptr.right;
while (ptr.lthread == false)
ptr = ptr.left;
return ptr;
}
// Printing the threaded tree
static void inorder(Node root)
{
if (root == null)
Console.Write("Tree is empty");
// Reach leftmost Node
Node ptr = root;
while (ptr.lthread == false)
ptr = ptr.left;
// One by one print successors
while (ptr != null) {
Console.Write("{0} ", ptr.info);
ptr = inorderSuccessor(ptr);
}
}
static Node inPred(Node ptr)
{
if (ptr.lthread == true)
return ptr.left;
ptr = ptr.left;
while (ptr.rthread == false)
ptr = ptr.right;
return ptr;
}
// Here 'par' is pointer to parent Node and 'ptr' is
// pointer to current Node.
static Node caseA(Node root, Node par,
Node ptr)
{
// If Node to be deleted is root
if (par == null)
root = null;
// If Node to be deleted is left
// of its parent
else if (ptr == par.left) {
par.lthread = true;
par.left = ptr.left;
}
else {
par.rthread = true;
par.right = ptr.right;
}
return root;
}
// Here 'par' is pointer to parent Node and 'ptr' is
// pointer to current Node.
static Node caseB(Node root, Node par,
Node ptr)
{
Node child;
// Initialize child Node to be deleted has
// left child.
if (ptr.lthread == false)
child = ptr.left;
// Node to be deleted has right child.
else
child = ptr.right;
// Node to be deleted is root Node.
if (par == null)
root = child;
// Node is left child of its parent.
else if (ptr == par.left)
par.left = child;
else
par.right = child;
// Find successor and predecessor
Node s = inSucc(ptr);
Node p = inPred(ptr);
// If ptr has left subtree.
if (ptr.lthread == false)
p.right = s;
// If ptr has right subtree.
else {
if (ptr.rthread == false)
s.left = p;
}
return root;
}
// Here 'par' is pointer to parent Node and 'ptr' is
// pointer to current Node.
static Node caseC(Node root, Node par,
Node ptr)
{
// Find inorder successor and its parent.
Node parsucc = ptr;
Node succ = ptr.right;
// Find leftmost child of successor
while (succ.lthread == false) {
parsucc = succ;
succ = succ.left;
}
ptr.info = succ.info;
if (succ.lthread == true && succ.rthread == true)
root = caseA(root, parsucc, succ);
else
root = caseB(root, parsucc, succ);
return root;
}
// Deletes a key from threaded BST with given root and
// returns new root of BST.
static Node delThreadedBST(Node root, int dkey)
{
// Initialize parent as null and ptrent
// Node as root.
Node par = null, ptr = root;
// Set true if key is found
int found = 0;
// Search key in BST : find Node and its
// parent.
while (ptr != null) {
if (dkey == ptr.info) {
found = 1;
break;
}
par = ptr;
if (dkey < ptr.info) {
if (ptr.lthread == false)
ptr = ptr.left;
else
break;
}
else {
if (ptr.rthread == false)
ptr = ptr.right;
else
break;
}
}
if (found == 0)
Console.Write("dkey not present in tree\n");
// Two Children
else if (ptr.lthread == false && ptr.rthread == false)
root = caseC(root, par, ptr);
// Only Left Child
else if (ptr.lthread == false)
root = caseB(root, par, ptr);
// Only Right Child
else if (ptr.rthread == false)
root = caseB(root, par, ptr);
// No child
else
root = caseA(root, par, ptr);
return root;
}
// Driver code
public static void Main(String[] args)
{
Node root = null;
root = insert(root, 20);
root = insert(root, 10);
root = insert(root, 30);
root = insert(root, 5);
root = insert(root, 16);
root = insert(root, 14);
root = insert(root, 17);
root = insert(root, 13);
root = delThreadedBST(root, 20);
inorder(root);
}
}
// This code has been contributed by 29AjayKumar
我们已经讨论了线程二叉搜索树的插入
在删除中,首先搜索要删除的密钥,然后有不同的情况用于删除在其中找到密钥的节点。
CPP
// Deletes a key from threaded BST with given root and
// returns new root of BST.
struct Node* delThreadedBST(struct Node* root, int dkey)
{
// Initialize parent as NULL and ptrent
// Node as root.
struct Node *par = NULL, *ptr = root;
// Set true if key is found
int found = 0;
// Search key in BST : find Node and its
// parent.
while (ptr != NULL) {
if (dkey == ptr->info) {
found = 1;
break;
}
par = ptr;
if (dkey < ptr->info) {
if (ptr->lthread == false)
ptr = ptr->left;
else
break;
}
else {
if (ptr->rthread == false)
ptr = ptr->right;
else
break;
}
}
if (found == 0)
printf("dkey not present in tree\n");
// Two Children
else if (ptr->lthread == false && ptr->rthread == false)
root = caseC(root, par, ptr);
// Only Left Child
else if (ptr->lthread == false)
root = caseB(root, par, ptr);
// Only Right Child
else if (ptr->rthread == false)
root = caseB(root, par, ptr);
// No child
else
root = caseA(root, par, ptr);
return root;
}
情况A:需要删除叶节点
在BST中,为了删除叶节点,将父节点的左或右指针设置为NULL。在这里,不是将指针设置为NULL,而是创建了一个线程。
如果要删除的叶节点是其父节点的左子节点,则在删除后,父节点的左指针应成为一个指向删除后其父节点的前身的线程。
par -> lthread = true;
par -> left = ptr -> left;
如果要删除的叶节点是其父节点的右子节点,则在删除后,父节点的右指针应成为指向其后继节点的线程。删除前为叶节点的有序后继节点的节点将成为删除后父节点的有序后继节点。
CPP
// Here 'par' is pointer to parent Node and 'ptr' is
// pointer to current Node.
struct Node* caseA(struct Node* root, struct Node* par,
struct Node* ptr)
{
// If Node to be deleted is root
if (par == NULL)
root = NULL;
// If Node to be deleted is left
// of its parent
else if (ptr == par->left) {
par->lthread = true;
par->left = ptr->left;
}
else {
par->rthread = true;
par->right = ptr->right;
}
// Free memory and return new root
free(ptr);
return root;
}
Java
// Here 'par' is pointer to parent Node and 'ptr' is
// pointer to current Node.
Node caseA(Node root, Node par,
Node ptr)
{
// If Node to be deleted is root
if (par == null)
root = null;
// If Node to be deleted is left
// of its parent
else if (ptr == par.left) {
par.lthread = true;
par.left = ptr.left;
}
else {
par.rthread = true;
par.right = ptr.right;
}
return root;
}
// This code is contributed by gauravrajput1
情况B:要删除的节点只有一个孩子
在像BST中一样删除节点后,将发现节点的有序后继者和有序前任者。
s = inSucc(ptr);
p = inPred(ptr);
如果要删除的节点具有左子树,则在删除后,其前任节点的右线程应指向其后继节点。
p->left = s;
在删除15之前,2是16的后继。在删除16之后,节点20成为15的后继,因此15的右线程将指向20。
如果要删除的节点具有右子树,则在删除后,其后继者的左线程应指向其前任者。
s->left = p;
在删除25之前是34的前继者,在34之前是30的后继者。在删除30之后,节点25成为34的前任,因此34的左线程将指向25。
CPP
// Here 'par' is pointer to parent Node and 'ptr' is
// pointer to current Node.
struct Node* caseB(struct Node* root, struct Node* par,
struct Node* ptr)
{
struct Node* child;
// Initialize child Node to be deleted has
// left child.
if (ptr->lthread == false)
child = ptr->left;
// Node to be deleted has right child.
else
child = ptr->right;
// Node to be deleted is root Node.
if (par == NULL)
root = child;
// Node is left child of its parent.
else if (ptr == par->left)
par->left = child;
else
par->right = child;
// Find successor and predecessor
Node* s = inSucc(ptr);
Node* p = inPred(ptr);
// If ptr has left subtree.
if (ptr->lthread == false)
p->right = s;
// If ptr has right subtree.
else {
if (ptr->rthread == false)
s->left = p;
}
free(ptr);
return root;
}
Java
// Here 'par' is pointer to parent Node and 'ptr' is
// pointer to current Node.
static Node caseB(Node root, Node par,
Node ptr)
{
Node child;
// Initialize child Node to be deleted has
// left child.
if (ptr.lthread == false)
child = ptr.left;
// Node to be deleted has right child.
else
child = ptr.right;
// Node to be deleted is root Node.
if (par == null)
root = child;
// Node is left child of its parent.
else if (ptr == par.left)
par.left = child;
else
par.right = child;
// Find successor and predecessor
Node s = inSucc(ptr);
Node p = inPred(ptr);
// If ptr has left subtree.
if (ptr.lthread == false)
p.right = s;
// If ptr has right subtree.
else {
if (ptr.rthread == false)
s.left = p;
}
return root;
}
// This code is contributed by gauravrajput1
情况C:要删除的节点有两个子节点
我们找到Node ptr的有序后继者(要删除的Node),然后将该后继者的信息复制到Node ptr中。在此有序后继节点之后,使用案例A或案例B删除。
CPP
// Here 'par' is pointer to parent Node and 'ptr' is
// pointer to current Node.
struct Node* caseC(struct Node* root, struct Node* par,
struct Node* ptr)
{
// Find inorder successor and its parent.
struct Node* parsucc = ptr;
struct Node* succ = ptr->right;
// Find leftmost child of successor
while (succ->left != NULL) {
parsucc = succ;
succ = succ->left;
}
ptr->info = succ->info;
if (succ->lthread == true && succ->rthread == true)
root = caseA(root, parsucc, succ);
else
root = caseB(root, parsucc, succ);
return root;
}
以下是完整的代码:
C++
// Complete C++ program to demonstrate deletion
// in threaded BST
#include
using namespace std;
struct Node {
struct Node *left, *right;
int info;
// True if left pointer points to predecessor
// in Inorder Traversal
bool lthread;
// True if right pointer points to predecessor
// in Inorder Traversal
bool rthread;
};
// Insert a Node in Binary Threaded Tree
struct Node* insert(struct Node* root, int ikey)
{
// Searching for a Node with given value
Node* ptr = root;
Node* par = NULL; // Parent of key to be inserted
while (ptr != NULL) {
// If key already exists, return
if (ikey == (ptr->info)) {
printf("Duplicate Key !\n");
return root;
}
par = ptr; // Update parent pointer
// Moving on left subtree.
if (ikey < ptr->info) {
if (ptr->lthread == false)
ptr = ptr->left;
else
break;
}
// Moving on right subtree.
else {
if (ptr->rthread == false)
ptr = ptr->right;
else
break;
}
}
// Create a new Node
Node* tmp = new Node;
tmp->info = ikey;
tmp->lthread = true;
tmp->rthread = true;
if (par == NULL) {
root = tmp;
tmp->left = NULL;
tmp->right = NULL;
}
else if (ikey < (par->info)) {
tmp->left = par->left;
tmp->right = par;
par->lthread = false;
par->left = tmp;
}
else {
tmp->left = par;
tmp->right = par->right;
par->rthread = false;
par->right = tmp;
}
return root;
}
// Returns inorder successor using left
// and right children (Used in deletion)
struct Node* inSucc(struct Node* ptr)
{
if (ptr->rthread == true)
return ptr->right;
ptr = ptr->right;
while (ptr->lthread == false)
ptr = ptr->left;
return ptr;
}
// Returns inorder successor using rthread
// (Used in inorder)
struct Node* inorderSuccessor(struct Node* ptr)
{
// If rthread is set, we can quickly find
if (ptr->rthread == true)
return ptr->right;
// Else return leftmost child of right subtree
ptr = ptr->right;
while (ptr->lthread == false)
ptr = ptr->left;
return ptr;
}
// Printing the threaded tree
void inorder(struct Node* root)
{
if (root == NULL)
printf("Tree is empty");
// Reach leftmost Node
struct Node* ptr = root;
while (ptr->lthread == false)
ptr = ptr->left;
// One by one print successors
while (ptr != NULL) {
printf("%d ", ptr->info);
ptr = inorderSuccessor(ptr);
}
}
struct Node* inPred(struct Node* ptr)
{
if (ptr->lthread == true)
return ptr->left;
ptr = ptr->left;
while (ptr->rthread == false)
ptr = ptr->right;
return ptr;
}
// Here 'par' is pointer to parent Node and 'ptr' is
// pointer to current Node.
struct Node* caseA(struct Node* root, struct Node* par,
struct Node* ptr)
{
// If Node to be deleted is root
if (par == NULL)
root = NULL;
// If Node to be deleted is left
// of its parent
else if (ptr == par->left) {
par->lthread = true;
par->left = ptr->left;
}
else {
par->rthread = true;
par->right = ptr->right;
}
// Free memory and return new root
free(ptr);
return root;
}
// Here 'par' is pointer to parent Node and 'ptr' is
// pointer to current Node.
struct Node* caseB(struct Node* root, struct Node* par,
struct Node* ptr)
{
struct Node* child;
// Initialize child Node to be deleted has
// left child.
if (ptr->lthread == false)
child = ptr->left;
// Node to be deleted has right child.
else
child = ptr->right;
// Node to be deleted is root Node.
if (par == NULL)
root = child;
// Node is left child of its parent.
else if (ptr == par->left)
par->left = child;
else
par->right = child;
// Find successor and predecessor
Node* s = inSucc(ptr);
Node* p = inPred(ptr);
// If ptr has left subtree.
if (ptr->lthread == false)
p->right = s;
// If ptr has right subtree.
else {
if (ptr->rthread == false)
s->left = p;
}
free(ptr);
return root;
}
// Here 'par' is pointer to parent Node and 'ptr' is
// pointer to current Node.
struct Node* caseC(struct Node* root, struct Node* par,
struct Node* ptr)
{
// Find inorder successor and its parent.
struct Node* parsucc = ptr;
struct Node* succ = ptr->right;
// Find leftmost child of successor
while (succ->lthread==false) {
parsucc = succ;
succ = succ->left;
}
ptr->info = succ->info;
if (succ->lthread == true && succ->rthread == true)
root = caseA(root, parsucc, succ);
else
root = caseB(root, parsucc, succ);
return root;
}
// Deletes a key from threaded BST with given root and
// returns new root of BST.
struct Node* delThreadedBST(struct Node* root, int dkey)
{
// Initialize parent as NULL and ptrent
// Node as root.
struct Node *par = NULL, *ptr = root;
// Set true if key is found
int found = 0;
// Search key in BST : find Node and its
// parent.
while (ptr != NULL) {
if (dkey == ptr->info) {
found = 1;
break;
}
par = ptr;
if (dkey < ptr->info) {
if (ptr->lthread == false)
ptr = ptr->left;
else
break;
}
else {
if (ptr->rthread == false)
ptr = ptr->right;
else
break;
}
}
if (found == 0)
printf("dkey not present in tree\n");
// Two Children
else if (ptr->lthread == false && ptr->rthread == false)
root = caseC(root, par, ptr);
// Only Left Child
else if (ptr->lthread == false)
root = caseB(root, par, ptr);
// Only Right Child
else if (ptr->rthread == false)
root = caseB(root, par, ptr);
// No child
else
root = caseA(root, par, ptr);
return root;
}
// Driver Program
int main()
{
struct Node* root = NULL;
root = insert(root, 20);
root = insert(root, 10);
root = insert(root, 30);
root = insert(root, 5);
root = insert(root, 16);
root = insert(root, 14);
root = insert(root, 17);
root = insert(root, 13);
root = delThreadedBST(root, 20);
inorder(root);
return 0;
}
Java
// Complete Java program to demonstrate deletion
// in threaded BST
import java.util.*;
class solution {
static class Node {
Node left, right;
int info;
// True if left pointer points to predecessor
// in Inorder Traversal
boolean lthread;
// True if right pointer points to predecessor
// in Inorder Traversal
boolean rthread;
};
// Insert a Node in Binary Threaded Tree
static Node insert(Node root, int ikey)
{
// Searching for a Node with given value
Node ptr = root;
Node par = null; // Parent of key to be inserted
while (ptr != null) {
// If key already exists, return
if (ikey == (ptr.info)) {
System.out.printf("Duplicate Key !\n");
return root;
}
par = ptr; // Update parent pointer
// Moving on left subtree.
if (ikey < ptr.info) {
if (ptr.lthread == false)
ptr = ptr.left;
else
break;
}
// Moving on right subtree.
else {
if (ptr.rthread == false)
ptr = ptr.right;
else
break;
}
}
// Create a new Node
Node tmp = new Node();
tmp.info = ikey;
tmp.lthread = true;
tmp.rthread = true;
if (par == null) {
root = tmp;
tmp.left = null;
tmp.right = null;
}
else if (ikey < (par.info)) {
tmp.left = par.left;
tmp.right = par;
par.lthread = false;
par.left = tmp;
}
else {
tmp.left = par;
tmp.right = par.right;
par.rthread = false;
par.right = tmp;
}
return root;
}
// Returns inorder successor using left
// and right children (Used in deletion)
static Node inSucc(Node ptr)
{
if (ptr.rthread == true)
return ptr.right;
ptr = ptr.right;
while (ptr.lthread == false)
ptr = ptr.left;
return ptr;
}
// Returns inorder successor using rthread
// (Used in inorder)
static Node inorderSuccessor(Node ptr)
{
// If rthread is set, we can quickly find
if (ptr.rthread == true)
return ptr.right;
// Else return leftmost child of right subtree
ptr = ptr.right;
while (ptr.lthread == false)
ptr = ptr.left;
return ptr;
}
// Printing the threaded tree
static void inorder(Node root)
{
if (root == null)
System.out.printf("Tree is empty");
// Reach leftmost Node
Node ptr = root;
while (ptr.lthread == false)
ptr = ptr.left;
// One by one print successors
while (ptr != null) {
System.out.printf("%d ", ptr.info);
ptr = inorderSuccessor(ptr);
}
}
static Node inPred(Node ptr)
{
if (ptr.lthread == true)
return ptr.left;
ptr = ptr.left;
while (ptr.rthread == false)
ptr = ptr.right;
return ptr;
}
// Here 'par' is pointer to parent Node and 'ptr' is
// pointer to current Node.
static Node caseA(Node root, Node par,
Node ptr)
{
// If Node to be deleted is root
if (par == null)
root = null;
// If Node to be deleted is left
// of its parent
else if (ptr == par.left) {
par.lthread = true;
par.left = ptr.left;
}
else {
par.rthread = true;
par.right = ptr.right;
}
return root;
}
// Here 'par' is pointer to parent Node and 'ptr' is
// pointer to current Node.
static Node caseB(Node root, Node par,
Node ptr)
{
Node child;
// Initialize child Node to be deleted has
// left child.
if (ptr.lthread == false)
child = ptr.left;
// Node to be deleted has right child.
else
child = ptr.right;
// Node to be deleted is root Node.
if (par == null)
root = child;
// Node is left child of its parent.
else if (ptr == par.left)
par.left = child;
else
par.right = child;
// Find successor and predecessor
Node s = inSucc(ptr);
Node p = inPred(ptr);
// If ptr has left subtree.
if (ptr.lthread == false)
p.right = s;
// If ptr has right subtree.
else {
if (ptr.rthread == false)
s.left = p;
}
return root;
}
// Here 'par' is pointer to parent Node and 'ptr' is
// pointer to current Node.
static Node caseC(Node root, Node par,
Node ptr)
{
// Find inorder successor and its parent.
Node parsucc = ptr;
Node succ = ptr.right;
// Find leftmost child of successor
while (succ.lthread == false) {
parsucc = succ;
succ = succ.left;
}
ptr.info = succ.info;
if (succ.lthread == true && succ.rthread == true)
root = caseA(root, parsucc, succ);
else
root = caseB(root, parsucc, succ);
return root;
}
// Deletes a key from threaded BST with given root and
// returns new root of BST.
static Node delThreadedBST(Node root, int dkey)
{
// Initialize parent as null and ptrent
// Node as root.
Node par = null, ptr = root;
// Set true if key is found
int found = 0;
// Search key in BST : find Node and its
// parent.
while (ptr != null) {
if (dkey == ptr.info) {
found = 1;
break;
}
par = ptr;
if (dkey < ptr.info) {
if (ptr.lthread == false)
ptr = ptr.left;
else
break;
}
else {
if (ptr.rthread == false)
ptr = ptr.right;
else
break;
}
}
if (found == 0)
System.out.printf("dkey not present in tree\n");
// Two Children
else if (ptr.lthread == false && ptr.rthread == false)
root = caseC(root, par, ptr);
// Only Left Child
else if (ptr.lthread == false)
root = caseB(root, par, ptr);
// Only Right Child
else if (ptr.rthread == false)
root = caseB(root, par, ptr);
// No child
else
root = caseA(root, par, ptr);
return root;
}
// Driver Program
public static void main(String args[])
{
Node root = null;
root = insert(root, 20);
root = insert(root, 10);
root = insert(root, 30);
root = insert(root, 5);
root = insert(root, 16);
root = insert(root, 14);
root = insert(root, 17);
root = insert(root, 13);
root = delThreadedBST(root, 20);
inorder(root);
}
}
// This code is contributed by Arnab Kundu
C#
// Complete C# program to demonstrate deletion
// in threaded BST
using System;
class GFG {
public class Node {
public Node left, right;
public int info;
// True if left pointer points to predecessor
// in Inorder Traversal
public bool lthread;
// True if right pointer points to predecessor
// in Inorder Traversal
public bool rthread;
};
// Insert a Node in Binary Threaded Tree
static Node insert(Node root, int ikey)
{
// Searching for a Node with given value
Node ptr = root;
Node par = null; // Parent of key to be inserted
while (ptr != null) {
// If key already exists, return
if (ikey == (ptr.info)) {
Console.Write("Duplicate Key !\n");
return root;
}
par = ptr; // Update parent pointer
// Moving on left subtree.
if (ikey < ptr.info) {
if (ptr.lthread == false)
ptr = ptr.left;
else
break;
}
// Moving on right subtree.
else {
if (ptr.rthread == false)
ptr = ptr.right;
else
break;
}
}
// Create a new Node
Node tmp = new Node();
tmp.info = ikey;
tmp.lthread = true;
tmp.rthread = true;
if (par == null) {
root = tmp;
tmp.left = null;
tmp.right = null;
}
else if (ikey < (par.info)) {
tmp.left = par.left;
tmp.right = par;
par.lthread = false;
par.left = tmp;
}
else {
tmp.left = par;
tmp.right = par.right;
par.rthread = false;
par.right = tmp;
}
return root;
}
// Returns inorder successor using left
// and right children (Used in deletion)
static Node inSucc(Node ptr)
{
if (ptr.rthread == true)
return ptr.right;
ptr = ptr.right;
while (ptr.lthread == false)
ptr = ptr.left;
return ptr;
}
// Returns inorder successor using rthread
// (Used in inorder)
static Node inorderSuccessor(Node ptr)
{
// If rthread is set, we can quickly find
if (ptr.rthread == true)
return ptr.right;
// Else return leftmost child of right subtree
ptr = ptr.right;
while (ptr.lthread == false)
ptr = ptr.left;
return ptr;
}
// Printing the threaded tree
static void inorder(Node root)
{
if (root == null)
Console.Write("Tree is empty");
// Reach leftmost Node
Node ptr = root;
while (ptr.lthread == false)
ptr = ptr.left;
// One by one print successors
while (ptr != null) {
Console.Write("{0} ", ptr.info);
ptr = inorderSuccessor(ptr);
}
}
static Node inPred(Node ptr)
{
if (ptr.lthread == true)
return ptr.left;
ptr = ptr.left;
while (ptr.rthread == false)
ptr = ptr.right;
return ptr;
}
// Here 'par' is pointer to parent Node and 'ptr' is
// pointer to current Node.
static Node caseA(Node root, Node par,
Node ptr)
{
// If Node to be deleted is root
if (par == null)
root = null;
// If Node to be deleted is left
// of its parent
else if (ptr == par.left) {
par.lthread = true;
par.left = ptr.left;
}
else {
par.rthread = true;
par.right = ptr.right;
}
return root;
}
// Here 'par' is pointer to parent Node and 'ptr' is
// pointer to current Node.
static Node caseB(Node root, Node par,
Node ptr)
{
Node child;
// Initialize child Node to be deleted has
// left child.
if (ptr.lthread == false)
child = ptr.left;
// Node to be deleted has right child.
else
child = ptr.right;
// Node to be deleted is root Node.
if (par == null)
root = child;
// Node is left child of its parent.
else if (ptr == par.left)
par.left = child;
else
par.right = child;
// Find successor and predecessor
Node s = inSucc(ptr);
Node p = inPred(ptr);
// If ptr has left subtree.
if (ptr.lthread == false)
p.right = s;
// If ptr has right subtree.
else {
if (ptr.rthread == false)
s.left = p;
}
return root;
}
// Here 'par' is pointer to parent Node and 'ptr' is
// pointer to current Node.
static Node caseC(Node root, Node par,
Node ptr)
{
// Find inorder successor and its parent.
Node parsucc = ptr;
Node succ = ptr.right;
// Find leftmost child of successor
while (succ.lthread == false) {
parsucc = succ;
succ = succ.left;
}
ptr.info = succ.info;
if (succ.lthread == true && succ.rthread == true)
root = caseA(root, parsucc, succ);
else
root = caseB(root, parsucc, succ);
return root;
}
// Deletes a key from threaded BST with given root and
// returns new root of BST.
static Node delThreadedBST(Node root, int dkey)
{
// Initialize parent as null and ptrent
// Node as root.
Node par = null, ptr = root;
// Set true if key is found
int found = 0;
// Search key in BST : find Node and its
// parent.
while (ptr != null) {
if (dkey == ptr.info) {
found = 1;
break;
}
par = ptr;
if (dkey < ptr.info) {
if (ptr.lthread == false)
ptr = ptr.left;
else
break;
}
else {
if (ptr.rthread == false)
ptr = ptr.right;
else
break;
}
}
if (found == 0)
Console.Write("dkey not present in tree\n");
// Two Children
else if (ptr.lthread == false && ptr.rthread == false)
root = caseC(root, par, ptr);
// Only Left Child
else if (ptr.lthread == false)
root = caseB(root, par, ptr);
// Only Right Child
else if (ptr.rthread == false)
root = caseB(root, par, ptr);
// No child
else
root = caseA(root, par, ptr);
return root;
}
// Driver code
public static void Main(String[] args)
{
Node root = null;
root = insert(root, 20);
root = insert(root, 10);
root = insert(root, 30);
root = insert(root, 5);
root = insert(root, 16);
root = insert(root, 14);
root = insert(root, 17);
root = insert(root, 13);
root = delThreadedBST(root, 20);
inorder(root);
}
}
// This code has been contributed by 29AjayKumar
输出 :
10 13 14 16 17 5 30