queues.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:4k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    
  3.    This library is free software; you can redistribute it and/or
  4.    modify it under the terms of the GNU Library General Public
  5.    License as published by the Free Software Foundation; either
  6.    version 2 of the License, or (at your option) any later version.
  7.    
  8.    This library is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.    Library General Public License for more details.
  12.    
  13.    You should have received a copy of the GNU Library General Public
  14.    License along with this library; if not, write to the Free
  15.    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  16.    MA 02111-1307, USA */
  17. /*
  18.   Code for generell handling of priority Queues.
  19.   Implemention of queues from "Algoritms in C" by Robert Sedgewick.
  20. */
  21. #include "mysys_priv.h"
  22. #include "mysys_err.h"
  23. #include <queues.h>
  24. /* Init queue */
  25. int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key,
  26.        pbool max_at_top, int (*compare) (void *, byte *, byte *),
  27.        void *first_cmp_arg)
  28. {
  29.   DBUG_ENTER("init_queue");
  30.   if ((queue->root= (byte **) my_malloc((max_elements+1)*sizeof(void*),
  31.  MYF(MY_WME))) == 0)
  32.     DBUG_RETURN(1);
  33.   queue->elements=0;
  34.   queue->compare=compare;
  35.   queue->first_cmp_arg=first_cmp_arg;
  36.   queue->max_elements=max_elements;
  37.   queue->offset_to_key=offset_to_key;
  38.   queue->max_at_top= max_at_top ? (-1 ^ 1) : 0;
  39.   DBUG_RETURN(0);
  40. }
  41. /*
  42.   Reinitialize queue for new usage;  Note that you can't currently resize
  43.   the number of elements!  If you need this, fix it :)
  44. */
  45. int reinit_queue(QUEUE *queue, uint max_elements, uint offset_to_key,
  46.                pbool max_at_top, int (*compare) (void *, byte *, byte *),
  47.                void *first_cmp_arg)
  48. {
  49.   DBUG_ENTER("reinit_queue");
  50.   if (queue->max_elements < max_elements)
  51.     /* It's real easy to do realloc here, just don't want to bother */
  52.     DBUG_RETURN(my_errno=EE_OUTOFMEMORY);
  53.   queue->elements=0;
  54.   queue->compare=compare;
  55.   queue->first_cmp_arg=first_cmp_arg;
  56.   queue->offset_to_key=offset_to_key;
  57.   queue->max_at_top= max_at_top ? (-1 ^ 1) : 0;
  58.   DBUG_RETURN(0);
  59. }
  60. void delete_queue(QUEUE *queue)
  61. {
  62.   DBUG_ENTER("delete_queue");
  63.   if (queue->root)
  64.   {
  65.     my_free((gptr) queue->root,MYF(0));
  66.     queue->root=0;
  67.   }
  68.   DBUG_VOID_RETURN;
  69. }
  70. /* Code for insert, search and delete of elements */
  71. void queue_insert(register QUEUE *queue, byte *element)
  72. {
  73.   reg2 uint idx,next;
  74.   int cmp;
  75. #ifndef DBUG_OFF
  76.   if (queue->elements < queue->max_elements)
  77. #endif
  78.   {
  79.     queue->root[0]=element;
  80.     idx= ++queue->elements;
  81.     /* max_at_top swaps the comparison if we want to order by desc */
  82.     while ((cmp=queue->compare(queue->first_cmp_arg,
  83.        element+queue->offset_to_key,
  84.        queue->root[(next=idx >> 1)] +
  85.        queue->offset_to_key)) &&
  86.    (cmp ^ queue->max_at_top) < 0)
  87.     {
  88.       queue->root[idx]=queue->root[next];
  89.       idx=next;
  90.     }
  91.     queue->root[idx]=element;
  92.   }
  93. }
  94. /* Remove item from queue */
  95. /* Returns pointer to removed element */
  96. byte *queue_remove(register QUEUE *queue, uint idx)
  97. {
  98. #ifndef DBUG_OFF
  99.   if (idx >= queue->max_elements)
  100.     return 0;
  101. #endif
  102.   {
  103.     byte *element=queue->root[++idx]; /* Intern index starts from 1 */
  104.     queue->root[idx]=queue->root[queue->elements--];
  105.     _downheap(queue,idx);
  106.     return element;
  107.   }
  108. }
  109. /* Fix when element on top has been replaced */
  110. #ifndef queue_replaced
  111. void queue_replaced(queue)
  112. QUEUE *queue;
  113. {
  114.   _downheap(queue,1);
  115. }
  116. #endif
  117. /* Fix heap when index have changed */
  118. void _downheap(register QUEUE *queue, uint idx)
  119. {
  120.   byte *element;
  121.   uint elements,half_queue,next_index,offset_to_key;
  122.   int cmp;
  123.   offset_to_key=queue->offset_to_key;
  124.   element=queue->root[idx];
  125.   half_queue=(elements=queue->elements) >> 1;
  126.   while (idx <= half_queue)
  127.   {
  128.     next_index=idx+idx;
  129.     if (next_index < elements &&
  130. (queue->compare(queue->first_cmp_arg,
  131. queue->root[next_index]+offset_to_key,
  132. queue->root[next_index+1]+offset_to_key) ^
  133.  queue->max_at_top) > 0)
  134.       next_index++;
  135.     if ((cmp=queue->compare(queue->first_cmp_arg,
  136.     queue->root[next_index]+offset_to_key,
  137.     element+offset_to_key)) == 0 ||
  138. (cmp ^ queue->max_at_top) > 0)
  139.       break;
  140.     queue->root[idx]=queue->root[next_index];
  141.     idx=next_index;
  142.   }
  143.   queue->root[idx]=element;
  144. }