二叉搜尋樹的經典應用面試題(key&key-value模式)
阿新 • • 發佈:2018-12-24
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);
}