Lowe,D 的SIFT代码
给定结点的索引,求其根和左右孩子的对应的索引
/* returns the array index of element i's parent */
static inline int parent( int i )
{
return ( i - 1 ) / 2;//返回父结点的序号
}
/* returns the array index of element i's right child */
static inline int right( int i )//返回右孩子的序号
{
return 2 * i + 2;
}
/* returns the array index of element i's left child */
static inline int left( int i )//返回左孩子的序号
{
return 2 * i + 1;
}
创建小根堆,分配空间
/*
minpq.h中相关结构体的定义
struct pq_node
{
void* data;
int key;
};
struct min_pq
{
struct pq_node* pq_array; // array containing priority queue
int nallocd; // number of elements allocated
int n; // number of elements in pq
};
*/
//创建一个小根堆
/*
Creates a new minimizing priority queue.
*/
struct min_pq* minpq_init()
{
struct min_pq* min_pq;
min_pq = malloc( sizeof( struct min_pq ) );//开辟小根堆空间
min_pq->pq_array = calloc( MINPQ_INIT_NALLOCD, sizeof( struct pq_node ) );//开辟小根堆中结点的空间,MINPQ_INIT_NALLOCD为512
min_pq->nallocd = MINPQ_INIT_NALLOCD;//堆中所能容纳的结点最大数量
min_pq->n = 0;//当前小根堆中结点的个数
return min_pq;
}
插入新结点,并重新调整为小根堆
//插入结点
/**
Inserts an element into a minimizing priority queue.
@param min_pq a minimizing priority queue(小根堆)
@param data the data to be inserted(结点数据)
@param key the key to be associated with \a data(决定结点在小根堆中所处位置的key值)
@return Returns 0 on success or 1 on failure.
*/
int minpq_insert( struct min_pq* min_pq, void* data, int key )
{
int n = min_pq->n;//小根堆已经存有的结点数量
/* double array allocation if necessary */
if( min_pq->nallocd == n )//要插入到的小根堆已满
{
min_pq->nallocd = array_double( (void**)&min_pq->pq_array,
min_pq->nallocd,
sizeof( struct pq_node ) );//utils.c中,扩大小根堆的大小,如果成果返回2*n,否则返回0
if( ! min_pq->nallocd ) //array_double函数返回0则执行if下面的语句
{
fprintf( stderr, "Warning: unable to allocate memory, %s, line %d\n",
__FILE__, __LINE__ );
return 1;//插入失败
}
}
min_pq->pq_array[n].data = data;//结点中的数据
min_pq->pq_array[n].key = INT_MAX;//INT_MAX为范围内的最大整数
decrease_pq_node_key( min_pq->pq_array, min_pq->n, key );//调用函数decrease_pq_node_key
min_pq->n++;//队列中结点数+1
return 0;//插入成功
}
(本地函数)Functions prototyped here
//插入和调整的过程
/*
Decrease a minimizing pq element's key, rearranging the pq if necessary
@param pq_array minimizing priority queue array(小根堆)
@param i index of the element whose key is to be decreased(小根堆中已有的结点,)
@param key new value of element <EM>i</EM>'s key; if greater than current
key, no action is taken(决定结点在小根堆中所处位置的key值)
*/
static void decrease_pq_node_key( struct pq_node* pq_array, int i, int key )
{
struct pq_node tmp;//用于交换时,暂存
if( key > pq_array[i].key )//key不能越界(不能超过int最大整数)
return;
pq_array[i].key = key;
while( i > 0 && pq_array[i].key < pq_array[parent(i)].key )//满足换的条件
{
//换 调整
tmp = pq_array[parent(i)];
pq_array[parent(i)] = pq_array[i];
pq_array[i] = tmp;
i = parent(i);//不断与当前位置的父结点的key值比较大小,确保父结点的值小
}
}
返回根结点的数据
//返回根结点的data数据
/*
Returns the element of a minimizing priority queue with the smallest key
without removing it from the queue.
@param min_pq a minimizing priority queue
@return Returns the element of \a min_pq with the smallest key or NULL
if \a min_pq is empty
*/
void* minpq_get_min( struct min_pq* min_pq )
{
if( min_pq->n < 1 )//小根堆中无结点
{
fprintf( stderr, "Warning: PQ empty, %s line %d\n", __FILE__, __LINE__ );
return NULL;
}
return min_pq->pq_array[0].data;//返回根结点的数据
}
剔除原根结点并返回其data,再重新调整为小根堆
//删除根结点并调整堆
/*
Removes and returns the element of a minimizing priority queue with the
smallest key.
@param min_pq a minimizing priority queue(小根堆)
@return Returns the element of \a min_pq with the smallest key of NULL
if \a min_pq is empty
*/
void* minpq_extract_min( struct min_pq* min_pq )
{
void* data;
if( min_pq->n < 1 )//队列中无结点
{
fprintf( stderr, "Warning: PQ empty, %s line %d\n", __FILE__, __LINE__ );
return NULL;
}
data = min_pq->pq_array[0].data;//根结点
min_pq->n--;//小根堆中结点的个数减1
min_pq->pq_array[0] = min_pq->pq_array[min_pq->n];//把最后一个结点挪到根结点位置
restore_minpq_order( min_pq->pq_array, 0, min_pq->n );//调用函数restore_minpq_order,
return data;//返回原根结点(已被删除)的data
}
(本地函数)Functions prototyped here
//去除根结点后,将最后一个结点放到根结点,再调整为小根堆
/*
Recursively restores correct priority queue order to a minimizing pq array
@param pq_array a minimizing priority queue array(小根堆)
@param i index at which to start reordering (最开始将i=0传入 根结点位置)
@param n number of elements in \a pq_array
*/
static void restore_minpq_order( struct pq_node* pq_array, int i, int n )
{
struct pq_node tmp;//用于交换时,暂存
int l, r, min = i;
l = left( i );//2 * i + 2 左孩子
r = right( i );//2 * i + 1 右孩子
//判断左右孩子是否存在,并将 左右根序号 的最小值存入min
if( l < n )//存在左孩子结点
if( pq_array[l].key < pq_array[i].key )
min = l;
if( r < n )//存在右孩子结点
if( pq_array[r].key < pq_array[min].key )
min = r;
if( min != i )
{
//将小的换到根结点
tmp = pq_array[min];
pq_array[min] = pq_array[i];
pq_array[i] = tmp;
restore_minpq_order( pq_array, min, n );//调用它自己
}
}
释放小根堆
//释放小根堆
/*
De-allocates the memory held by a minimizing priorioty queue
@param min_pq pointer to a minimizing priority queue
*/
void minpq_release( struct min_pq** min_pq )
{
if( ! min_pq )
{
fprintf( stderr, "Warning: NULL pointer error, %s line %d\n", __FILE__,
__LINE__ );
return;
}
if( *min_pq && (*min_pq)->pq_array )
{
free( (*min_pq)->pq_array );
free( *min_pq );
*min_pq = NULL;
}
}
建立小根堆在后续建立KDtree中会用到!