4

用c++实现一把golang里面的map数据类型

 2 years ago
source link: https://studygolang.com/articles/35160
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

因为之前写过一篇golang 数据类型分析的文章。包含slice、map、channel等。 想写一篇用其它语言实现golang数据类型的代码,于是选中map作为实验对象。 笔者之前写过5年的c++, 虽然 c++代码大概有3年没有写过了,但还是想试一试(可能是手痒痒。虽然写go很开心,但是也没有说对c++过河拆桥,偶尔还会想起以前gdb、makefile、linux kernel codeing、对照汇编指令集的日子)。 于是一边百度c++恢复功力,一边实现本文的代码,竟然大概用了2个小时。 目前实现的功能有:创建map(支持任意数据类型)、插入数据(自动扩容)、查询数据。数据删除和数据资源回收(在golang中是GC,在c++中就是析构函数对对象进行释放)后面有空再实现,时间不早准备休息了。

目录结构:

在这里插入图片描述

c++代码:

// main.cc

#include <iostream>
#include <string>
#include <string.h>
#include <stdlib.h>
#include <limits>
#include <time.h>   // for nanosleep
#include <sys/time.h>   // for gettimeofday

using namespace std;
using std::hash;
using std::string;
using std::cout;



class S {
        public:
                string first_name;
                string last_name;
};

template<typename S>
class myhash 
{
        public:
                size_t operator()(const S &s) const
                {
                        size_t h1 = hash<string>()(s.first_name);
                        size_t h2 = hash<string>()(s.last_name);
                        return h1 ^ (h2 << 1);
                }
};


template<typename KEY, typename VALUE>
class bmap {
public:
        char topbits;
        KEY key[8];
        VALUE values[8];
        //pad      uintptr
        //
        void * overflow;
};

template<typename KEY, typename VALUE>  
class TangMap
{
        typedef bmap<KEY, VALUE> slot_node;
        public:
                TangMap(int slot_len=8) {
                        slot_num= slot_len;
                        buckets = (slot_node *)malloc(sizeof(slot_node) * slot_num);
                        slot_node * it = (slot_node *)buckets;
                        for (auto i=0; i<slot_num; i++) {
                                it->overflow = NULL;
                        }
                        count = 0;
                        //cout << "----:" << slot_num << endl;
                        printf("%p", buckets);
                }
                ~TangMap() {
                        cout << "destruction function is invoked!" << endl;
                }

                void insert(KEY key, VALUE val) {
                        hash<KEY> hash_fn;
                        size_t slot_index = (hash_fn(key) & 0xff) % slot_num;
                        size_t subslot_index = ((hash_fn(key) >> 8) & 0xff) % slot_num;
                        cout << "slot_index is:" << slot_index << ", subslot_index is:" << subslot_index << endl;
                        auto it = &buckets[slot_index]; // 获取槽位头节点
                        for (;;) {
                                if (it->topbits & (1 << subslot_index)) {
                                        cout << "--->bmap can not insert into this node" << endl;
                                        if (it->overflow != NULL) {
                                                it = (slot_node *)it->overflow;
                                                continue;
                                        } else {
                                                auto node = new(slot_node);
                                                node->overflow = NULL;
                                                it->overflow = node;

                                                it->key[subslot_index] = key;
                                                it->values[subslot_index] = val;
                                                it->topbits |= 1 << subslot_index;
                                                count++;
                                                break;
                                        }
                                } else {
                                        cout << "bmap can insert into this node" << endl;
                                        it->key[subslot_index] = key;
                                        it->values[subslot_index] = val;
                                        it->topbits |= 1 << subslot_index;
                                        printf("it->topbits=%d\r\n", it->topbits);
                                        count++;
                                        break;
                                }
                        }

                        printf("it->topbits=%d\r\n", it->topbits);
                }


                VALUE * operator[](KEY key) {
                        hash<KEY> hash_fn;
                        size_t slot_index = (hash_fn(key) & 0xff) % slot_num;
                        size_t subslot_index = ((hash_fn(key) >> 8) & 0xff) % slot_num;
                        cout << "slot_index is:" << slot_index << ", subslot_index is:" << subslot_index << endl;
                        auto it = &buckets[slot_index]; // 获取槽位头节点
                        for (;;) {
                                if (it->topbits & (1 << subslot_index)) {
                                        if (key == it->key[subslot_index]) {
                                                cout << "find key!" << endl;
                                                return &it->values[subslot_index];
                                        } else {
                                                if (it->overflow != NULL) {
                                                        it = (slot_node *)it->overflow;
                                                        continue;
                                                } else {
                                                        return NULL;
                                                }
                                        }
                                } else {
                                        if (it->overflow != NULL) {
                                                it = (slot_node *)it->overflow;
                                                continue;
                                        } else {
                                                return NULL;
                                        }
                                }
                        }
                }

                // 元素个数,调用 len(map) 时,直接返回此值
                int count;     
                char        flags;    
                int slot_num;         // buckets 的对数 log_2

                slot_node * buckets;    // 指向内存的指针,可以看作是:[]bmap。   其大小为 2^B. 如果元素个数为0,就为 nil

                void *extra;
};


inline int randf(void)
{
        struct timespec tim;
        tim.tv_sec=0; tim.tv_nsec=1e4;
        nanosleep(&tim, 0);
        struct timeval cur;
        gettimeofday(&cur, 0);
        srand(cur.tv_usec);
        return rand()/float(RAND_MAX);
}


string randstr(char *str, const int len)
{
        srand(time(NULL));
        int i;
        for (i = 0; i < len; ++i)
        {
                switch ((randf() % 3))
                {
                        case 1:
                                str[i] = 'A' + randf() % 26;
                                break;
                        case 2:
                                str[i] = 'a' + randf() % 26;
                                break;
                        default:
                                str[i] = '0' + randf() % 10;
                                break;
                }
        }
        str[++i] = '\0';
        return str;
}


int main(int arcg, char **argv) {
        const int LEN_NAME=40;
        char name[LEN_NAME+1];
        TangMap<std::string,string> obj;
        for (auto i=0; i<40; i++) {
                auto key = "key" + std::to_string(i);
                auto val = "value" + std::to_string(i);
                obj.insert(key, val);

                auto v = obj[key];
                printf("val is:%s, v is:%s\r\n\r\n",  val.c_str(), v->c_str());
        }
}

编译执行:

root@ubuntu:~/zz/map# g++ main.cc 
root@ubuntu:~/zz/map# 
root@ubuntu:~/zz/map# ./a.out 
0x55ef79a2ce70slot_index is:4, subslot_index is:2
bmap can insert into this node
it->topbits=4
it->topbits=4
slot_index is:4, subslot_index is:2
find key!
val is:value0, v is:value0

slot_index is:2, subslot_index is:2
bmap can insert into this node
it->topbits=4
it->topbits=4
slot_index is:2, subslot_index is:2
find key!
val is:value1, v is:value1

slot_index is:4, subslot_index is:6
bmap can insert into this node
it->topbits=68
it->topbits=68
slot_index is:4, subslot_index is:6
find key!
val is:value2, v is:value2

slot_index is:2, subslot_index is:6
bmap can insert into this node
it->topbits=68
it->topbits=68
slot_index is:2, subslot_index is:6
find key!
val is:value3, v is:value3

slot_index is:6, subslot_index is:2
bmap can insert into this node
it->topbits=4
it->topbits=4
slot_index is:6, subslot_index is:2
find key!
val is:value4, v is:value4

slot_index is:0, subslot_index is:0
bmap can insert into this node
it->topbits=1
it->topbits=1
slot_index is:0, subslot_index is:0
find key!
val is:value5, v is:value5

slot_index is:7, subslot_index is:1
bmap can insert into this node
it->topbits=2
it->topbits=2
slot_index is:7, subslot_index is:1
find key!
val is:value6, v is:value6

slot_index is:5, subslot_index is:3
bmap can insert into this node
it->topbits=8
it->topbits=8
slot_index is:5, subslot_index is:3
find key!
val is:value7, v is:value7

slot_index is:4, subslot_index is:5
bmap can insert into this node
it->topbits=100
it->topbits=100
slot_index is:4, subslot_index is:5
find key!
val is:value8, v is:value8

slot_index is:3, subslot_index is:6
bmap can insert into this node
it->topbits=64
it->topbits=64
slot_index is:3, subslot_index is:6
find key!
val is:value9, v is:value9

slot_index is:5, subslot_index is:0
bmap can insert into this node
it->topbits=9
it->topbits=9
slot_index is:5, subslot_index is:0
find key!
val is:value10, v is:value10

slot_index is:5, subslot_index is:7
bmap can insert into this node
it->topbits=-119
it->topbits=-119
slot_index is:5, subslot_index is:7
find key!
val is:value11, v is:value11

slot_index is:0, subslot_index is:0
--->bmap can not insert into this node
it->topbits=1
slot_index is:0, subslot_index is:0
find key!
val is:value12, v is:value12

slot_index is:7, subslot_index is:2
bmap can insert into this node
it->topbits=6
it->topbits=6
slot_index is:7, subslot_index is:2
find key!
val is:value13, v is:value13

slot_index is:4, subslot_index is:4
bmap can insert into this node
it->topbits=116
it->topbits=116
slot_index is:4, subslot_index is:4
find key!
val is:value14, v is:value14

slot_index is:3, subslot_index is:1
bmap can insert into this node
it->topbits=66
it->topbits=66
slot_index is:3, subslot_index is:1
find key!
val is:value15, v is:value15

slot_index is:4, subslot_index is:1
bmap can insert into this node
it->topbits=118
it->topbits=118
slot_index is:4, subslot_index is:1
find key!
val is:value16, v is:value16

slot_index is:3, subslot_index is:5
bmap can insert into this node
it->topbits=98
it->topbits=98
slot_index is:3, subslot_index is:5
find key!
val is:value17, v is:value17

slot_index is:6, subslot_index is:1
bmap can insert into this node
it->topbits=6
it->topbits=6
slot_index is:6, subslot_index is:1
find key!
val is:value18, v is:value18

slot_index is:6, subslot_index is:6
bmap can insert into this node
it->topbits=70
it->topbits=70
slot_index is:6, subslot_index is:6
find key!
val is:value19, v is:value19

slot_index is:6, subslot_index is:1
--->bmap can not insert into this node
it->topbits=70
slot_index is:6, subslot_index is:1
find key!
val is:value20, v is:value20

slot_index is:2, subslot_index is:1
bmap can insert into this node
it->topbits=70
it->topbits=70
slot_index is:2, subslot_index is:1
find key!
val is:value21, v is:value21

slot_index is:5, subslot_index is:2
bmap can insert into this node
it->topbits=-115
it->topbits=-115
slot_index is:5, subslot_index is:2
find key!
val is:value22, v is:value22

slot_index is:5, subslot_index is:7
--->bmap can not insert into this node
it->topbits=-115
slot_index is:5, subslot_index is:7
find key!
val is:value23, v is:value23

slot_index is:0, subslot_index is:4
bmap can insert into this node
it->topbits=17
it->topbits=17
slot_index is:0, subslot_index is:4
find key!
val is:value24, v is:value24

slot_index is:5, subslot_index is:3
--->bmap can not insert into this node
bmap can insert into this node
it->topbits=8
it->topbits=8
slot_index is:5, subslot_index is:3
find key!
val is:value25, v is:value25

slot_index is:7, subslot_index is:2
--->bmap can not insert into this node
it->topbits=6
slot_index is:7, subslot_index is:2
find key!
val is:value26, v is:value26

slot_index is:6, subslot_index is:7
bmap can insert into this node
it->topbits=-58
it->topbits=-58
slot_index is:6, subslot_index is:7
find key!
val is:value27, v is:value27

slot_index is:0, subslot_index is:2
bmap can insert into this node
it->topbits=21
it->topbits=21
slot_index is:0, subslot_index is:2
find key!
val is:value28, v is:value28

slot_index is:1, subslot_index is:1
bmap can insert into this node
it->topbits=2
it->topbits=2
slot_index is:1, subslot_index is:1
find key!
val is:value29, v is:value29

slot_index is:0, subslot_index is:4
--->bmap can not insert into this node
bmap can insert into this node
it->topbits=16
it->topbits=16
slot_index is:0, subslot_index is:4
find key!
val is:value30, v is:value30

slot_index is:7, subslot_index is:1
--->bmap can not insert into this node
bmap can insert into this node
it->topbits=2
it->topbits=2
slot_index is:7, subslot_index is:1
find key!
val is:value31, v is:value31

slot_index is:6, subslot_index is:1
--->bmap can not insert into this node
bmap can insert into this node
it->topbits=2
it->topbits=2
slot_index is:6, subslot_index is:1
find key!
val is:value32, v is:value32

slot_index is:3, subslot_index is:5
--->bmap can not insert into this node
it->topbits=98
slot_index is:3, subslot_index is:5
find key!
val is:value33, v is:value33

slot_index is:7, subslot_index is:5
bmap can insert into this node
it->topbits=38
it->topbits=38
slot_index is:7, subslot_index is:5
find key!
val is:value34, v is:value34

slot_index is:2, subslot_index is:4
bmap can insert into this node
it->topbits=86
it->topbits=86
slot_index is:2, subslot_index is:4
find key!
val is:value35, v is:value35

slot_index is:7, subslot_index is:1
--->bmap can not insert into this node
--->bmap can not insert into this node
it->topbits=2
slot_index is:7, subslot_index is:1
find key!
val is:value36, v is:value36

slot_index is:5, subslot_index is:0
--->bmap can not insert into this node
bmap can insert into this node
it->topbits=9
it->topbits=9
slot_index is:5, subslot_index is:0
find key!
val is:value37, v is:value37

slot_index is:0, subslot_index is:4
--->bmap can not insert into this node
--->bmap can not insert into this node
it->topbits=16
slot_index is:0, subslot_index is:4
find key!
val is:value38, v is:value38

slot_index is:4, subslot_index is:4
--->bmap can not insert into this node
it->topbits=118
slot_index is:4, subslot_index is:4
find key!
val is:value39, v is:value39

destruction function is invoked!
root@ubuntu:~/zz/map#

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK