C 工具库8:map

摘要:
本篇介绍另外一个在C++stl中常用的容器map.我打算将map的实现容器和map接口分开,创建map的时候可以传递一个实现了interface_map_container接口的对象指针进来,如果这个参数传0,则默认使用红黑树做实际的容器.这样做的好处是用户可以根据性能需求传递自己定制的容器类.例如在游戏程序中常见的数据表.一般通过一个索引查询,并且在程序启动时候将数据全部加载好,在以后的运行中,

本篇介绍另外一个在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的后继节点,为根节点的情况下返回nilstatic 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的前驱节点,为根节点的情况下返回nilstatic 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,大于返回1typedef 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;
}

免责声明:文章转载自《C 工具库8:map》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇【 linux知识积累 】网络相关配置与知识-CentOS7为例Ubuntu 下命令安装 Java下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Nginx核心知识100讲学习笔记(陶辉)Nginx架构基础(四)

一、红黑树 1、红黑树 2、红黑树复杂度 3、使用红黑树的模块 1、本地内存做的红黑树 ngx_conf_module ngx_event_timer_rbtree #管理定时器的红黑树 2、管理定时器的红黑树 Ngx_http_file_cache Ngx_http_geo_module Ngx_http_limit_conn_module Ng...

博雅大数据机器学习十讲第三讲

点到平面的距离 直线方程:(w_1x_1+w_2x_2+w_0 = 0) 点到直线距离(d = frac {|w_1x_1^{'}+w_2x_2^{'}+w_0|}{sqrt{w^2_1+w^2_2}}) 欧式空间超平面:(w_1x_1+w_2x_2+...+w_dx_d+w_0 = 0) 点到超平面距离: [d = frac {|w_1x_1^{'...

C#如何获取其他程序ListView控件中的内容

源码下载:http://download.csdn.net/detail/php_fly/4923388 需求:获取其他程序中的ListView控件的文本内容 原理:进程之间是相互隔离的,数据是不能共享的(有些特例)    LVM_GETTITEMTEXT:将一个数据缓冲区提供给listview32控件,你不能把你的进程的数据缓冲提供给另外的程序,所以要用...

yolo接口

在文件yolo_v2_class.hpp中声明。 extern "C" LIB_API int init(const char *configurationFilename, const char *weightsFilename, int gpu); extern "C" LIB_API int detect_image(const char *file...

C++中extern关键字用法小结

总结C++中关于extern关键字的用法。 1.变量的生明和定义中 C++语言支持分离式编译机制,该机制允许将程序分割为若干个文件,每个文件可被独立编译。为了将程序分为许多文件,则需要在文件中共享代码,例如一个文件的代码可能需要另一个文件中中定义的变量。 为了支持分离式编译,C++允许将声明和定义分离开来。变量的声明规定了变量的类型和名字,即使一个名字为程...

c语言中typeof关键字

为什么因为一个关键字而专门写一篇随笔呢?因为这个关键字在Linux里面地位非同一般!这个关键字typeof在linux内核里面使用非常广泛! 下面这两个等效声明,用于声明int类弄的变量atypeof(int) a;typeof('b') a; //相当于获取'b'的类型,定义一个变量a下面用于声明指针和数组typeof(int*) p1,p2;typeo...