10Sstevel@tonic-gate /* 2*11038SRao.Shoaib@Sun.COM * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 30Sstevel@tonic-gate * Copyright (c) 1997,1999 by Internet Software Consortium. 40Sstevel@tonic-gate * 50Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software for any 60Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above 70Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies. 80Sstevel@tonic-gate * 9*11038SRao.Shoaib@Sun.COM * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 10*11038SRao.Shoaib@Sun.COM * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11*11038SRao.Shoaib@Sun.COM * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 12*11038SRao.Shoaib@Sun.COM * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13*11038SRao.Shoaib@Sun.COM * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14*11038SRao.Shoaib@Sun.COM * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 15*11038SRao.Shoaib@Sun.COM * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 160Sstevel@tonic-gate */ 170Sstevel@tonic-gate 18*11038SRao.Shoaib@Sun.COM /*% 190Sstevel@tonic-gate * Heap implementation of priority queues adapted from the following: 200Sstevel@tonic-gate * 210Sstevel@tonic-gate * _Introduction to Algorithms_, Cormen, Leiserson, and Rivest, 220Sstevel@tonic-gate * MIT Press / McGraw Hill, 1990, ISBN 0-262-03141-8, chapter 7. 230Sstevel@tonic-gate * 240Sstevel@tonic-gate * _Algorithms_, Second Edition, Sedgewick, Addison-Wesley, 1988, 250Sstevel@tonic-gate * ISBN 0-201-06673-4, chapter 11. 260Sstevel@tonic-gate */ 270Sstevel@tonic-gate 280Sstevel@tonic-gate #if !defined(LINT) && !defined(CODECENTER) 29*11038SRao.Shoaib@Sun.COM static const char rcsid[] = "$Id: heap.c,v 1.4 2006/03/09 23:57:56 marka Exp $"; 300Sstevel@tonic-gate #endif /* not lint */ 310Sstevel@tonic-gate 320Sstevel@tonic-gate #include "port_before.h" 330Sstevel@tonic-gate 340Sstevel@tonic-gate #include <stddef.h> 350Sstevel@tonic-gate #include <stdlib.h> 360Sstevel@tonic-gate #include <errno.h> 370Sstevel@tonic-gate 380Sstevel@tonic-gate #include "port_after.h" 390Sstevel@tonic-gate 400Sstevel@tonic-gate #include <isc/heap.h> 410Sstevel@tonic-gate 42*11038SRao.Shoaib@Sun.COM /*% 430Sstevel@tonic-gate * Note: to make heap_parent and heap_left easy to compute, the first 440Sstevel@tonic-gate * element of the heap array is not used; i.e. heap subscripts are 1-based, 450Sstevel@tonic-gate * not 0-based. 460Sstevel@tonic-gate */ 470Sstevel@tonic-gate #define heap_parent(i) ((i) >> 1) 480Sstevel@tonic-gate #define heap_left(i) ((i) << 1) 490Sstevel@tonic-gate 500Sstevel@tonic-gate #define ARRAY_SIZE_INCREMENT 512 510Sstevel@tonic-gate 520Sstevel@tonic-gate heap_context 530Sstevel@tonic-gate heap_new(heap_higher_priority_func higher_priority, heap_index_func index, 540Sstevel@tonic-gate int array_size_increment) { 550Sstevel@tonic-gate heap_context ctx; 560Sstevel@tonic-gate 57*11038SRao.Shoaib@Sun.COM if (higher_priority == NULL) 58*11038SRao.Shoaib@Sun.COM return (NULL); 59*11038SRao.Shoaib@Sun.COM 600Sstevel@tonic-gate ctx = (heap_context)malloc(sizeof (struct heap_context)); 61*11038SRao.Shoaib@Sun.COM if (ctx == NULL) 620Sstevel@tonic-gate return (NULL); 63*11038SRao.Shoaib@Sun.COM 640Sstevel@tonic-gate ctx->array_size = 0; 650Sstevel@tonic-gate if (array_size_increment == 0) 660Sstevel@tonic-gate ctx->array_size_increment = ARRAY_SIZE_INCREMENT; 670Sstevel@tonic-gate else 680Sstevel@tonic-gate ctx->array_size_increment = array_size_increment; 690Sstevel@tonic-gate ctx->heap_size = 0; 700Sstevel@tonic-gate ctx->heap = NULL; 710Sstevel@tonic-gate ctx->higher_priority = higher_priority; 720Sstevel@tonic-gate ctx->index = index; 730Sstevel@tonic-gate return (ctx); 740Sstevel@tonic-gate } 750Sstevel@tonic-gate 760Sstevel@tonic-gate int 770Sstevel@tonic-gate heap_free(heap_context ctx) { 780Sstevel@tonic-gate if (ctx == NULL) { 790Sstevel@tonic-gate errno = EINVAL; 800Sstevel@tonic-gate return (-1); 810Sstevel@tonic-gate } 820Sstevel@tonic-gate 830Sstevel@tonic-gate if (ctx->heap != NULL) 840Sstevel@tonic-gate free(ctx->heap); 850Sstevel@tonic-gate free(ctx); 860Sstevel@tonic-gate 870Sstevel@tonic-gate return (0); 880Sstevel@tonic-gate } 890Sstevel@tonic-gate 900Sstevel@tonic-gate static int 910Sstevel@tonic-gate heap_resize(heap_context ctx) { 920Sstevel@tonic-gate void **new_heap; 930Sstevel@tonic-gate 940Sstevel@tonic-gate ctx->array_size += ctx->array_size_increment; 950Sstevel@tonic-gate new_heap = (void **)realloc(ctx->heap, 960Sstevel@tonic-gate (ctx->array_size) * (sizeof (void *))); 970Sstevel@tonic-gate if (new_heap == NULL) { 980Sstevel@tonic-gate errno = ENOMEM; 990Sstevel@tonic-gate return (-1); 1000Sstevel@tonic-gate } 1010Sstevel@tonic-gate ctx->heap = new_heap; 1020Sstevel@tonic-gate return (0); 1030Sstevel@tonic-gate } 1040Sstevel@tonic-gate 1050Sstevel@tonic-gate static void 1060Sstevel@tonic-gate float_up(heap_context ctx, int i, void *elt) { 1070Sstevel@tonic-gate int p; 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate for ( p = heap_parent(i); 1100Sstevel@tonic-gate i > 1 && ctx->higher_priority(elt, ctx->heap[p]); 1110Sstevel@tonic-gate i = p, p = heap_parent(i) ) { 1120Sstevel@tonic-gate ctx->heap[i] = ctx->heap[p]; 1130Sstevel@tonic-gate if (ctx->index != NULL) 1140Sstevel@tonic-gate (ctx->index)(ctx->heap[i], i); 1150Sstevel@tonic-gate } 1160Sstevel@tonic-gate ctx->heap[i] = elt; 1170Sstevel@tonic-gate if (ctx->index != NULL) 1180Sstevel@tonic-gate (ctx->index)(ctx->heap[i], i); 1190Sstevel@tonic-gate } 1200Sstevel@tonic-gate 1210Sstevel@tonic-gate static void 1220Sstevel@tonic-gate sink_down(heap_context ctx, int i, void *elt) { 1230Sstevel@tonic-gate int j, size, half_size; 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate size = ctx->heap_size; 1260Sstevel@tonic-gate half_size = size / 2; 1270Sstevel@tonic-gate while (i <= half_size) { 1280Sstevel@tonic-gate /* find smallest of the (at most) two children */ 1290Sstevel@tonic-gate j = heap_left(i); 1300Sstevel@tonic-gate if (j < size && ctx->higher_priority(ctx->heap[j+1], 1310Sstevel@tonic-gate ctx->heap[j])) 1320Sstevel@tonic-gate j++; 1330Sstevel@tonic-gate if (ctx->higher_priority(elt, ctx->heap[j])) 1340Sstevel@tonic-gate break; 1350Sstevel@tonic-gate ctx->heap[i] = ctx->heap[j]; 1360Sstevel@tonic-gate if (ctx->index != NULL) 1370Sstevel@tonic-gate (ctx->index)(ctx->heap[i], i); 1380Sstevel@tonic-gate i = j; 1390Sstevel@tonic-gate } 1400Sstevel@tonic-gate ctx->heap[i] = elt; 1410Sstevel@tonic-gate if (ctx->index != NULL) 1420Sstevel@tonic-gate (ctx->index)(ctx->heap[i], i); 1430Sstevel@tonic-gate } 1440Sstevel@tonic-gate 1450Sstevel@tonic-gate int 1460Sstevel@tonic-gate heap_insert(heap_context ctx, void *elt) { 1470Sstevel@tonic-gate int i; 1480Sstevel@tonic-gate 1490Sstevel@tonic-gate if (ctx == NULL || elt == NULL) { 1500Sstevel@tonic-gate errno = EINVAL; 1510Sstevel@tonic-gate return (-1); 1520Sstevel@tonic-gate } 1530Sstevel@tonic-gate 1540Sstevel@tonic-gate i = ++ctx->heap_size; 1550Sstevel@tonic-gate if (ctx->heap_size >= ctx->array_size && heap_resize(ctx) < 0) 1560Sstevel@tonic-gate return (-1); 1570Sstevel@tonic-gate 1580Sstevel@tonic-gate float_up(ctx, i, elt); 1590Sstevel@tonic-gate 1600Sstevel@tonic-gate return (0); 1610Sstevel@tonic-gate } 1620Sstevel@tonic-gate 1630Sstevel@tonic-gate int 1640Sstevel@tonic-gate heap_delete(heap_context ctx, int i) { 1650Sstevel@tonic-gate void *elt; 166*11038SRao.Shoaib@Sun.COM int less; 1670Sstevel@tonic-gate 1680Sstevel@tonic-gate if (ctx == NULL || i < 1 || i > ctx->heap_size) { 1690Sstevel@tonic-gate errno = EINVAL; 1700Sstevel@tonic-gate return (-1); 1710Sstevel@tonic-gate } 1720Sstevel@tonic-gate 173*11038SRao.Shoaib@Sun.COM if (i == ctx->heap_size) { 174*11038SRao.Shoaib@Sun.COM ctx->heap_size--; 175*11038SRao.Shoaib@Sun.COM } else { 176*11038SRao.Shoaib@Sun.COM elt = ctx->heap[ctx->heap_size--]; 177*11038SRao.Shoaib@Sun.COM less = ctx->higher_priority(elt, ctx->heap[i]); 178*11038SRao.Shoaib@Sun.COM ctx->heap[i] = elt; 179*11038SRao.Shoaib@Sun.COM if (less) 180*11038SRao.Shoaib@Sun.COM float_up(ctx, i, ctx->heap[i]); 181*11038SRao.Shoaib@Sun.COM else 182*11038SRao.Shoaib@Sun.COM sink_down(ctx, i, ctx->heap[i]); 183*11038SRao.Shoaib@Sun.COM } 1840Sstevel@tonic-gate 1850Sstevel@tonic-gate return (0); 1860Sstevel@tonic-gate } 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate int 1890Sstevel@tonic-gate heap_increased(heap_context ctx, int i) { 1900Sstevel@tonic-gate if (ctx == NULL || i < 1 || i > ctx->heap_size) { 1910Sstevel@tonic-gate errno = EINVAL; 1920Sstevel@tonic-gate return (-1); 1930Sstevel@tonic-gate } 1940Sstevel@tonic-gate 1950Sstevel@tonic-gate float_up(ctx, i, ctx->heap[i]); 1960Sstevel@tonic-gate 1970Sstevel@tonic-gate return (0); 1980Sstevel@tonic-gate } 1990Sstevel@tonic-gate 2000Sstevel@tonic-gate int 2010Sstevel@tonic-gate heap_decreased(heap_context ctx, int i) { 2020Sstevel@tonic-gate if (ctx == NULL || i < 1 || i > ctx->heap_size) { 2030Sstevel@tonic-gate errno = EINVAL; 2040Sstevel@tonic-gate return (-1); 2050Sstevel@tonic-gate } 2060Sstevel@tonic-gate 2070Sstevel@tonic-gate sink_down(ctx, i, ctx->heap[i]); 2080Sstevel@tonic-gate 2090Sstevel@tonic-gate return (0); 2100Sstevel@tonic-gate } 2110Sstevel@tonic-gate 2120Sstevel@tonic-gate void * 2130Sstevel@tonic-gate heap_element(heap_context ctx, int i) { 2140Sstevel@tonic-gate if (ctx == NULL || i < 1 || i > ctx->heap_size) { 2150Sstevel@tonic-gate errno = EINVAL; 2160Sstevel@tonic-gate return (NULL); 2170Sstevel@tonic-gate } 2180Sstevel@tonic-gate 2190Sstevel@tonic-gate return (ctx->heap[i]); 2200Sstevel@tonic-gate } 2210Sstevel@tonic-gate 2220Sstevel@tonic-gate int 2230Sstevel@tonic-gate heap_for_each(heap_context ctx, heap_for_each_func action, void *uap) { 2240Sstevel@tonic-gate int i; 2250Sstevel@tonic-gate 2260Sstevel@tonic-gate if (ctx == NULL || action == NULL) { 2270Sstevel@tonic-gate errno = EINVAL; 2280Sstevel@tonic-gate return (-1); 2290Sstevel@tonic-gate } 2300Sstevel@tonic-gate 2310Sstevel@tonic-gate for (i = 1; i <= ctx->heap_size; i++) 2320Sstevel@tonic-gate (action)(ctx->heap[i], uap); 2330Sstevel@tonic-gate return (0); 2340Sstevel@tonic-gate } 235*11038SRao.Shoaib@Sun.COM 236*11038SRao.Shoaib@Sun.COM /*! \file */ 237