zoukankan      html  css  js  c++  java
  • C 工具库8:map

    本篇介绍另外一个在C++ stl中常用的容器map.


    我打算将map的实现容器和map接口分开,创建map的时候可以传递一个实现了interface_map_container接口的对象指针进来,如果这个参数
    传0,则默认使用红黑树做实际的容器.


    这样做的好处是用户可以根据性能需求传递自己定制的容器类.例如在游戏程序中常见的数据表.一般通过一个索引查询,并且在程序启动时候
    将数据全部加载好,在以后的运行中,只会对数据进行查询,不会做任何修改的动作.在这种情况下,使用一个数组存放key,val对,再加载完成后
    对数组排序,后面查询的时候使用2分法,显然比用红黑树或其它的二叉平衡树效率更高.


    好了,下面介绍map的实现,首先定义了迭代器:

    typedef struct map_iter
    {
    void *node;
    struct map_iter (*next)(struct map_iter*);
    void (*get_first)(struct map_iter,void*);
    void (*get_second)(struct map_iter,void*);
    void (*set_second)(struct map_iter,void*);
    }map_iter;

    迭代器定义了4个函数指针,分别用来获得后继迭代器,get key的值,以及get/set value.这四个函数是由各container类型负责的,例如红黑
    数的next是由函数RB_iter_next实现的,它获取当前节点的后续节点.如果container是上面所说的数组实现的则next仅需增加下标,并返回
    所指向的元素便可.


    然后是container的接口:

    struct interface_map_container
    {
    map_iter (*insert)(struct interface_map_container*,void*,void*);
    map_iter (*erase)(struct interface_map_container*,map_iter);
    void (*remove)(struct interface_map_container* rb,void*);
    map_iter (*find)(struct interface_map_container* rb,void *);
    map_iter (*begin)(struct interface_map_container* rb);
    map_iter (*end)(struct interface_map_container* rb);
    int (*size)(struct interface_map_container*);
    int (*empty)(struct interface_map_container*);
    void (*destroy)(struct interface_map_container**);
    };

    所有希望作为map底层存储容器的类型都必须实现interface_map_container接口定义的函数.


    最后是map的默认容器红黑树,红黑树是一种复杂的数据结构,其具体定义及特性在这里就不介绍了,想要了解可以参考<算法导论>或<算法:C语言实现>.

    不过这里还是推荐看wiki里的这个介绍,http://zh.wikipedia.org/wiki/%E7%BA%A2%E9%BB%91%E6%A0%91思想跟算法导论中是一样的,但是更简单

    易懂(至少我是这么认为的,算法导论中对删除部分的处理看了半天还是似懂非懂,看过wiki的文章后立马就全都明白了)



    下面介绍下红黑树实现方式的选择,<算法:C语言实现>中使用的是左倾斜红节点,这种实现方式相当直观,其插入和删除操作也很好理解.但是这在实现find和
    erase的时候就性能差一点了.


    我希望和C++ stl中的操作类似,find返回一个迭代器,将这个跌代器传入erase可以删除这个节点.在<算法:C语言实现>删除的过程是自顶向下,沿搜索路径,
    将遇到的所有2 node转变成3或4 node这样使得在删除时容易处理.显然,在find中,这个过程是不需要的,只有在erase过程中才需要.这使得至少需要沿搜索路
    径查找两次(一次在find的时候,一次在erase的时候).而<算法导论>中的实现就没有这个问题,可以直接传入迭代器,无须而外的搜索就可以删除目标节点.


    最后贴上代码. 

    rbtree.h

    #ifndef _RBTREE_H
    #define _RBTREE_H
    #include "map.h"

    typedef struct RBtree *RBtree_t;
    extern RBtree_t RBtree_create(unsigned short,unsigned short,comp _comp);


    struct interface_map_container;
    extern void RBtree_destroy(struct interface_map_container**);

    ///检查是否有违反红黑树性质
    extern void RBtree_check_vaild(RBtree_t);
    #endif

    rbtree.c

    #include "RBtree.h"
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <assert.h>
    #include "map.h"

    typedef struct RBnode
    {
    struct RBnode *parent;
    struct RBnode *left;
    struct RBnode *right;
    RBtree_t tree;
    unsigned short color;
    unsigned short key_size;
    unsigned short val_size;
    char data[1];//key & value
    }RBnode;

    #ifndef IMPLEMEMT
    #define IMPLEMEMT(SUPER_CLASS) struct SUPER_CLASS super_class
    #endif

    struct RBtree
    {
    IMPLEMEMT(interface_map_container);
    RBnode *root;
    RBnode *nil;
    unsigned int size;
    unsigned short key_size;
    unsigned short val_size;
    comp compare_function;
    RBnode dummy;//nil节点
    };

    #define RED 1
    #define BLACK 2

    //节点数据操作
    inline static void *get_key(RBnode *n)
    {
    assert(n);
    return (void*)(n->data);
    }

    inline static void *get_value(RBnode *n)
    {
    assert(n);
    return (void*)(&(n->data[n->key_size]));
    }

    inline static void copy_key(RBnode *n,void *key)
    {
    memcpy(get_key(n),key,n->key_size);
    }

    inline static void copy_value(RBnode *n,void *value)
    {
    memcpy(get_value(n),value,n->val_size);
    }

    inline static int less(RBtree_t rb,void *left,void *right)
    {
    return rb->compare_function(left,right) == -1;
    }

    inline static int equal(RBtree_t rb,void *left,void *right)
    {
    return rb->compare_function(left,right) == 0;
    }

    inline static int more(RBtree_t rb,void *left,void *right)
    {
    return rb->compare_function(left,right) == 1;
    }

    extern map_iter RBtree_insert(struct interface_map_container *,void*,void*);
    extern map_iter RBtree_erase(struct interface_map_container *,map_iter);
    extern void RBtree_delete(struct interface_map_container *,void*);
    extern map_iter RBtree_find(struct interface_map_container *,void *);
    extern map_iter RBtree_begin(struct interface_map_container *);
    extern map_iter RBtree_end(struct interface_map_container *);
    extern int RBtree_size(struct interface_map_container *);
    extern int RBtree_empty(struct interface_map_container *);

    RBtree_t RBtree_create(unsigned short key_size,unsigned short val_size,comp _comp)
    {
    struct RBtree *rb = malloc(sizeof(*rb));
    if(rb)
    {
    rb->size = 0;
    rb->dummy.color = BLACK;
    rb->nil = &rb->dummy;
    rb->nil->tree = rb;
    rb->root = rb->nil;
    rb->key_size = key_size;
    rb->val_size = val_size;
    rb->compare_function = _comp;
    rb->super_class.insert = RBtree_insert;
    rb->super_class.erase = RBtree_erase;
    rb->super_class.remove = RBtree_delete;
    rb->super_class.find = RBtree_find;
    rb->super_class.begin = RBtree_begin;
    rb->super_class.end = RBtree_end;
    rb->super_class.size = RBtree_size;
    rb->super_class.empty = RBtree_empty;
    rb->super_class.destroy = RBtree_destroy;
    }
    return rb;
    }

    void RBtree_destroy(struct interface_map_container **_rb)
    {

    }

    /*
    * 左右旋转
    */
    static RBnode *rotate_left(RBtree_t rb,RBnode *n)
    {
    RBnode *parent = n->parent;
    RBnode *right = n->right;
    if(right == rb->nil)
    return;

    n->right = right->left;
    right->left->parent = n;

    if(n == rb->root)
    rb->root = right;
    else
    {
    if(n == parent->left)
    parent->left = right;
    else
    parent->right = right;
    }
    right->parent = parent;
    n->parent = right;
    right->left = n;
    }


    static RBnode *rotate_right(RBtree_t rb,RBnode *n)
    {
    RBnode *parent = n->parent;
    RBnode *left = n->left;
    if(left == rb->nil)
    return;
    n->left = left->right;
    left->right->parent = n;

    if(n == rb->root)
    rb->root = left;
    else
    {
    if(n == parent->left)
    parent->left = left;
    else
    parent->right = left;
    }
    left->parent = parent;
    n->parent = left;
    left->right = n;
    }

    inline static void color_flip(RBnode *n)
    {
    if(n->left && n->right)
    {
    n->color = RED;
    n->left->color = n->right->color = BLACK;
    }
    }

    static void insert_fix_up(RBtree_t rb,RBnode *n)
    {
    while(n->parent->color == RED)
    {
    RBnode *parent = n->parent;
    RBnode *grand_parent = parent->parent;
    if(parent == grand_parent->left)
    {
    RBnode *ancle = grand_parent->right;
    if(ancle->color == RED)
    {
    //叔叔节点是红色,执行一次颜色翻转
    color_flip(grand_parent);
    n = grand_parent;
    }
    else
    {
    if(n == parent->right)
    {
    n = parent;
    rotate_left(rb,n);
    }

    n->parent->color = BLACK;
    n->parent->parent->color = RED;
    rotate_right(rb,n->parent->parent);
    }
    }
    else
    {
    RBnode *ancle = grand_parent->left;
    if(ancle->color == RED)
    {
    //叔叔节点是红色,执行一次颜色翻转
    color_flip(grand_parent);
    n = grand_parent;
    }
    else
    {
    if(n == parent->left)
    {
    n = parent;
    rotate_right(rb,n);
    }
    n->parent->color = BLACK;
    n->parent->parent->color = RED;
    rotate_left(rb,n->parent->parent);
    }
    }
    }
    rb->root->color = BLACK;
    }

    static RBnode *find(RBtree_t rb,void *key)
    {
    if(rb->root == rb->nil)
    return rb->nil;
    RBnode *cur = rb->root;
    RBnode *pre;
    while(cur != rb->nil)
    {
    pre = cur;
    if(equal(rb,key,get_key(cur)))
    return cur;
    if(less(rb,key,get_key(cur)))
    cur = cur->left;
    else
    cur = cur->right;
    }
    return pre;
    }

    RBnode *create_node(RBtree_t rb,void *key,void *value)
    {

    RBnode *n = malloc(sizeof(*n) + rb->key_size + rb->val_size - 1);
    n->key_size = rb->key_size;
    n->val_size = rb->val_size;
    copy_key(n,key);
    copy_value(n,value);
    return n;
    }

    inline static RBnode *minimum(RBtree_t rb,RBnode *n)
    {
    while(n->left != rb->nil)
    n = n->left;
    return n;
    }

    inline static RBnode *maxmum(RBtree_t rb,RBnode *n)
    {
    while(n->right != rb->nil)
    n = n->right;
    return n;
    }

    //获得n的后继节点,为根节点的情况下返回nil
    static RBnode *successor(RBtree_t rb,RBnode *n)
    {
    assert(rb);
    if(n->right != rb->nil)
    return minimum(rb,n->right);
    RBnode *y = n->parent;
    while(y != rb->nil && n == y->right)
    {
    n = y;
    y = y->parent;
    }
    return y;
    }

    //获得n的前驱节点,为根节点的情况下返回nil
    static RBnode *predecessor(RBtree_t rb,RBnode *n)
    {
    assert(rb);
    if(n->left != rb->nil)
    return maxmum(rb,n->left);
    RBnode *y = n->parent;
    while(y != rb->nil && n == y->left)
    {
    n = y;
    y = y->parent;
    }
    return y;

    }

    static RBnode *get_delete_node(RBtree_t rb,RBnode *n)
    {
    if(n->left == rb->nil && n->right == rb->nil)
    return n;
    else if(n->right != rb->nil)
    return minimum(rb,n->right);
    else
    return maxmum(rb,n->left);
    }

    static void delete_fix_up(RBtree_t rb,RBnode *n)
    {
    while(n != rb->root && n->color != RED)
    {
    RBnode *p = n->parent;
    if(n == p->left)
    {
    RBnode *w = p->right;
    if(w->color == RED)//兄弟为红
    {
    w->color = BLACK;
    p->color = RED;
    rotate_left(rb,p);
    w = p->right;
    }
    //兄弟为黑
    if(w->left->color == BLACK && w->right->color == BLACK)
    {
    //兄弟的两儿子为黑
    w->color = RED;
    n = p;
    }
    else
    {
    if(w->right->color == BLACK)
    {
    //兄弟的右孩子为黑
    w->left->color == BLACK;
    w->color = RED;
    rotate_right(rb,w);
    w = p->right;
    }
    //兄弟的右孩子为红
    w->color = p->color;
    p->color = BLACK;
    w->right->color = BLACK;
    rotate_left(rb,p);
    n = rb->root;
    }
    }
    else
    {
    RBnode *w = p->left;
    if(w->color == RED)
    {
    w->color = BLACK;
    p->color = RED;
    rotate_right(rb,p);
    w = p->left;
    }
    if(w->left->color == BLACK && w->right->color == BLACK)
    {
    w->color = RED;
    n = p;
    }
    else
    {
    if(w->left->color == BLACK)
    {
    w->right->color == BLACK;
    w->color = RED;
    rotate_left(rb,w);
    w = p->left;
    }
    w->color = p->color;
    p->color = BLACK;
    w->left->color = BLACK;
    rotate_right(rb,p);
    n = rb->root;
    }
    }
    }
    n->color = BLACK;
    }

    void rb_iter_get_first(map_iter iter,void *first)
    {
    RBnode *n = (RBnode*)iter.node;
    memcpy(first,get_key(n),n->key_size);
    }

    void rb_iter_get_second(map_iter iter,void *second)
    {
    RBnode *n = (RBnode*)iter.node;
    memcpy(second,get_value(n),n->val_size);
    }

    void rb_iter_set_second(map_iter iter,void *val)
    {
    RBnode *n = (RBnode*)iter.node;
    copy_value(n,val);
    }

    static map_iter RB_iter_next(struct map_iter *iter)
    {
    RBnode *n = (RBnode*)iter->node;

    RBtree_t rb = n->tree;

    if(iter->node == rb->nil)
    return (*iter);
    RBnode *succ = successor(rb,n);
    map_iter next ={0,RB_iter_next,rb_iter_get_first,rb_iter_get_second,rb_iter_set_second};
    if(!succ)
    next.node = rb->nil;
    else
    next.node = succ;
    return next;
    }


    map_iter RBtree_begin(struct interface_map_container *_rb)
    {
    RBtree_t rb = (RBtree_t)_rb;
    RBnode *min = minimum(rb,rb->root);
    map_iter begin = {0,RB_iter_next,rb_iter_get_first,rb_iter_get_second,rb_iter_set_second};
    begin.node = (min == 0 ? rb->nil : min);
    return begin;
    }

    map_iter RBtree_end(struct interface_map_container *_rb)
    {
    RBtree_t rb = (RBtree_t)_rb;
    map_iter end ={rb->nil,RB_iter_next,rb_iter_get_first,rb_iter_get_second,rb_iter_set_second};
    return end;
    }

    map_iter RBtree_find(struct interface_map_container *_rb,void *key)
    {
    RBtree_t rb = (RBtree_t)_rb;
    RBnode *n = find(rb,key);
    if(n == rb->nil || equal(rb,key,get_key(n)) == 0)
    return RBtree_end(_rb);

    map_iter it ={n,RB_iter_next,rb_iter_get_first,rb_iter_get_second,rb_iter_set_second};
    return it;
    }

    map_iter RBtree_insert(struct interface_map_container *_rb,void *key,void *val)
    {
    RBtree_t rb = (RBtree_t)_rb;
    assert(rb);
    RBnode *x = find(rb,key);
    if(x != rb->nil && equal(rb,key,get_key(x)))
    return RBtree_end(_rb);//不允许插入重复节点
    RBnode *n = create_node(rb,key,val);
    n->color = RED;
    n->left = n->right = rb->nil;
    n->tree = rb;

    if(x == rb->nil)
    {
    n->parent = rb->nil;
    rb->root = n;
    }
    else
    {
    n->parent = x;
    if(less(rb,key,get_key(x)))
    x->left = n;
    else
    x->right = n;
    }
    ++rb->size;
    insert_fix_up(rb,n);
    map_iter it ={n,RB_iter_next,rb_iter_get_first,rb_iter_get_second,rb_iter_set_second};
    return it;
    }

    static void rb_delete(RBtree_t rb,void *key,RBnode **succ)
    {
    assert(rb);
    RBnode *n = find(rb,key);
    if(equal(rb,key,get_key(n)))
    {
    RBnode *x = get_delete_node(rb,n);//获得实际被删除的节点

    if(succ)
    {
    if(x == n || less(rb,get_key(x),get_key(n)))
    *succ = successor(rb,x);
    else
    {
    //被删除节点是自己的后继,后继的数据回被拷贝到当前节点
    //所以删除以后,当前节点就是后继节点.
    *succ = n;
    }
    }
    RBnode *parent = x->parent;
    RBnode **link = (x == parent->left)? &(parent->left):&(parent->right);
    RBnode *z = rb->nil;
    if(x->left != rb->nil || x->right != rb->nil)
    {
    if(x->left != rb->nil)
    *link = x->left;
    else
    *link = x->right;
    z = *link;
    }
    else
    *link = rb->nil;

    z->parent = parent;
    if(n != x)
    {
    //拷贝数据
    copy_key(n,get_key(x));
    copy_value(n,get_value(x));
    }
    if(x != rb->root && x->color == BLACK)
    delete_fix_up(rb,z);
    if(x == rb->root)
    rb->root = rb->nil;
    free(x);
    --rb->size;
    }
    }

    void RBtree_delete(struct interface_map_container *_rb,void *key)
    {
    RBtree_t rb = (RBtree_t)_rb;
    rb_delete(rb,key,0);
    }

    /*
    * 删除当前节点返回后继节点的迭代器
    */
    map_iter RBtree_erase(struct interface_map_container *_rb,map_iter it)
    {
    RBtree_t rb = (RBtree_t)_rb;
    RBnode *succ = 0;
    rb_delete(rb,get_key(it.node),&succ);
    if(succ == 0)
    return RBtree_end(_rb);
    map_iter next ={succ,RB_iter_next,rb_iter_get_first,rb_iter_get_second,rb_iter_set_second};
    return next;
    }

    RBtree_size(struct interface_map_container *_rb)
    {
    RBtree_t rb = (RBtree_t)_rb;
    return rb->size;
    }

    RBtree_empty(struct interface_map_container *_rb)
    {
    RBtree_t rb = (RBtree_t)_rb;
    return rb->size == 0;
    }


    static int check(RBtree_t rb,RBnode *n,int level,int black_level,int *max_black_level,int *max_level)
    {
    if(n == rb->nil)
    return 1;
    if(n->color == BLACK)
    ++black_level;
    else
    {
    if(n->parent->color == RED)
    {
    printf("父节点颜色为RED\n");
    return 0;
    }
    }
    ++level;
    if(n->left == rb->nil && n->right == rb->nil)
    {
    //到达叶节点
    if(level > *max_level)
    *max_level = level;
    if(*max_black_level == 0)
    *max_black_level = black_level;
    else
    if(*max_black_level != black_level)
    {
    printf("黑色节点数目不一致\n");
    return 0;
    }
    return 1;
    }
    else
    {
    if(0 == check(rb,n->left,level,black_level,max_black_level,max_level))
    return 0;
    if(0 == check(rb,n->right,level,black_level,max_black_level,max_level))
    return 0;
    }
    }

    void RBtree_check_vaild(RBtree_t rb)
    {
    assert(rb);
    if(rb->root != rb->nil)
    {
    int max_black_level = 0;
    int max_level = 0;
    if(check(rb,rb->root,0,0,&max_black_level,&max_level))
    printf("max_black_level:%d,max_level:%d\n",max_black_level,max_level);
    }
    }

    map.h

    #ifndef _MAP_H
    #define _MAP_H

    typedef struct map_iter
    {
    void *node;
    struct map_iter (*next)(struct map_iter*);
    void (*get_first)(struct map_iter,void*);
    void (*get_second)(struct map_iter,void*);
    void (*set_second)(struct map_iter,void*);
    }map_iter;


    extern int map_iter_equal(map_iter,map_iter);

    #ifndef IT_MAP_GETFIRST
    #define IT_MAP_GETFIRST(TYPE,ITER)\
    ({ TYPE __result;\
    do ITER.get_first(ITER,&__result);\
    while(0);\
    __result;})
    #endif

    #ifndef IT_MAP_GETSECOND
    #define IT_MAP_GETSECOND(TYPE,ITER)\
    ({ TYPE __result;\
    do ITER.get_second(ITER,&__result);\
    while(0);\
    __result;})
    #endif

    #ifndef IT_MAP_SETSECOND
    #define IT_MAP_SETSECOND(TYPE,ITER,VAL)\
    {TYPE val=VAL;ITER.set_second(ITER,&val);}
    #endif

    #ifndef IT_MAP_NEXT
    #define IT_MAP_NEXT(ITER)\
    ITER.next(&ITER)
    #endif

    //能作为map存储容器的类型都必须实现的接口
    struct interface_map_container
    {
    map_iter (*insert)(struct interface_map_container*,void*,void*);
    map_iter (*erase)(struct interface_map_container*,map_iter);
    void (*remove)(struct interface_map_container* rb,void*);
    map_iter (*find)(struct interface_map_container* rb,void *);
    map_iter (*begin)(struct interface_map_container* rb);
    map_iter (*end)(struct interface_map_container* rb);
    int (*size)(struct interface_map_container*);
    int (*empty)(struct interface_map_container*);
    void (*destroy)(struct interface_map_container**);
    };

    //相等返回0,小于返回-1,大于返回1
    typedef int (*comp)(void*,void*);
    typedef struct map *map_t;

    //创建一个map,如果最后一个参数传0,则默认使用红黑树
    map_t map_create(unsigned short key_size,unsigned short val_size,comp _comp,struct interface_map_container*);
    void map_destroy(map_t*);

    inline extern map_iter map_insert(map_t,void*,void*);
    inline extern map_iter map_erase(map_t,map_iter);
    inline extern void map_remove(map_t,void*);
    inline extern map_iter map_find(map_t,void *);
    inline extern map_iter map_begin(map_t);
    inline extern map_iter map_end(map_t);
    inline extern int map_size(map_t);
    inline extern int map_empty(map_t);

    #ifndef MAP_INSERT
    #define MAP_INSERT(KEY_TYPE,VAL_TYPE,MAP,KEY,VAL)\
    ({ map_iter it;KEY_TYPE key = KEY;VAL_TYPE val = VAL;\
    do it = map_insert(MAP,&key,&val);\
    while(0);\
    it;})
    #endif

    #ifndef MAP_REMOVE
    #define MAP_REMOVE(KEY_TYPE,MAP,KEY)\
    { KEY_TYPE key = KEY;map_remove(MAP,&key);}
    #endif

    #ifndef MAP_FIND
    #define MAP_FIND(KEY_TYPE,MAP,KEY)\
    ({ map_iter it;KEY_TYPE key = KEY;\
    do it = map_find(MAP,&key);\
    while(0);\
    it;})
    #endif

    #endif

    map.c

    #include "map.h"
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <assert.h>
    #include "RBtree.h"

    struct map
    {
    struct interface_map_container *container;
    int free_container_on_destroy;
    };

    map_t map_create(unsigned short key_size,unsigned short val_size,comp _comp,struct interface_map_container *container)
    {
    map_t m = malloc(sizeof(*m));
    if(!m)
    return 0;
    if(container)
    {
    m->container = container;
    m->free_container_on_destroy = 0;
    }
    else
    {
    m->container = (struct interface_map_container *)RBtree_create(key_size,val_size,_comp);
    if(!m->container)
    {
    free(m);
    return 0;
    }
    m->free_container_on_destroy = 1;
    }
    return m;
    }

    void map_destroy(map_t *m)
    {

    }

    inline map_iter map_insert(map_t m,void *key,void *val)
    {
    assert(m);
    return m->container->insert(m->container,key,val);
    }

    inline map_iter map_erase(map_t m,map_iter it)
    {
    assert(m);
    return m->container->erase(m->container,it);
    }

    inline void map_remove(map_t m,void *key)
    {
    assert(m);
    m->container->remove(m->container,key);
    }

    inline map_iter map_find(map_t m,void *key)
    {
    assert(m);
    return m->container->find(m->container,key);
    }

    inline map_iter map_begin(map_t m)
    {
    assert(m);
    return m->container->begin(m->container);
    }

    inline map_iter map_end(map_t m)
    {
    assert(m);
    return m->container->end(m->container);
    }
    inline int map_size(map_t m)
    {
    assert(m);
    return m->container->size(m->container);
    }
    inline int map_empty(map_t m)
    {
    assert(m);
    return m->container->empty(m->container);
    }

    int map_iter_equal(map_iter a,map_iter b)
    {
    return a.node == b.node;
    }

    test.c

    #include "RBtree.h"
    #include <stdio.h>


    int compare(void *left,void *right)
    {
    int l = *(int*)left;
    int r = *(int*)right;
    if( l == r)
    return 0;
    else if(l < r)
    return -1;
    return 1;
    }


    int main()
    {

    map_t m = map_create(sizeof(int),sizeof(int),compare,0);
    int i = 9;
    for( ; i >= 0; --i)
    {
    MAP_INSERT(int,int,m,i,i);
    }

    map_iter it = map_begin(m);
    map_iter end = map_end(m);
    for( ; !map_iter_equal(it,end); it = IT_MAP_NEXT(it))
    printf("%d\n",IT_MAP_GETFIRST(int,it));

    return 0;
    }











  • 相关阅读:
    VitrualBox无法创建64位虚拟机
    SharePoint2010安装全过程
    SharePoint 2010 集成Window Live 认证遇到的问题 part1
    sharepoint 2007 page
    解决sharepoint 2010浏览器在线浏览Word出错
    http://newoinc.wordpress.com/2010/07/09/webpartpropertypaneokcancelapplybuttonsdisplayissue/
    jquery ajax 实现从service读取数据,done
    刚好理解:TreeView设置checkbox事件__doPostBack()
    ASPAJAXExtSetup 安装说明(转)
    一个简单登陆框的变化+更新了如何连接sql数据库,获得数据集,比较两种方法(数据集和读数据)
  • 原文地址:https://www.cnblogs.com/sniperHW/p/2429623.html
Copyright © 2011-2022 走看看