Sift:小根堆(minpq.c)

本文介绍了如何使用C语言实现一个最小堆(minimizingpriorityqueue)的数据结构,包括初始化、插入节点、调整堆顺序以及释放内存。这些操作在构建KD树(KD-tree)的过程中至关重要。
摘要由CSDN通过智能技术生成

 

 

 

 

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中会用到!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值