queues.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:6k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. /*
  14.   Code for generell handling of priority Queues.
  15.   Implemention of queues from "Algoritms in C" by Robert Sedgewick.
  16. */
  17. #include "mysys_priv.h"
  18. #include "mysys_err.h"
  19. #include <queues.h>
  20. /*
  21.   Init queue
  22.   SYNOPSIS
  23.     init_queue()
  24.     queue Queue to initialise
  25.     max_elements Max elements that will be put in queue
  26.     offset_to_key Offset to key in element stored in queue
  27. Used when sending pointers to compare function
  28.     max_at_top Set to 1 if you want biggest element on top.
  29.     compare Compare function for elements, takes 3 arguments.
  30.     first_cmp_arg First argument to compare function
  31.   NOTES
  32.     Will allocate max_element pointers for queue array
  33.   RETURN
  34.     0 ok
  35.     1 Could not allocate memory
  36. */
  37. int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key,
  38.        pbool max_at_top, int (*compare) (void *, byte *, byte *),
  39.        void *first_cmp_arg)
  40. {
  41.   DBUG_ENTER("init_queue");
  42.   if ((queue->root= (byte **) my_malloc((max_elements+1)*sizeof(void*),
  43.  MYF(MY_WME))) == 0)
  44.     DBUG_RETURN(1);
  45.   queue->elements=0;
  46.   queue->compare=compare;
  47.   queue->first_cmp_arg=first_cmp_arg;
  48.   queue->max_elements=max_elements;
  49.   queue->offset_to_key=offset_to_key;
  50.   queue->max_at_top= max_at_top ? (-1 ^ 1) : 0;
  51.   DBUG_RETURN(0);
  52. }
  53. /*
  54.   Reinitialize queue for other usage
  55.   SYNOPSIS
  56.     reinit_queue()
  57.     queue Queue to initialise
  58.     max_elements Max elements that will be put in queue
  59.     offset_to_key Offset to key in element stored in queue
  60. Used when sending pointers to compare function
  61.     max_at_top Set to 1 if you want biggest element on top.
  62.     compare Compare function for elements, takes 3 arguments.
  63.     first_cmp_arg First argument to compare function
  64.   NOTES
  65.     This will delete all elements from the queue.  If you don't want this,
  66.     use resize_queue() instead.
  67.   RETURN
  68.     0 ok
  69.     EE_OUTOFMEMORY Wrong max_elements
  70. */
  71. int reinit_queue(QUEUE *queue, uint max_elements, uint offset_to_key,
  72.  pbool max_at_top, int (*compare) (void *, byte *, byte *),
  73.  void *first_cmp_arg)
  74. {
  75.   DBUG_ENTER("reinit_queue");
  76.   queue->elements=0;
  77.   queue->compare=compare;
  78.   queue->first_cmp_arg=first_cmp_arg;
  79.   queue->offset_to_key=offset_to_key;
  80.   queue->max_at_top= max_at_top ? (-1 ^ 1) : 0;
  81.   resize_queue(queue, max_elements);
  82.   DBUG_RETURN(0);
  83. }
  84. /*
  85.   Resize queue
  86.   SYNOPSIS
  87.     resize_queue()
  88.     queue Queue
  89.     max_elements New max size for queue
  90.   NOTES
  91.     If you resize queue to be less than the elements you have in it,
  92.     the extra elements will be deleted
  93.   RETURN
  94.     0 ok
  95.     1 Error.  In this case the queue is unchanged
  96. */
  97. int resize_queue(QUEUE *queue, uint max_elements)
  98. {
  99.   byte **new_root;
  100.   DBUG_ENTER("resize_queue");
  101.   if (queue->max_elements == max_elements)
  102.     DBUG_RETURN(0);
  103.   if ((new_root= (byte **) my_realloc((void *)queue->root,
  104.       (max_elements+1)*sizeof(void*),
  105.       MYF(MY_WME))) == 0)
  106.     DBUG_RETURN(1);
  107.   set_if_smaller(queue->elements, max_elements);
  108.   queue->max_elements= max_elements;
  109.   queue->root= new_root;
  110.   DBUG_RETURN(0);
  111. }
  112. /*
  113.   Delete queue
  114.   SYNOPSIS
  115.    delete_queue()
  116.    queue Queue to delete
  117.   IMPLEMENTATION
  118.     Just free allocated memory.
  119.   NOTES
  120.     Can be called safely multiple times
  121. */
  122. void delete_queue(QUEUE *queue)
  123. {
  124.   DBUG_ENTER("delete_queue");
  125.   if (queue->root)
  126.   {
  127.     my_free((gptr) queue->root,MYF(0));
  128.     queue->root=0;
  129.   }
  130.   DBUG_VOID_RETURN;
  131. }
  132. /* Code for insert, search and delete of elements */
  133. void queue_insert(register QUEUE *queue, byte *element)
  134. {
  135.   reg2 uint idx,next;
  136.   int cmp;
  137. #ifndef DBUG_OFF
  138.   if (queue->elements < queue->max_elements)
  139. #endif
  140.   {
  141.     queue->root[0]=element;
  142.     idx= ++queue->elements;
  143.     /* max_at_top swaps the comparison if we want to order by desc */
  144.     while ((cmp=queue->compare(queue->first_cmp_arg,
  145.        element+queue->offset_to_key,
  146.        queue->root[(next=idx >> 1)] +
  147.        queue->offset_to_key)) &&
  148.    (cmp ^ queue->max_at_top) < 0)
  149.     {
  150.       queue->root[idx]=queue->root[next];
  151.       idx=next;
  152.     }
  153.     queue->root[idx]=element;
  154.   }
  155. }
  156. /* Remove item from queue */
  157. /* Returns pointer to removed element */
  158. byte *queue_remove(register QUEUE *queue, uint idx)
  159. {
  160. #ifndef DBUG_OFF
  161.   if (idx >= queue->max_elements)
  162.     return 0;
  163. #endif
  164.   {
  165.     byte *element=queue->root[++idx]; /* Intern index starts from 1 */
  166.     queue->root[idx]=queue->root[queue->elements--];
  167.     _downheap(queue,idx);
  168.     return element;
  169.   }
  170. }
  171. /* Fix when element on top has been replaced */
  172. #ifndef queue_replaced
  173. void queue_replaced(QUEUE *queue)
  174. {
  175.   _downheap(queue,1);
  176. }
  177. #endif
  178. /* Fix heap when index have changed */
  179. void _downheap(register QUEUE *queue, uint idx)
  180. {
  181.   byte *element;
  182.   uint elements,half_queue,next_index,offset_to_key;
  183.   int cmp;
  184.   offset_to_key=queue->offset_to_key;
  185.   element=queue->root[idx];
  186.   half_queue=(elements=queue->elements) >> 1;
  187.   while (idx <= half_queue)
  188.   {
  189.     next_index=idx+idx;
  190.     if (next_index < elements &&
  191. (queue->compare(queue->first_cmp_arg,
  192. queue->root[next_index]+offset_to_key,
  193. queue->root[next_index+1]+offset_to_key) ^
  194.  queue->max_at_top) > 0)
  195.       next_index++;
  196.     if ((cmp=queue->compare(queue->first_cmp_arg,
  197.     queue->root[next_index]+offset_to_key,
  198.     element+offset_to_key)) == 0 ||
  199. (cmp ^ queue->max_at_top) > 0)
  200.       break;
  201.     queue->root[idx]=queue->root[next_index];
  202.     idx=next_index;
  203.   }
  204.   queue->root[idx]=element;
  205. }
  206. static int queue_fix_cmp(QUEUE *queue, void **a, void **b)
  207. {
  208.   return queue->compare(queue->first_cmp_arg,
  209. (byte*) (*a)+queue->offset_to_key,
  210. (byte*) (*b)+queue->offset_to_key);
  211. }
  212. /*
  213.   Fix heap when every element was changed,
  214.   actually, it can be done better, in linear time, not in n*log(n)
  215. */
  216. void queue_fix(QUEUE *queue)
  217. {
  218.   qsort2(queue->root+1,queue->elements, sizeof(void *),
  219.  (qsort2_cmp)queue_fix_cmp, queue);
  220. }