home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1994 June / NEBULA_SE.ISO / SourceCode / MiscKit / Source / MiscPriorityQueue.m < prev    next >
Encoding:
Text File  |  1994-01-07  |  9.8 KB  |  537 lines

  1. /* NAME:
  2. **    MiscPriorityQueue:Object
  3. **
  4. **    COPYRIGHT 1992 BY ONYSCHUK AND ASSOCIATES
  5. **    ALL RIGHTS RESERVED.
  6. **
  7. ** REVISION HISTORY:
  8. **    Sun Aug 16 14:14:03 EDT 1992    Mark Onyschuk
  9. **                    Starting point.
  10. **
  11. ** DESCRIPTION:
  12. **    A priority queue which dequeues objects sorted by
  13. **    unsigned integer priorities.
  14. **
  15. **    NOTE: priority(0) > priority(1) > priority(2) > ... 
  16. **
  17. ** DISCLAIMER:
  18. **    This is free software; you can redistribute it and/or modify
  19. **    it under the terms of the MiscKit license; either version
  20. **    1, or (at your option) any later version.
  21. **
  22. **    This program is distributed in the hope that it will be
  23. **    useful, but WITHOUT ANY WARRANTY; without even the implied
  24. **    warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  25. **    PURPOSE.
  26. */
  27.  
  28. #import <misckit/MiscPriorityQueue.h>
  29. #import <appkit/appkit.h> // for free()
  30.  
  31.  
  32. /* DEFINITIONS **********************************************************/
  33.  
  34. #define DEFAULTSIZE    8
  35.  
  36.  
  37. /* MACROS ***************************************************************/
  38.  
  39. #define OBJECTAT(z)    (heap[z].object)
  40. #define PRIORITYOF(z)    (heap[z].priority)
  41.  
  42. #define HEAPMALLOC(q)    \
  43.     ((NODE*)NXZoneMalloc([self zone],sizeof(NODE)*(q)))
  44. #define HEAPREALLOC(q)    \
  45.     ((NODE*)NXZoneRealloc([self zone],heap,sizeof(NODE)*(q)))
  46. #define HEAPFREE()    \
  47.     (NXZoneFree([self zone],heap))
  48.  
  49.  
  50. @implementation MiscPriorityQueue
  51.  
  52. /* INITIALIZING A PRIORITY QUEUE ****************************************/
  53.  
  54. - init
  55. {
  56.     return [self initCount:DEFAULTSIZE];
  57. }
  58.  
  59. - initCount:(unsigned)count
  60. {
  61.     if ((self = [super init]) != nil)
  62.     {
  63.     top  = 0;
  64.         size = (count < 1) ? 1 : count;
  65.     heap = HEAPMALLOC(size + 1);
  66.     }
  67.     return self;
  68. }
  69.  
  70.  
  71. /* FREEING A PRIORITY QUEUE *********************************************/
  72.  
  73. - free
  74. {
  75.     HEAPFREE();
  76.     return [super free];
  77. }
  78.  
  79. - copyFromZone:(NXZone *)zone
  80. {
  81.     int i;
  82.     MiscPriorityQueue *copy;
  83.     
  84.     copy = [[[self class] allocFromZone:zone] initCount:size];
  85.     
  86.     for (i = top; i > 0; i--)
  87.     {
  88.         ((NODE *)(copy->heap))[i].object   = heap[i].object;
  89.         ((NODE *)(copy->heap))[i].priority = heap[i].priority;
  90.     }
  91.     
  92.     copy->top  = top;
  93.     copy->size = size;
  94.     
  95.     return copy;
  96. }
  97.  
  98.  
  99. /* ADDING/REMOVING OBJECTS FROM A PRIORITY QUEUE ************************/
  100.  
  101. /* NAME:
  102. **    - addObject:withPriority;
  103. **
  104. ** ARGUMENTS:
  105. **    anObject        object to be queued
  106. **    priority        unsigned integer priority
  107. **
  108. ** LAST EDITED:
  109. **    Sun Aug 23 15:17:03 EDT 1992    Mark Onyschuk
  110. **
  111. ** DESCRIPTION:
  112. **    Adds an object to the priority queue.
  113. **
  114. ** ALGORITHM:
  115. **    begin
  116. **        top <- top + 1
  117. **
  118. **        if top > size(heap)
  119. **        begin
  120. **        size(heap) = size(heap * 2)
  121. **        end
  122. **
  123. **        heap[top].object <- anObject
  124. **        heap[top].priority <- priority
  125. **
  126. **        i = top;
  127. **        j = parentOf(i);
  128. **
  129. **        while (i <> 1) && (priorityOf(i) < priorityOf(j))
  130. **        begin
  131. **        swap objects and priorities of i and j
  132. **
  133. **        i <- j;
  134. **        j <- parentOf(i);
  135. **        end
  136. **    end
  137. **
  138. ** RETURNS:
  139. **    self;
  140. */
  141.  
  142. - addObject:anObject withPriority:(unsigned int)priority
  143. {
  144.     int        i,
  145.             j;
  146.     NODE     temp;    
  147.  
  148.  
  149.     top += 1;
  150.         
  151.     if (top > size)
  152.     {
  153.         size *= 2;
  154.     heap  = HEAPREALLOC(size + 1);
  155.     }    
  156.  
  157.     
  158.     OBJECTAT(top) = anObject;
  159.     PRIORITYOF(top) = priority;
  160.     
  161.     for (i=top, j=i/2; (i>1) && (PRIORITYOF(i) < PRIORITYOF(j)); i=j, j=i/2)
  162.     { 
  163.     temp.object = OBJECTAT(i);
  164.     temp.priority = PRIORITYOF(i);
  165.     
  166.     OBJECTAT(i) = OBJECTAT(j);
  167.     PRIORITYOF(i) = PRIORITYOF(j);
  168.     
  169.     OBJECTAT(j) = temp.object;
  170.     PRIORITYOF(j) = temp.priority;
  171.     }
  172.     
  173.     return self;    
  174. }
  175.  
  176. /* NAME:
  177. **    - removeObject;
  178. **
  179. ** ARGUMENTS:
  180. **    none
  181. **
  182. ** LAST EDITED:
  183. **    Sun Aug 23 15:17:03 EDT 1992    Mark Onyschuk
  184. **
  185. ** DESCRIPTION:
  186. **    Removes an object from the priority queue.
  187. **
  188. ** ALGORITHM:
  189. **    begin
  190. **        if (isEmpty(heap))
  191. **        return nil
  192. **
  193. **        anObject <- objectAt(1)
  194. **
  195. **        move the top object and priority to the beginning (1)
  196. **        top <- top - 1
  197. **        i <- 1
  198. **
  199. **        while (i <= top / 2)
  200. **        begin
  201. **        j = objectOfMaxPriority(i*2, i*2 + 1)
  202. **
  203. **        if (priorityOf(i) > priorityOf(j))
  204. **        begin
  205. **            swap objects and priorities of i and j
  206. **            i <- j
  207. **        end else begin
  208. **            return anObject
  209. **        end
  210. **        end
  211. **        return anObject
  212. **    end
  213. **
  214. ** RETURNS:
  215. **    object from the queue with top priority, or
  216. **    nil if the queue is empty.
  217. */
  218.  
  219. - removeObject;
  220. {
  221.     int        i,
  222.             j;
  223.  
  224.     NODE    temp;
  225.     
  226.     id        anObject;
  227.     
  228.         
  229.  
  230.     if (top == 0)
  231.         return nil;
  232.  
  233.     anObject  = OBJECTAT(1);
  234.     
  235.          
  236.     OBJECTAT(1) = OBJECTAT(top);
  237.     PRIORITYOF(1) = PRIORITYOF(top);
  238.     
  239.     
  240.     i    = 1;
  241.     top -= 1;
  242.  
  243.     while (i <= top/2)
  244.     {
  245.         if ((PRIORITYOF(i*2) < PRIORITYOF((i*2) + 1)) || ((i*2) == top))
  246.         j =  i*2;
  247.     else
  248.         j = (i*2) + 1;
  249.     
  250.         if (PRIORITYOF(i) > PRIORITYOF(j))
  251.     {
  252.         temp.object = OBJECTAT(i);
  253.         temp.priority = PRIORITYOF(i);
  254.         
  255.         OBJECTAT(i) = OBJECTAT(j);
  256.         PRIORITYOF(i) = PRIORITYOF(j);
  257.         
  258.         OBJECTAT(j) = temp.object;
  259.         PRIORITYOF(j) = temp.priority;
  260.         
  261.         i = j;
  262.     }
  263.     else
  264.     {
  265.         return anObject;
  266.     }
  267.     }
  268.     return anObject;
  269. }    
  270.     
  271.  
  272. /* DETERMINING THE HIGHEST PRIORITY IN A PRIORITY QUEUE *****************/
  273.  
  274. /* NAME:
  275. **    - (unsigned)highestPriority
  276. **
  277. ** ARGUMENTS:
  278. **    none.
  279. **
  280. ** DESCRIPTION:
  281. **    Returns the highest priority occurring in the priority
  282. **    queue.
  283. **
  284. ** RETURNS:
  285. **    the highest priority occurring in the queue, or
  286. **    the latest priority occurring in the queue if the queue is empty.
  287. */
  288.  
  289. - (unsigned)highestPriority
  290. {
  291.     return PRIORITYOF(1);
  292. }
  293.  
  294.     
  295. /* COUNTING THE NUMBER OF OBJECTS IN A PRIORITY QUEUE *******************/
  296.  
  297. /* NAME:
  298. **    -(int)count;
  299. **
  300. ** ARGUMENTS:
  301. **    none.
  302. **
  303. ** LAST EDITED:
  304. **    Sun Aug 23 15:17:03 EDT 1992    Mark Onyschuk
  305. **
  306. ** DESCRIPTION:
  307. **    Returns the number of objects currently queued.
  308. **
  309. ** RETURNS:
  310. **    count of objects currently in the queue.
  311. */
  312.  
  313. - (unsigned int)count
  314. {
  315.     return top;
  316. }
  317.  
  318.  
  319. /* COMPARING AND COMBINING PRIORITY QUEUES ******************************/
  320.  
  321. /* NAME:
  322. **    - (BOOL)isEqual:anObject
  323. **
  324. ** ARGUMENTS:
  325. **    anObject        a MiscPriorityQueue
  326. **
  327. ** LAST MODIFIED:
  328. **    Sun Aug 23 15:17:03 EDT 1992    Mark Onyschuk
  329. **
  330. ** DESCRIPTION:
  331. **    Compares <anObject> with the reciever and returns YES if
  332. **    <anObject> is a MiscPriorityQueue, and both <anObject> and self
  333. **    contain the same objects in the same order.
  334. **
  335. ** RETURNS:
  336. **    YES if <anObject> is equal to the receiver, or
  337. **    NO otherwise.
  338. */
  339.  
  340. - (BOOL)isEqual:anObject
  341. {
  342.     int i;
  343.     
  344.     if (anObject == self)
  345.         return YES;
  346.     
  347.     if (([anObject isKindOf:[self class]]) &&
  348.         ((i = [anObject count]) == [self count]))
  349.     {
  350.         /* we make copies because priority queues are partially
  351.     ** ordered trees and the contents of one queue and another
  352.     ** though equal might be arranged different order inside the
  353.     ** tree.
  354.     */
  355.     id copyA = [self copy];
  356.     id copyB = [anObject copy];
  357.  
  358.     while ((i--) && ([copyA removeObject] == [copyB removeObject]))
  359.         ;
  360.  
  361.     return (i < 0) ? YES : NO;
  362.     }
  363.     return NO;
  364. }
  365.  
  366.  
  367. /* NAME:
  368. **    - appendQueue:(MiscPriorityQueue *)otherQueue
  369. **
  370. ** ARGUMENTS:
  371. **    otherQueue        source queue
  372. **
  373. ** LAST MODIFIED:
  374. **    Sun Aug 23 15:17:03 EDT 1992    Mark Onyschuk
  375. **
  376. ** DESCRIPTION:
  377. **    Appends the contents of <otherQueue> to the reciever.
  378. **
  379. ** RETURNS:
  380. **    self.
  381. */
  382.  
  383. - appendQueue:(MiscPriorityQueue *)otherQueue
  384. {
  385.     int i;
  386.  
  387.     for (i = otherQueue->top; i > 0; i--)
  388.         [self addObject : ((NODE *)(otherQueue->heap))[i].object
  389.        withPriority : ((NODE *)(otherQueue->heap))[i].priority];
  390.  
  391.     return self;
  392. }
  393.  
  394.  
  395. /* GETTING AND SETTING THE CAPACITY OF A PRIORITY QUEUE *****************/
  396.  
  397. /* NAME:
  398. **    -(unsigned int)capacity
  399. **
  400. ** ARGUMENTS:
  401. **    none.
  402. **
  403. ** LAST EDITED:
  404. **    Sun Aug 23 15:17:03 EDT 1992    Mark Onyschuk
  405. **
  406. ** DESCRIPTION:
  407. **    Returns the maximum number of objects that can be stored in the
  408. **    Queue without allocating more memory for it. When new memory is
  409. **    allocated, it's taken from the same zone that was specified
  410. **    when the Queue was created.
  411. **
  412. ** RETURNS:
  413. **    capacity.
  414. */
  415.  
  416. - (unsigned int)capacity
  417. {
  418.     return size;
  419. }
  420.  
  421. /* NAME:
  422. **    - setAvailableCapacity:(unsigned int)capacity
  423. **
  424. ** ARGUMENTS:
  425. **    capacity            unsigned integer
  426. **
  427. ** LAST MODIFIED:
  428. **    Tue Sep  1 15:56:18 EDT 1992    Mark Onyschuk
  429. **
  430. ** DESCRIPTION:
  431. **    Allocates or reallocates heap memory to contain
  432. **    <capacity> objects.
  433. **
  434. ** RETURNS:
  435. **    nil if <capacity> is less than <top>, or
  436. **    self otherwise.
  437. */
  438.  
  439. - setAvailableCapacity:(unsigned int)capacity
  440. {
  441.     if (capacity < top)
  442.         return nil;
  443.  
  444.     size  = capacity;
  445.     heap  = HEAPREALLOC(size + 1);
  446.     
  447.     return self;
  448. }
  449.  
  450.  
  451. /* EMPTYING A PRIORITY QUEUE ********************************************/
  452.  
  453. - empty
  454. {
  455.     top = 0;
  456.     return self;
  457. }
  458.  
  459. - freeObjects
  460. {
  461.     for (; top > 0; top--)
  462.         [OBJECTAT(top) free];
  463.  
  464.     return self;
  465. }   
  466.  
  467.  
  468. /* SENDING MESSAGES TO OBJECTS ******************************************/
  469.  
  470. - makeObjectsPerform:(SEL)aSelector
  471. {
  472.     int    i;
  473.     
  474.     for (i = top; i > 0; i--)
  475.         if ([OBJECTAT(i) respondsTo:aSelector])
  476.         [OBJECTAT(i) perform:aSelector];
  477.     
  478.     return self;
  479. }
  480.  
  481. - makeObjectsPerform:(SEL)aSelector with:anObject
  482. {
  483.     int    i;
  484.     
  485.     for (i = top; i > 0; i--)
  486.         if ([OBJECTAT(i) respondsTo:aSelector])
  487.         [OBJECTAT(i) perform:aSelector with:anObject];
  488.  
  489.     return self;
  490. }
  491.  
  492.  
  493. /* READING AND WRITING TYPED STREAMS ************************************/
  494.  
  495. - read:(NXTypedStream *)stream
  496. {
  497.     int i;
  498.     
  499.     [super read:stream];
  500.     
  501.     NXReadType(stream, "i", &size);
  502.     NXReadType(stream, "i", &top);
  503.  
  504.     if (heap)
  505.         free(heap);
  506.  
  507.     heap = (NODE *)HEAPMALLOC(size+1);
  508.     
  509.     for (i = 1; i <= top; i ++)
  510.     {
  511.     OBJECTAT(i) = NXReadObject(stream);
  512.         NXReadType(stream, "i", &(PRIORITYOF(i)));
  513.     }
  514.     
  515.     return self;
  516. }
  517.  
  518. - write:(NXTypedStream *)stream
  519. {
  520.     int i;
  521.     
  522.     [super write:stream];
  523.     
  524.     NXWriteType(stream, "i", &size);
  525.     NXWriteType(stream, "i", &top);
  526.  
  527.     for (i = 1; i < top; i ++)
  528.     {
  529.         NXWriteObject(stream, OBJECTAT(i));
  530.     NXWriteType(stream, "i", &(PRIORITYOF(i))); 
  531.     }
  532.     
  533.     return self;
  534. }
  535.  
  536. @end
  537.