在STL里有map,在MFC里有CMap,它们都是通过模板来构造这样一种结构,即可以将<key,value>键值对存储进来。对于键值对的存储会使用到某种数据结构,来达到快速存储与搜索的目的。
本文中使用二叉排序树来构造类CC_Map,具有插入、删除、搜索节点等基本功能。定义节点类CMapItem,它也是一个模板类,其中可以存储<key,value>,key和value的数据类型通过模板参数来定义。在CMapItem里重载了>,<,==,=等基本操作符,用于节点大小的比较。如果key、value为用户自定义类型,例如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(),¤tItem,&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;
}
};
使用:


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);