📄 ivv_cluster_min_hash.cxx
字号:
// Copyright (C) Ipion Software GmbH 1999-2000. All rights reserved.
#include <ivp_physics.hxx>
#include "ivv_cluster_min_hash.hxx"
extern unsigned int IVP_Hash_crctab[];
inline int IVV_Cluster_Min_Hash::hash_index(const char *key)const{
unsigned int c;
unsigned int index = 0xffffffffL;
int i;
for (i=sizeof(void *)-1;i>=0;i--){
c = *((unsigned char *)(key++));
index = IVP_Hash_crctab[((int) index ^ c) & 0xff] ^ (index >> 8);
}
index = index & (size-1);
return index;
};
IVV_Cluster_Min_Hash::IVV_Cluster_Min_Hash(int sizei){
size = sizei;
int i;
for (i=0;i<32;i++){
if ( (1<<i) == sizei) break;
}
IVP_ASSERT (i!=32); // must be power 2
elems = (IVV_Cluster_Min_Hash_Elem **)p_calloc(sizeof(void *),size);
stadel = (IVV_Cluster_Min_Hash_Elem **)p_calloc(sizeof(void *),size*2);
min_per_array_pos = stadel + size;
counter = 0;
}
IVV_Cluster_Min_Hash_Elem::~IVV_Cluster_Min_Hash_Elem(){
delete next;
}
IVV_Cluster_Min_Hash::~IVV_Cluster_Min_Hash(){
unsigned int i;
for (i=0;i<size;i++){
if (!elems[i]) continue;
delete elems[i];
}
P_FREE(elems);
P_FREE(stadel);
}
/**
* elems: array of unsorted linked list
* min_per_array_pos parallel array of minimal elements per linked list
*
* stadel: binary tree of minimal elements
* stadel[1] == root
* stadel[2-3] next level
* stadel[4-7] ""
* ...
* stadel[size/2 - size-1]
* stadel[size - 2size-1] == min_per_array_pos[0 .. size-1] (same memory)
*/
// a new minimum element at a given hash index was set, so update stadel
void IVV_Cluster_Min_Hash::min_added_at_index(IVV_Cluster_Min_Hash_Elem *elem, int i){
unsigned int height;
IVP_DOUBLE val = elem->value;
i += size;
stadel[i] = elem; // transport new min element from bottom to top till smaller element is found
for (height = size>>1;height > 0;height>>=1){ // stadel, go from bottom to to top
i = i>>1;
if (stadel[i] && val >= stadel[i]->value){
break;
}
stadel[i] = elem;
}
}
// the minimum element at an array position has been removed
// search new minimum in linked list.
void IVV_Cluster_Min_Hash::min_removed_at_index(IVV_Cluster_Min_Hash_Elem *elem, int i){
{ // search hash index position for new minimal element
IVV_Cluster_Min_Hash_Elem *new_min = elems[i];
IVV_Cluster_Min_Hash_Elem *el;
el = new_min;
if (el){
for (el =el->next;el;el=el->next){
#if defined( SORT_MINDIST_ELEMENTS )
if (el->value < new_min->value ||
(el->value == new_min->value && el->cmp_index < new_min->cmp_index)){
new_min = el;
}
#else
if (el->value < new_min->value){
new_min = el;
}
#endif
}
}
min_per_array_pos[i] = new_min;
}
// go from bottom to top and trace path of elem
// as long as element is found update stadel
unsigned int height;
i += size;
for (height = size>>1;height > 0;height>>=1){ // stadel, go from bottom to top
i = i>>1;
if (elem != stadel[i]){ // finito
break;
}
int j = i*2;
if (!stadel[j]){
stadel[i] = stadel[j+1];
}else if (!stadel[j+1]){
stadel[i] = stadel[j];
}else{
#if defined( SORT_MINDIST_ELEMENTS )
if (stadel[j]->value < stadel[j+1]->value ||
(stadel[j]->value == stadel[j+1]->value && stadel[j]->cmp_index < stadel[j+1]->cmp_index))
#else
if (stadel[j]->value < stadel[j+1]->value)
#endif
{
stadel[i] = stadel[j];
}else{
stadel[i] = stadel[j+1];
}
}
}
}
void IVV_Cluster_Min_Hash::add(void *elem, IVP_DOUBLE val){
int i = hash_index((char *)&elem);
IVV_Cluster_Min_Hash_Elem *el = new IVV_Cluster_Min_Hash_Elem();//(IVV_Cluster_Min_Hash_Elem *)p_malloc(sizeof(IVV_Cluster_Min_Hash_Elem));
#if defined(SORT_MINDIST_ELEMENTS)
static int sort_counter = 1;
el->cmp_index = sort_counter++;
#endif
el->elem = elem;
el->next = elems[i];
elems[i] = el;
el->value = val;
counter++;
if (!min_per_array_pos[i] || val < min_per_array_pos[i]->value){
this->min_added_at_index(el,i);
}
}
/** update element in min_hash */
void IVV_Cluster_Min_Hash::change_value(void *elem, IVP_DOUBLE val){
remove(elem);
add(elem,val);
return;
int i = hash_index((char *)&elem);
IVV_Cluster_Min_Hash_Elem *el;
for (el = elems[i];el;el=el->next){
if ( el->elem == elem){
break;
}
}
IVP_ASSERT(el != NULL);
if (val < el->value){ // we got smaller
el->value = val; // update stadel
if (val <= min_per_array_pos[i]->value){ // new mimimum found
min_added_at_index(el,i);
}
}else{ // we became bigger
el->value = val; // update stadel
if (el == min_per_array_pos[i]){ // we were a minimum, so get rid of it
min_removed_at_index(el,i); // let's look for a new minimum
}
}
}
/** try to remove element from min_hash */
void IVV_Cluster_Min_Hash::remove(void *elem){
int i = hash_index((char *)&elem);
IVV_Cluster_Min_Hash_Elem *el,*last_el;
last_el = 0;
for (el = elems[i];el;el=el->next){
if ( el->elem == elem){
if (last_el){
last_el->next = el->next;
}else{
elems[i] = el->next;
}
el->next = 0;
if (el == min_per_array_pos[i]){
min_removed_at_index(el,i);
}
P_DELETE(el);
counter--;
return;
}
last_el = el;
}
}
int IVV_Cluster_Min_Hash::is_elem(void *elem){
int i = hash_index((char *)&elem);
IVV_Cluster_Min_Hash_Elem *el;
for (el = elems[i];el;el=el->next){
if ( el->elem == elem){
return 1;
}
}
return 0;
}
void IVV_Cluster_Min_Hash::remove_min(){
IVV_Cluster_Min_Hash_Elem *min = (IVV_Cluster_Min_Hash_Elem *)this->find_min_elem();
if (min){
this->remove(min);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -