📜  三元搜索树(删除)

📅  最后修改于: 2021-04-17 10:29:11             🧑  作者: Mango

在TST的SET 1帖子中,我们描述了如何在TST中插入和搜索节点。在本文中,我们将讨论有关如何从TST删除节点的算法。

在删除操作过程中,我们使用递归从下往上的方式删除密钥。从特里删除键时,以下是可能的情况。

  1. TST中可能没有密钥。
    解决方案:删除操作不应修改TST。
  2. 密钥作为唯一密钥存在(密钥的任何部分都不包含另一个密钥(前缀),密钥本身也不是TST中另一个密钥的前缀)。
    解决方案:删除所有节点。
  3. 键是TST中另一个长键的前缀键。
    解决方案:取消标记叶子节点。
  4. TST中存在的密钥,具有至少另一个密钥作为前缀密钥。
    解决方案:从密钥末尾删除节点,直到删除最长前缀密钥的第一个叶节点。

delete_node函数的说明

  1. 假设我们要删除字符串“ BIG”,因为它在TST中不存在,因此在与第一个字符“ B”匹配之后,delete_node函数将返回零。因此,什么也不会被删除。
  2. 现在我们要删除字符串“ BUG”,它在TST中唯一存在,即它既没有一部分是其他字符串的前缀,又没有任何其他字符串的前缀,因此将被完全删除。
  3. 现在我们要删除字符串“ CAT”,因为它是字符串“ CATS”的前缀,所以我们无法删除字符串“ CAT”中的内容,而只能取消标记叶节点,这将确保“ CAT”不再是成员TST的字符串。
  4. 现在我们要删除字符串“ CATS”,因为它具有前缀字符串“ CAT”,它也是TST的成员字符串,因此我们只能删除字符串“ CATS”的最后一个字符,这将确保字符串“ CAT”仍然保留TST的一部分。
C
// C program to demonstrate deletion in
// Ternary Search Tree (TST). For insert
// and other functions, refer
// https://www.geeksforgeeks.org/ternary-search-tree/
#include
#include
  
// structure of a node in TST
struct Node
{
    char key;
    int isleaf;
    struct Node *left;
    struct Node *eq;
    struct Node *right;
};
  
// function to create a Node in TST
struct Node *createNode(char key)
{
    struct Node *temp =
        (struct Node*)malloc(sizeof(struct Node));
    temp->key = key;
    temp->isleaf = 0;
    temp->left = NULL;
    temp->eq = NULL;
    temp->right = NULL;
    return temp;
};
  
// function to insert a Node in TST
void insert_node(struct Node **root ,char *s)
{
    if (!(*root))
        (*root) = createNode(*s);
  
    if ((*s)<(*root)->key)
        insert_node( &(*root)->left ,s);
  
    else if ((*s)>(*root)->key)
        insert_node( &(*root)->right ,s);
  
    else if ((*s) == (*root)->key)
    {
        if (*(s+1) == '\0')
        {
            (*root)->isleaf = 1;
            return;
        }
        insert_node( &(*root)->eq ,s+1);
    }
}
  
// function to display the TST
void display(struct Node *root, char str[], int level)
{
    if (!root)
        return;
  
    display(root->left ,str ,level);
    str[level] = root->key;
  
    if (root->isleaf == 1)
    {
        str[level+1] = '\0';
        printf("%s\n",str);
    }
  
    display(root->eq ,str ,level+1);
    display(root->right ,str ,level);
}
  
// to check if current Node is leaf node or not
int isLeaf(struct Node *root)
{
    return root->isleaf == 1;
}
  
// to check if current node has any child node or not
int isFreeNode(struct Node *root)
{
    if (root->left ||root->eq ||root->right)
        return 0;
    return 1;
}
  
// function to delete a string in TST
int delete_node(struct Node *root, char str[],
                int level ,int n)
{
    if (root == NULL)
        return 0;
  
  
    // CASE 4 Key present in TST, having
    // atleast one other key as prefix key.
    if (str[level+1] == '\0')
    {
        // Unmark leaf node if present
        if (isLeaf(root))
        {
            root->isleaf=0;
            return isFreeNode(root);
        }
  
        // else string is not present in TST and
        // return 0
        else
            return 0;
    }
    else
    {
        // CASE 3 Key is prefix key of another
        // long key in TST.
        if (str[level] < root->key)
            delete_node(root->left ,str ,level ,n);
        else if (str[level] > root->key)
            delete_node(root->right ,str ,level ,n);
  
        // CASE 1 Key may not be there in TST.
        else if (str[level] == root->key)
        {
            // CASE 2 Key present as unique key
            if( delete_node(root->eq ,str ,level+1 ,n) )
            {
                // delete the last node, neither it
                // has any child
                // nor it is part of any other string
                free(root->eq);
                return !isLeaf(root) && isFreeNode(root);
            }
        }
    }
  
    return 0;
}
  
// Driver function
int main()
{
    struct Node *temp = NULL;
  
    insert_node(&temp ,"CAT");
    insert_node(&temp ,"BUGS");
    insert_node(&temp ,"CATS");
    insert_node(&temp ,"UP");
  
    int level = 0;
    char str[20];
    int p = 0;
  
    printf( "1.Content of the TST before "
            "deletion:\n" );
    display(temp ,str ,level);
  
    level = 0;
    delete_node(temp ,"CAT" ,level ,5);
  
    level = 0;
    printf("\n2.Content of the TST after "
           "deletion:\n");
    display(temp, str, level);
    return 0;
}


C++
// C++ program to demonstrate deletion in
// Ternary Search Tree (TST)
// For insert and other functions, refer
// https://www.geeksforgeeks.org/ternary-search-tree
  
#include
using namespace std;
  
// structure of a node in TST
struct Node
{
    char key;
    int isleaf;
    struct Node *left;
    struct Node *eq;
    struct Node *right;
};
  
// function to create a node in TST
struct Node *createNode(char key)
{
    struct Node *temp = new Node;
    temp->key = key;
    temp->isleaf = 0;
    temp->left = NULL;
    temp->eq = NULL;
    temp->right = NULL;
    return temp;
};
  
// function to insert a Node in TST
void insert_node(struct Node **root, char *s)
{
    if (!(*root))
    {
        (*root) = createNode(*s);
    }
  
    if ((*s)<(*root)->key)
        insert_node( &(*root)->left, s);
  
    else if ((*s)>(*root)->key)
        insert_node( &(*root)->right, s);
  
    else if ((*s) == (*root)->key)
    {
        if (*(s+1) == '\0')
        {
            (*root)->isleaf = 1;
            return;
        }
        insert_node( &(*root)->eq, s+1);
    }
}
  
// function to display the TST
void display(struct Node *root, char str[], int level)
{
    if (!root)
        return;
  
    display(root->left, str, level);
    str[level] = root->key;
  
    if (root->isleaf == 1)
    {
        str[level+1] = '\0';
        cout<< str <eq, str, level+1);
    display(root->right, str, level);
}
  
//to check if current node is leaf node or not
int isLeaf(struct Node *root)
{
    return root->isleaf == 1;
}
  
// to check if current node has any child
// node or not
int isFreeNode(struct Node *root)
{
    if (root->left ||root->eq ||root->right)
        return 0;
    return 1;
}
  
// function to delete a string in TST
int delete_node(struct Node *root, char str[],
                int level, int n)
{
    if (root == NULL)
        return 0;
  
  
    // CASE 4 Key present in TST, having atleast
    // one other key as prefix key.
    if (str[level+1] == '\0')
    {
        // Unmark leaf node if present
        if (isLeaf(root))
        {
            root->isleaf = 0;
            return isFreeNode(root);
        }
  
        // else string is not present in TST and
        // return 0
        else
            return 0;
    }
  
    // CASE 3 Key is prefix key of another long
    // key in TST.
    if (str[level] < root->key)
        return delete_node(root->left, str, level, n);
    if (str[level] > root->key)
        return delete_node(root->right, str, level, n);
  
    // CASE 1 Key may not be there in TST.
    if (str[level] == root->key)
    {
        // CASE 2 Key present as unique key
        if (delete_node(root->eq, str, level+1, n))
        {
            // delete the last node, neither it has
            // any child nor it is part of any other
            // string
            delete(root->eq);
            return !isLeaf(root) && isFreeNode(root);
        }
    }
  
    return 0;
}
  
// Driver function
int main()
{
    struct Node *temp = NULL;
  
    insert_node(&temp, "CAT");
    insert_node(&temp, "BUGS");
    insert_node(&temp, "CATS");
    insert_node(&temp, "UP");
  
    int level = 0;
    char str[20];
    int p = 0;
  
    cout << "1.Content of the TST before deletion:\n";
    display(temp, str, level);
  
    level = 0;
    delete_node(temp,"CAT", level, 5);
  
    level = 0;
    cout << "\n2.Content of the TST after deletion:\n";
    display(temp, str, level);
    return 0;
}


输出:

1.Content of the TST before deletion:
BUGS
CAT
CATS
UP

2.Content of the TST after deletion:
BUGS
CATS
UP