Blender文档翻译-什么是Ghash?

原文(Blender官方文档):https://wiki.blender.org/index.php/Dev:Source/Data_Structures/GHash_Tutorial,本人英语水平较差,边学边译,有不对的地方欢迎批评指正!

What is a GHash?

There are times that you need to make an easily searchable list, where the size is unknown, and it needs to be quickly accessed (no linear searching) One great way to get this job done is with a hash table. Setting up your own hash, when you haven't got a clue can be a daunting task. But why reinvent the wheel! There is already a generic hash data structure built into the Blender codebase! ZR wrote ghash which lets you set up and use a hash with very little code. This can give you several options...

  • A Keyed Hash Table
  • An Item Set

 

什么是GHash?

有时您需要创建一个易于搜索的列表,其中大小未知,需要快速访问(非线性搜索)。用哈希表来完成这项工作是个很好的办法。当你没有头绪时,建立你自己的哈希是一项艰巨的任务。为什么要重新发明轮子!在Blender代码库中构建了通用哈希数据结构!ZR编写了Ghash,它让您可以用非常少的代码创建和使用散列。它有二个选项...

  • 带键哈希表
  • 项目集合

Hash Table

A hash table is basically these key and value pairs that have been stored in such a way that passing the key to the hash will return you the value. ghash uses pointers as the key and value. Since it is set up with void pointers, they can point to just about anything. One application would be the case that you had a data structure that held temporary meta data about an EditEdge. For each edit edge, you could use the EdgeEdge* as your key and then dynamically allocate some memory to your meta data struct and then assign that as the value. Then whenever you needed the metadata for that edge, you pass the key to the hash and it returns the pointer to your struct.

哈希表

哈希表从根本上来说,就是些键和值对,它们的这种存储方式可将键传递给散列返回其值。GHash使用指针的键和值。由于它是用空指针设置的,所以它们可以指向任何东西。一个应用程序会出现这样的情况,你有一个数据结构存储了EditEdge的临时元数据。每个编辑的边,你可以使用EditEdge *作为键(key),然后动态地分配内存给你的元数据结构作为其值。然后,每当需要该边的元数据时,就将键传递给散列,返回指向结构的指针。

An Item Set

Suppose you just want to make a dynamic list of items. Just feed the keys to the hash with NULL as the value. Then you can check later if the key is in the hash or set up an iterator to step through the keys of your hash.

项目集合

假如您只想创建一个动态的项目列表。只需将散列的键用NULL值进行填充即可。然后,你可检查键是否在在哈希表中,或者设定一个迭代器来遍历哈希表的键。

Using GHash

The Basic GHash

We get there from this .h file

 #include "BLI_ghash.h"

First we need to declare our ghash: Then we need to create our new data structure. We pass this init function pointers to the hash and compare functions that this hash will be using. In this case a pointer hash. The function arguments determine how key values are compared or hashed, and can be used to create more specialized hash tables.

GHash *gh;
 
gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);

When it comes time to add an entry into our hash we call BLI_ghash_insert and pass it our hash, the key and value. Where key and value are both pointers.

 BLI_ghash_insert(gh, key, value);

Then we can pass the key to BLI_ghash_lookup and retrieve that value back

 value = BLI_ghash_lookup(gh, key);

One way to create a dynamic set of objects is to enter keys into the hash with NULL as the value. Then, you can later use BLI_ghash_haskey to see if that item is in the hash. It returns 1 for yes and 0 for no.

 BLI_ghash_haskey(gh,key)

Of course we can check the size with

 BLI_ghash_size(gh)

When we are done, be sure to clean up after yourself with this little beauty!

 BLI_ghash_free(gh, NULL, NULL);

使用GHash

The Basic GHash

我们从这里得到.h文件

 #include "BLI_ghash.h"

首先需要声明Ghash:然后我们需要创建新的数据结构。我们将哈希表需使用的初始化和比较函数指针传递给它。这里是一个哈希表指针。 函数的参数确定键值是如何进行比较或散列的,也能创建更特别的哈希表。

GHash *gh;
 
gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);

在添加一项到哈希表时,调用bli_ghash_insert并传递给它哈希表、键和值。其中键和值都是指针。

 BLI_ghash_insert(gh, key, value);

接着传递键到BLI_ghash_lookup取得值并返回

 value = BLI_ghash_lookup(gh, key);

创建对象动态集合的一种方式是添加键到哈希表时以NULL作为值。之后你可使用BLI_ghash_haskey去看看哪些项在哈希表中,它返回1表示是的,0是否定的。

 BLI_ghash_haskey(gh,key)

当然我们可以查看大小:

 BLI_ghash_size(gh)

当我们做完了,一定要用这小美人来清理自己!

 BLI_ghash_free(gh, NULL, NULL);

Using An Iterator

After we create our hash, we need to create an iterator if we want to step though it... Note that it is not safe to insert elements or free the hash while we are itereating through it.

We will need to declare our iterator

 GHashIterator* ghi;

Then later we initialize it with this

 ghi = BLI_ghashIterator_new(gh);

The iterator starts on the first key and we step through the keys using

 BLI_ghashIterator_step(ghi);

On a given key we can get the key or value using these, they return the key or value pointers if the iterator has completly gone through the hash, you will get NULL from either.

BLI_ghashIterator_getKey(ghi);
 
BLI_ghashIterator_getValue(ghi);

We can also test the doneness of the iterator with this. Returning 1 if done 0 if not.

 BLI_ghashIterator_isDone(ghi);

and eventaully free it with this

 BLI_ghashIterator_free(ghi);

使用迭代器

创建散列之后,如果想遍历它,需要创建一个迭代器,注意,在我们通过它进行迭代时,插入元素或释放散列是不安全的。

我们需要声明我们的迭代器

 GHashIterator* ghi;

随后我们这样初始化它:

 ghi = BLI_ghashIterator_new(gh);

迭代器从第一个键开始遍历所有的键使用:

 BLI_ghashIterator_step(ghi);

On a given key we can get the key or value using these, they return the key or value pointers if the iterator has completly gone through the hash, you will get NULL from either.

在给定的键上,我们可以使用这些来获取键或值,它们返回键或值指针,如果迭代器已经完全遍历了散列,您将获得NULL。

BLI_ghashIterator_getKey(ghi);
 
BLI_ghashIterator_getValue(ghi);

我们也可以用这个测试迭代器的完好性。完成返回1,否则返回0。

 BLI_ghashIterator_isDone(ghi);

最终还是用这个来释放它

 BLI_ghashIterator_free(ghi);
 

示例

下面是一些打印散列项示例代码:

void print_hash(GHash *gh) {
    GHashIterator *ghi = BLI_ghashIterator_new(gh);
    for (; !BLI_ghashIterator_isDone(ghi); BLI_ghashIterator_step(ghi)) {
        printf("Key(%p) : Value(%p)\n", BLI_ghashIterator_getKey(ghi),
                                        BLI_ghashIterator_getValue(ghi));
    }
    BLI_ghashIterator_free(ghi);
}
posted @ 2017-12-29 23:10  平凡人  阅读(...)  评论(...编辑  收藏