【C++】使用AVL平衡树实现一个类似STL的Map

我才学完AVL,感觉AVL好像能实现类似map这样的功能,于是做了这样一个模板类。(后来知道stl的map也是用平衡树实现的,但是是用内建的红黑树,更高级一点)

#include <iostream>
#include <cstdio>
#include <string>
using namespace std;

/*
Map使用起来就像一个强大的数组,但是你不需要事先声明它的范围,它的下标可以任意地大(不溢出);甚至不局限于整数,你甚至可以
用float、double、结构体、类(注1)作为它的下标,然后来访问它。
另外,即使你的下标很大,但是它所使用的空间只与你使用过的有关!
例如:
    a1[2032974248889]=90;
    a2[2389.5353]=34;
都是可以实现的。


Map实质上是个映射集。从它的下标(下面我们称为关键字),映射到对应的值。
声明一个Map,它可以存储若干映射,你可以通过关键字来访问这些映射。

使用:
1.定义
        Map<关键字类型,映射值类型> 变量名;
    用这样的形式来定义Map;
    例如:
        Map<int, char> a;

2.添加映射(赋值)
    下面两个方式都是可以的。
        a[299342]='S';
        a.MappingAt(299342)='S';

3.单个访问
        printf("%c",a[299342]);
    如果这个关键字之前并未出现,但你使用了它,那么自动创建这个映射,它的值为默认值。

4.连续访问
        连续访问不建议用a[i]这样的形式来访问。因为定位一个关键字需要时间(O(logN),N为a中所有映射的个数),尽管它不算耗时。
        但是使用迭代器,进行连续访问,时间复杂度是O(N)(由于数据结构,事实上每个节点会在迭代过程中访问两遍,但是编程者无需关心。)
        a的迭代器it是这样声明的:
        a.Iterator it;
        for(it=a.Begin();it!=a.End;it=it->Next())
        {
            printf("%d ",it->Value);
        }
        Begin()返回a中第一个映射指针,End是最后一个映射的下一个无效的指针。Next()返回下一个映射指针。
        他们是按照关键字的大小顺序排列的。

        逆序的话,是这样的:
        for(it=a.End->Last;it!=End;it=it->Last())
        {
            printf("%d ",it->Value);
        }
        !无论是逆序或正序迭代,最后都是在End结束。

        *请留意Begin()是方法函数,但End是指针变量。
5.删除映射
        对于迭代器it
        使用Delete(it);
        或者关键字x
        使用Delete(x);
        如果这个关键字没有使用过,即没有对应的映射值,将不会做任何操作。



这个Map是用查找树来存储映射的。查找树使用AVL来维护平衡。




注1:
    如果关键字类型是结构体或类的话,你需要定义大小比较和判断相等的重载操作符(> < ==)。
    或者建议写一个函数,将这个特殊类型转换成数值,将这个数值作为关键字类型,便于比较。例如字符串就可以这样。

*/
template <class KeyType,class ValueType>
class Map
{
public:
    struct Treenode
    {
        Treenode *Left=nullptr;
        Treenode *Right=nullptr;
        Treenode *Father=nullptr;
        KeyType Key;
        ValueType Value;
        int Height=1;
        int GetHeight()
        {
            int lh=Left==nullptr?0:Left->Height;
            int rh=Right==nullptr?0:Right->Height;
            Height=lh>rh?lh+1:rh+1;
            return Height;
        }
        void AddToLeft(Treenode *T)
        {
            Left=T;
            T->Father=this;
        }
        void AddToRight(Treenode *T)
        {
            Right=T;
            T->Father=this;
        }
        void RemoveFromTree()
        {
            if(this==Father->Left)Father->Left=nullptr;
            else Father->Right=nullptr;
        }
        Treenode* Next()
        {
            Treenode* p;
            if(Right==nullptr)
            {
                p=Father;
                while(p->Key<Key&&p->Father!=nullptr)
                    p=p-&
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值