模拟实现一个简单的字典

分析:实现一个简单的英汉字典
这个问题其实和我的上一篇博客《判断一个单词拼写是否正确》类似,都可以用二叉搜索树来解决,只不过这次结点里存放的数据,是以键值对的形式存放的,意思就是这个结点的数据由两种类型的数据组成,一个是英语,一个是英语对应的汉语意思。
具体的插入、删除、查找操作为什么那样实现,请参考这篇博客:https://mp.csdn.net/mdeditor/82465620

BSTreeNodeKV.h

#ifndef __BSTREENODEKV_H__
#define __BSTREENODEKV_H__

#define false 0
#define true 1

#include<stdio.h>
#include<assert.h>
#include<malloc.h>

typedef char* k;//中文
typedef char* v;//英文

typedef struct Pair
{
    k _key;
    v _value;
}Pair;

typedef struct BSTreeNodeKV
{
    struct BSTreeNodeKV* _pLeft;
    struct BSTreeNodeKV* _pRight;
    Pair _data;
}BSTNKV;

void InitBSTNKV(BSTNKV** pRoot);
void InsertBSTNKV(BSTNKV** pRoot, k key, v value);
BSTNKV* FindBSTNKV(BSTNKV* pRoot, k key);
void DestroyBSTNKV(BSTNKV** pRoot);
void DelectBSTNKV(BSTNKV** pRoot, k key);


#endif //__BSTREENODEKV_H__

BSTreeNodeKV.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"BSTreeNodeKV.h"

BSTNKV* BuyNode(k key, v value)
{
    BSTNKV* newNode = (BSTNKV*)malloc(sizeof(BSTNKV));
    if (NULL == newNode)
    {
        printf("创建结点失败\n");
        return NULL;
    }
    newNode->_data._key = key;
    newNode->_data._value = value;
    newNode->_pLeft = NULL;
    newNode->_pRight = NULL;
}

void InitBSTNKV(BSTNKV** pRoot)
{
    assert(pRoot);
    *pRoot = NULL;
}

void InsertBSTNKV(BSTNKV** pRoot, k key, v value)
{
    assert(pRoot);
    if (*pRoot == NULL)
        *pRoot = BuyNode(key, value);
    int tmp = strcmp((*pRoot)->_data._key, key);
    if (tmp > 0)
    {
        return InsertBSTNKV(&(*pRoot)->_pLeft, key, value);
    }
    else if (tmp < 0)
        return InsertBSTNKV(&(*pRoot)->_pRight, key, value);
    else
        return;
}

BSTNKV* FindBSTNKV(BSTNKV* pRoot, k key)
{
    if (pRoot == NULL)
        return NULL;
    int tmp = strcmp(pRoot->_data._key, key);
    if (tmp > 0)
        return FindBSTNKV(pRoot->_pLeft, key);
    else if (tmp < 0)
        return FindBSTNKV(pRoot->_pRight, key);
    else
        return pRoot;
}

void DestroyBSTNKV(BSTNKV** pRoot)
{
    assert(pRoot);
    while (*pRoot)
    {
        DestroyBSTNKV(&(*pRoot)->_pLeft);
        DestroyBSTNKV(&(*pRoot)->_pRight);
        free(*pRoot);
        *pRoot = NULL;
    }
}

void DelectBSTNKV(BSTNKV** pRoot, k key)
{
    assert(pRoot);
    BSTNKV* pCur = NULL;
    BSTNKV* pParent = NULL;
    if (NULL == *pRoot)
        return false;
    else
    {
        //找到待删除结点

        pCur = *pRoot;
        while (pCur)
        {
            if (key > pCur->_data._key)
            {
                pParent = pCur;
                pCur = pCur->_pRight;
            }
            else if (key < pCur->_data._key)
            {
                pParent = pCur;
                pCur = pCur->_pLeft;
            }
            else
                break;
        }
        //删除结点

        //待删结点是叶子节点或者只有右孩子
        if (NULL == pCur->_pLeft)
        {
            if (pCur == *pRoot)//若果删除的是根结点
                *pRoot = pCur->_pRight;
            else if (pCur == pParent->_pLeft)
                pParent->_pLeft = pCur->_pRight;
            else
                pParent->_pRight = pCur->_pRight;
        }
        //只有左孩子
        else if (NULL == pCur->_pRight)
        {
            if (pCur == *pRoot)//若果删除的是根结点
                *pRoot = pCur->_pLeft;
            else if (pCur == pParent->_pLeft)
                pParent->_pLeft = pCur->_pLeft;
            else
                pParent->_pRight = pCur->_pLeft;
        }
        //左右孩子都存在
        else
        {
            //替代法,向待删除点的右子树找最左边的数(最小)/向待删除点的左子树找最右边的数(最大),将待删除点与最左边/最右边的数交换,删除最左边/最右边的数
            BSTNKV* Inorder = pCur->_pRight;
            pParent = Inorder;
            while (Inorder->_pLeft)//除了循环函数,Inorder不可能有左孩子
            {
                pParent = Inorder;
                Inorder = Inorder->_pLeft;
            }
            pCur->_data._value = Inorder->_data._value;//交换
            if (Inorder == pParent->_pLeft)
                pParent->_pLeft = Inorder->_pRight;
            else if (Inorder == pParent->_pRight)
                pParent->_pRight = Inorder->_pRight;
            pCur = Inorder;
        }
    }
    free(pCur);
    pCur = NULL;
    return true;
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"BSTreeNodeKV.h"

int main()
{
    BSTNKV* pRoot;
    InitBSTNKV(&pRoot);
    InsertBSTNKV(&pRoot, "hello", "你好");
    InsertBSTNKV(&pRoot, "world", "世界");
    InsertBSTNKV(&pRoot, "child", "孩子");

    //DestroyBSTNKV(&pRoot);
    DelectBSTNKV(&pRoot, "world");

    printf("%s\n", FindBSTNKV(pRoot, "hello")->_data._value);
    printf("%s\n", FindBSTNKV(pRoot, "world")->_data._value);



    return 0;
}

猜你喜欢

转载自blog.csdn.net/huaijiu123/article/details/82714222