二叉搜索树的经典应用面试题(key&key-value模式)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hansionz/article/details/82052583
0.题目
  • 1.假设给你一篇英语文章,又给你一个在这个英语文章中的英语单词,让你检查这个英语单词是否拼写正确。
  • 2.假设给你一篇英语文章,如何才能求出文章中所有单词重复出现的次数呢?
1.思路
  • 1.第一题是key模式,我们可以将这篇英语文章中的所有正确的单词都放在一颗二叉搜索树中,然后在二叉搜索树搜索这个单词,如果在二叉搜索树中,则必然是正确的;如果不在,则是错误的。
  • 2.第二题是key-value模式,我们可以遍历这篇文章,遇到二叉搜索树中没有的,我们就把这个单词给插入,count域为1(用来计数重复出现多少次);如果二叉搜索树中有这个单词,则让它的count++一下

2.代码实现

key模式
由于key模式就是判断一个值是否在一棵二叉搜索树中,对于第一题,我们只需要把二叉搜索树的插入数据的类型该为char*,查找函数等稍微改一下数据类型即可,所有这里贴出二叉搜索树基本操作,总结在我的另一边博客:
https://blog.csdn.net/hansionz/article/details/81985287

key-value模式

/*****************************************************************/
/*key-value模式*/

typedef char* BSTKeyType;//key类型(字符串)
typedef int BSTValueType;//value类型(计数用的为整型)
//定义二叉搜索树结点类型
typedef struct BSTKeyValueNode
{
    BSTKeyType _key;
    BSTValueType _value;
    struct BSTKeyValueNode* _left;
    struct BSTKeyValueNode* _right;
}BSTKeyValueNode;
/**********************************************************************/
/*key-value*/
//创建一个新的结点
BSTKeyValueNode* BuyBSTKeyValueNode(BSTKeyType key,BSTValueType value)
{
    BSTKeyValueNode* tmp = (BSTKeyValueNode*)malloc(sizeof(BSTKeyValueNode));
    if (tmp == NULL)
    {
        perror("use malloc of create");
    }
    tmp->_key = (char*)malloc(strlen(key) + 1);
    strcpy(tmp->_key, key);//字符串(char*)不能直接赋值,要用strcpy拷贝
    tmp->_value = value;
    tmp->_left = NULL;
    tmp->_right = NULL;

    return tmp;
}
//新插入一个结点(插入成功返回1,失败返回0)
int BSTKVInsert(BSTKeyValueNode** kvroot, BSTKeyType key, BSTValueType value)
{
    assert(kvroot);

    BSTKeyValueNode* cur = *kvroot;
    BSTKeyValueNode* parent = NULL;//用来记录要插入结点的双亲
    //整棵树为空,插入第一个结点(这里要改变根节点指针的指向,必须要用二级指针)
    if (*kvroot == NULL)
    {
        *kvroot = BuyBSTKeyValueNode(key, value);
        return 1;
    }
    //1.找到插入位置
    while (cur)
    {
        if (strcmp(cur->_key, key) > 0)
        {
            parent = cur;
            cur = cur->_left;
        }
        else if (strcmp(cur->_key, key) < 0)
        {
            parent = cur;
            cur = cur->_right;
        }
        //如果存在相同的数据,则插入失败
        else
        {
            return 0;
        }
    }
    //2.parent为插入结点的双亲,在确定要插入的结点在左还是右,然后直接插入
    if (strcmp(parent->_key, key) > 0)
    {
        parent->_left = BuyBSTKeyValueNode(key, value);
    }
    else
    {
        parent->_right = BuyBSTKeyValueNode(key, value);
    }
    return 1;
}
//在二叉树中找一个结点
BSTKeyValueNode* BSTKVFind(BSTKeyValueNode** kvroot, BSTKeyType key)
{
    assert(kvroot);

    BSTKeyValueNode* cur = *kvroot;
    //根据二叉搜索树的性质比较遍历一遍
    while (cur)
    {
        if (strcmp(cur->_key, key) > 0)
        {
            cur = cur->_left;
        }
        else if (strcmp(cur->_key, key) < 0)
        {
            cur = cur->_right;
        }
        else
        {
            //找到返回它的地址
            return cur;
        }
    }
    //找不到返回NULL
    return NULL;
}
//中序遍历(方便测试使用)
void BSTKVInorder(BSTKeyValueNode** kvroot)
{
    assert(kvroot);

    if (*kvroot == NULL)
    {
        return;
    }
    BSTKVInorder(&(*kvroot)->_left);
    printf("%s:%d\n", (*kvroot)->_key, (*kvroot)->_value);
    BSTKVInorder(&(*kvroot)->_right);
}

下边是测试代码

void TestBSKVTree()
{
    BSTKeyValueNode* kvr = NULL;
    char str[20] = { '0' };
    while (1)
    {
        scanf("%s", str);
        //输入exit则结束
        if (strcmp(str, "exit") == 0)
        {
            break;
        }
        BSTKeyValueNode* fnode = BSTKVFind(&kvr, str);
        //如果二叉搜索树中存在结点,则只改变它的value域,记录次数
        if (fnode)
        {
            fnode->_value++;
        }
        //不存在,则插入此结点
        else
        {
            BSTKVInsert(&kvr, str, 1);
        }
    }
    //中序遍历看结果
    BSTKVInorder(&kvr);
}

猜你喜欢

转载自blog.csdn.net/hansionz/article/details/82052583
今日推荐