使用二叉排序树构造键值映射

本文介绍了一种使用二叉排序树实现的Map结构,包括插入、删除、搜索等功能。通过模板类CMapItem存储键值对,并实现了比较运算符以支持不同数据类型的键。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

    在STL里有map,在MFC里有CMap,它们都是通过模板来构造这样一种结构,即可以将<key,value>键值对存储进来。对于键值对的存储会使用到某种数据结构,来达到快速存储与搜索的目的。

     本文中使用二叉排序树来构造类CC_Map,具有插入、删除、搜索节点等基本功能。定义节点类CMapItem,它也是一个模板类,其中可以存储<key,value>keyvalue的数据类型通过模板参数来定义。在CMapItem里重载了><==,=等基本操作符,用于节点大小的比较。如果keyvalue为用户自定义类型,例如CCustomCls,则只需要在CCustomCls里重新重载这几个操作符即可(如果CCustomCls是作为key的数据类型的话,因为程序中默认是对key进行比较)。

     由于是仓促之作,还很不完善,以后在使用中在进行修改吧,先存在这里,以作参考。更希望大家能够指出问题,帮助完善,共同学习。

 

CMapItem

 

#pragma once

 

template<class First,class Second>

class CC_MapItem

{

public:

     CC_MapItem(void)

     {

         m_pLeft = NULL;

         m_pRight = NULL;

     }

 

public:

     ~CC_MapItem(void)

     {

         m_pLeft = NULL;

         m_pRight = NULL;

     }

 

public:

     void MakePair(First first,Second second)

     {

         m_First = first;

         m_Second = second;

 

         m_pLeft = NULL;

         m_pRight = NULL;

     };

 

     //获取key

     First GetFirst()

     {

         return m_First;

     }

 

     void SetFirst(First key)

     {

         m_First = key;

     }

 

     //获取value

     Second GetSecond()

     {

         return m_Second;

     }

    

     void SetSecond(Second value)

     {

         m_Second =value;

     }

 

     bool operator >(CC_MapItem<First,Second>& item)

     {

         return this->m_First > item.m_First;

     }

 

     bool operator <(CC_MapItem<First,Second>& item)

     {

         return this->m_First < item.m_First;

     }

 

     bool operator ==(CC_MapItem<First,Second>& item)

     {

         return this->m_First == item.m_First;

     }

 

 

private:

     First m_First;

     Second m_Second;

 

public:

     CC_MapItem<First,Second>* m_pLeft//左子节点

     CC_MapItem<First,Second>* m_pRight; //右子节点

};

 

CC_Map

 

#pragma once

 

#include "C_MapItem.h"

/********************************************************************

     创建时间: 2008/08/23

     扩展名:     h

    

     功 能:       与STL中的map类似,由key和value组成的项,通过二叉树构成集合

*********************************************************************/

 

template<class First,class Second>

class CC_Map

{

public:

     CC_Map(void)

     {

         m_Root = NULL;

     }

 

     /********************************************************************

     创建时间:      2008/08/23

     函数功能:      插入一项

    

     输入参数:     

     输出参数:      1: 成功0:已存在,不插入 -1:失败

     ********************************************************************/

     int Insert(CC_MapItem<First,Second>& item)

     {

         //new一个新的MapItem,然后添加进来,也是为了便于后续的释放

         CC_MapItem<First,Second>* InsertItem = new CC_MapItem<First,Second>;

         if(InsertItem == NULL) return -1;

         InsertItem->MakePair(item.GetFirst(),item.GetSecond());

 

         if(!m_Root)

              m_Root = InsertItem;

         else

         {

              CC_MapItem<First,Second>* pCurItem = m_Root;

              CC_MapItem<First,Second>* pPreItem = m_Root;

              int flag = 0;

              while(pCurItem)

              {

                   if((*InsertItem) < (*pCurItem))

                   {

                       flag = -1;

                       pPreItem = pCurItem;

                       pCurItem = pCurItem->m_pLeft;

                   }

                   else if((*InsertItem) > (*pCurItem))

                   {

                       flag = 1;

                       pPreItem = pCurItem;

                       pCurItem = pCurItem->m_pRight;

                   }

                   else if((*InsertItem) == (*pCurItem))

                       return 0;

              }

 

              if(flag == -1)

                   pPreItem->m_pLeft = InsertItem;

              else if(flag == 1)

                   pPreItem->m_pRight = InsertItem;

         }

 

         return 1;

     }

 

     //////////////////////////////////////////////////////////////////////////

     int Insert(First first,Second second)

     {

         CC_MapItem<First,Second> tmp;

         tmp.MakePair(first,second);

 

         return Insert(tmp);

     }

     //////////////////////////////////////////////////////////////////////////

 

     /********************************************************************

     创建时间:      2008/08/23

     函数功能:      遍历,并调用回调函数

     ********************************************************************/

     void Traversal(void(*callback)(CC_MapItem<First,Second>*))

     {

         TraversalRecusive(m_Root,callback);

     }

 

     /********************************************************************

     创建时间:      2008/08/24

     函数功能:      通过key找到value

    

     输入参数:      key      First

     输出参数:      value    Second

     ********************************************************************/

     Second Find(First key)

     {

         return FindRecusive(key,m_Root);

     }

 

     /********************************************************************

     创建时间:      2008/08/24

     函数功能:      通过key找到item

 

     输入参数:     

     输出参数:     

     ********************************************************************/

     CC_MapItem<First,Second>* FindItem(First key)

     {

         return FindItemRecusive(key,m_Root);

     }

 

     /********************************************************************

     创建时间:      2008/08/24

     函数功能:      将key处的值设置为value,未找到则插入

 

     输入参数:     

     输出参数:      1:成功0:失败

     ********************************************************************/

     int SetAt(First key,Second value)

     {

         CC_MapItem<First,Second>* itemFind = FindItemRecusive(key,m_Root);

         if(itemFind//找到了

         {

              itemFind->SetSecond(value);

              return 1;

         }

         else

         {

              itemFind = new CC_MapItem<First,Second>;

              if(!itemFind) return 0;

              itemFind->MakePair(key,value);

              Insert(*itemFind);

 

              //释放刚才new的item

              delete itemFind;

              itemFind = NULL;

 

              return 1;

         }

     }

 

     /********************************************************************

     创建时间:      2008/08/24

     函数功能:      用于删除操作

    

     输入参数:      flag: -1左1右

     输出参数:      1:成功0:失败-1:未找到

     ********************************************************************/

     int SearchItemForDel(CC_MapItem<First,Second>* root,First key,CC_MapItem<First,Second>** item,CC_MapItem<First,Second>** parent,int* flag)

     {   

         if((*item) == NULL) return 0;

         if((*parent) == NULL) return 0;

         while(root)

         {

              if(key < root->GetFirst())

              {

                   *parent = *item;

                   *item = (*item)->m_pLeft;

                   *flag = -1;

                   return SearchItemForDel(root->m_pLeft,key,item,parent,flag);

              }

              else if(key > root->GetFirst())

              {

                   *parent = *item;

                   *item = (*item)->m_pRight;

                   *flag = 1;

                   return SearchItemForDel(root->m_pRight,key,item,parent,flag);

              }

              else

              {

                   return 1;

              }

         }

 

         return -1;

     }

 

     /********************************************************************

     创建时间:      2008/08/24

     函数功能:      删除某个节点

 

     输入参数:     

     输出参数:     

     ********************************************************************/

     void DeleteItem(CC_MapItem<First,Second>* item)

     {

         if(item//判断是否为NULL

         {

              if(item->m_pLeft)    //如果左子树不为空

              {

                   CC_MapItem<First,Second>* pCur = item->m_pLeft;

                   CC_MapItem<First,Second>* pPre = item->m_pLeft;

 

                   while(pCur->m_pRight)

                   {

                       pPre = pCur;

                       pCur = pCur->m_pRight;

                   }

 

                   item->SetFirst(pCur->GetFirst());

                   item->SetSecond(pCur->GetSecond());

 

                   if(pPre != pCur)

                       pPre->m_pRight = pCur->m_pLeft;

                   else

                       item->m_pLeft = pCur->m_pLeft;

 

                   delete(pCur);

                   pCur = NULL;

              }

              else

              {

                   /*CC_MapItem<First,Second>* q = item;

                   item = item->m_pRight;

                   delete q;

                   q = NULL;*/

 

                   CC_MapItem<First,Second>* currentItem = m_Root;

                   CC_MapItem<First,Second>* parent = m_Root;

                   int flag = 0;

 

                   SearchItemForDel(m_Root,item->GetFirst(),&currentItem,&parent,&flag);

                   if(item == parent)

                       m_Root = m_Root->m_pRight;

                   else

                   {

                       if(flag == -1)

                            parent->m_pLeft = currentItem->m_pRight;

                       else if(flag == 1)

                            parent->m_pRight = currentItem->m_pRight;

 

                       delete item;

                       item = NULL;

                   }

              }

         }

     }

 

     /********************************************************************

     创建时间:      2008/08/24

     函数功能:      删除某个节点

 

     输入参数:     

     输出参数:     

     ********************************************************************/

     void DeleteItem(CC_MapItem<First,Second>* item,CC_MapItem<First,Second>* parent,int flag)

     {

         if(item//判断是否为NULL

         {

              if(item->m_pLeft)    //如果左子树不为空

              {

                   CC_MapItem<First,Second>* pCur = item->m_pLeft;

                   CC_MapItem<First,Second>* pPre = item->m_pLeft;

 

                   while(pCur->m_pRight)

                   {

                       pPre = pCur;

                       pCur = pCur->m_pRight;

                   }

 

                   item->SetFirst(pCur->GetFirst());

                   item->SetSecond(pCur->GetSecond());

 

                   if(pPre != pCur)

                       pPre->m_pRight = pCur->m_pLeft;

                   else

                       item->m_pLeft = pCur->m_pLeft;

 

                   delete(pCur);

                   pCur = NULL;

              }

              else

              {

                   if(item == parent)

                       m_Root = m_Root->m_pRight;

                   else

                   {

                       if(flag == -1)

                            parent->m_pLeft = item->m_pRight;

                       else if(flag == 1)

                            parent->m_pRight = item->m_pRight;

 

                       delete item;

                       item = NULL;

                   }

              }

         }

     }

 

     /********************************************************************

     创建时间:      2008/08/24

     函数功能:      根据key找到某项,然后删除

 

     输入参数:     

     输出参数:     

     ********************************************************************/

     void Delete(First key)

     {

         CC_MapItem<First,Second>* item = m_Root;

         CC_MapItem<First,Second>* parent = m_Root;

         int flag = 0;

        

         SearchItemForDel(m_Root,key,&item,&parent,&flag);

 

         DeleteItem(item,parent,flag);

     };

public:

     ~CC_Map(void)

     {

         Release(m_Root);

     };

 

private:

     CC_MapItem<First,Second>* m_Root;

 

     //释放内存,后序遍历

     void Release(CC_MapItem<First,Second>* item)

     {

         if(item)

         {

              Release(item->m_pLeft);

              Release(item->m_pRight);

              delete item;

              item = NULL;

         }

     }

 

     //中序遍历

     void TraversalRecusive(CC_MapItem<First,Second>* item,void(*callback)(CC_MapItem<First,Second>*))

     {

         if(item)

         {

              TraversalRecusive(item->m_pLeft,callback);

              callback(item);

              TraversalRecusive(item->m_pRight,callback);

         }

     }

 

     //搜索

     Second FindRecusive(First key,CC_MapItem<First,Second>* root)

     {

         if(root)

         {

              if(key < root->GetFirst())

                   return FindRecusive(key,root->m_pLeft);

              else if(key > root->GetFirst())

                   return FindRecusive(key,root->m_pRight);

              else

                   return root->GetSecond();

         }

 

         return -1;

     }

 

     //搜索

     CC_MapItem<First,Second>* FindItemRecusive(First key,CC_MapItem<First,Second>* root)

     {

         if(root)

         {

              if(key < root->GetFirst())

                   return FindItemRecusive(key,root->m_pLeft);

              else if(key > root->GetFirst())

                   return FindItemRecusive(key,root->m_pRight);

              else

                   return root;

         }

 

         return NULL;

     }

};

 

 

使用:

 

ContractedBlock.gifExpandedBlockStart.gifCode


CC_Map
<int,int> pMap;

 CC_MapItem
<int,int> b0;
 b0.MakePair(
5,3);

 CC_MapItem
<int,int> b1;
 b1.MakePair(
7,12);

 CC_MapItem
<int,int> b2;
 b2.MakePair(
1,87);

 CC_MapItem
<int,int> b3;
 b3.MakePair(
5,234);

 CC_MapItem
<int,int> b4;
 b4.MakePair(
3,16);

 CC_MapItem
<int,int> b5;
 b5.MakePair(
2,11);

 CC_MapItem
<int,int> b6;
 b6.MakePair(
8,123);

 CC_MapItem
<int,int> b7;
 b7.MakePair(
7,324);

 pMap.Insert(b0);
 pMap.Insert(b1);
 pMap.Insert(b2);
 pMap.Insert(b3);
 pMap.Insert(b4);
 pMap.Insert(b5);
 pMap.Insert(b6);
 pMap.Insert(b7);

 
//回调函数遍历
 
//void(*p)(CC_MapItem<int,int>* item) = CallBack;
 
//pMap.Traversal(p);

 
//查找
 int value = pMap.Find(3);

 
//设置
 pMap.SetAt(9,132);
 value 
= pMap.Find(9);

 
//删除节点
 pMap.Delete(7);

 

转载于:https://www.cnblogs.com/whu-gy/archive/2008/08/24/1275076.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值