src/queue.cpp
changeset 6678 6353b8865d42
parent 6431 7f89731a0507
child 6872 1c4a4a609f85
child 8533 a9b708fe4a00
equal deleted inserted replaced
6677:0578c2e31ed1 6678:6353b8865d42
     1 /* $Id$ */
     1 /* $Id$ */
       
     2 
       
     3 /** @file queue.cpp */
     2 
     4 
     3 #include "stdafx.h"
     5 #include "stdafx.h"
     4 #include "openttd.h"
     6 #include "openttd.h"
     5 #include "queue.h"
     7 #include "queue.h"
     6 #include "helpers.hpp"
     8 #include "helpers.hpp"
    89  */
    91  */
    90 
    92 
    91 #define BINARY_HEAP_BLOCKSIZE (1 << BINARY_HEAP_BLOCKSIZE_BITS)
    93 #define BINARY_HEAP_BLOCKSIZE (1 << BINARY_HEAP_BLOCKSIZE_BITS)
    92 #define BINARY_HEAP_BLOCKSIZE_MASK (BINARY_HEAP_BLOCKSIZE - 1)
    94 #define BINARY_HEAP_BLOCKSIZE_MASK (BINARY_HEAP_BLOCKSIZE - 1)
    93 
    95 
    94 // To make our life easy, we make the next define
    96 /* To make our life easy, we make the next define
    95 //  Because Binary Heaps works with array from 1 to n,
    97  *  Because Binary Heaps works with array from 1 to n,
    96 //  and C with array from 0 to n-1, and we don't like typing
    98  *  and C with array from 0 to n-1, and we don't like typing
    97 //  q->data.binaryheap.elements[i - 1] every time, we use this define.
    99  *  q->data.binaryheap.elements[i - 1] every time, we use this define. */
    98 #define BIN_HEAP_ARR(i) q->data.binaryheap.elements[((i) - 1) >> BINARY_HEAP_BLOCKSIZE_BITS][((i) - 1) & BINARY_HEAP_BLOCKSIZE_MASK]
   100 #define BIN_HEAP_ARR(i) q->data.binaryheap.elements[((i) - 1) >> BINARY_HEAP_BLOCKSIZE_BITS][((i) - 1) & BINARY_HEAP_BLOCKSIZE_MASK]
    99 
   101 
   100 static void BinaryHeap_Clear(Queue* q, bool free_values)
   102 static void BinaryHeap_Clear(Queue* q, bool free_values)
   101 {
   103 {
   102 	/* Free all items if needed and free all but the first blocks of memory */
   104 	/* Free all items if needed and free all but the first blocks of memory */
   112 		if (free_values) {
   114 		if (free_values) {
   113 			for (j = 0; j < (1 << BINARY_HEAP_BLOCKSIZE_BITS); j++) {
   115 			for (j = 0; j < (1 << BINARY_HEAP_BLOCKSIZE_BITS); j++) {
   114 				/* For every element in the block */
   116 				/* For every element in the block */
   115 				if ((q->data.binaryheap.size >> BINARY_HEAP_BLOCKSIZE_BITS) == i &&
   117 				if ((q->data.binaryheap.size >> BINARY_HEAP_BLOCKSIZE_BITS) == i &&
   116 						(q->data.binaryheap.size & BINARY_HEAP_BLOCKSIZE_MASK) == j) {
   118 						(q->data.binaryheap.size & BINARY_HEAP_BLOCKSIZE_MASK) == j) {
   117 					break; /* We're past the last element */
   119 					break; // We're past the last element
   118 				}
   120 				}
   119 				free(q->data.binaryheap.elements[i][j].item);
   121 				free(q->data.binaryheap.elements[i][j].item);
   120 			}
   122 			}
   121 		}
   123 		}
   122 		if (i != 0) {
   124 		if (i != 0) {
   158 #ifdef QUEUE_DEBUG
   160 #ifdef QUEUE_DEBUG
   159 		printf("[BinaryHeap] Increasing size of elements to %d nodes\n", q->data.binaryheap.blocks *  BINARY_HEAP_BLOCKSIZE);
   161 		printf("[BinaryHeap] Increasing size of elements to %d nodes\n", q->data.binaryheap.blocks *  BINARY_HEAP_BLOCKSIZE);
   160 #endif
   162 #endif
   161 	}
   163 	}
   162 
   164 
   163 	// Add the item at the end of the array
   165 	/* Add the item at the end of the array */
   164 	BIN_HEAP_ARR(q->data.binaryheap.size + 1).priority = priority;
   166 	BIN_HEAP_ARR(q->data.binaryheap.size + 1).priority = priority;
   165 	BIN_HEAP_ARR(q->data.binaryheap.size + 1).item = item;
   167 	BIN_HEAP_ARR(q->data.binaryheap.size + 1).item = item;
   166 	q->data.binaryheap.size++;
   168 	q->data.binaryheap.size++;
   167 
   169 
   168 	// Now we are going to check where it belongs. As long as the parent is
   170 	/* Now we are going to check where it belongs. As long as the parent is
   169 	// bigger, we switch with the parent
   171 	 * bigger, we switch with the parent */
   170 	{
   172 	{
   171 		BinaryHeapNode temp;
   173 		BinaryHeapNode temp;
   172 		int i;
   174 		int i;
   173 		int j;
   175 		int j;
   174 
   176 
   175 		i = q->data.binaryheap.size;
   177 		i = q->data.binaryheap.size;
   176 		while (i > 1) {
   178 		while (i > 1) {
   177 			// Get the parent of this object (divide by 2)
   179 			/* Get the parent of this object (divide by 2) */
   178 			j = i / 2;
   180 			j = i / 2;
   179 			// Is the parent bigger then the current, switch them
   181 			/* Is the parent bigger then the current, switch them */
   180 			if (BIN_HEAP_ARR(i).priority <= BIN_HEAP_ARR(j).priority) {
   182 			if (BIN_HEAP_ARR(i).priority <= BIN_HEAP_ARR(j).priority) {
   181 				temp = BIN_HEAP_ARR(j);
   183 				temp = BIN_HEAP_ARR(j);
   182 				BIN_HEAP_ARR(j) = BIN_HEAP_ARR(i);
   184 				BIN_HEAP_ARR(j) = BIN_HEAP_ARR(i);
   183 				BIN_HEAP_ARR(i) = temp;
   185 				BIN_HEAP_ARR(i) = temp;
   184 				i = j;
   186 				i = j;
   185 			} else {
   187 			} else {
   186 				// It is not, we're done!
   188 				/* It is not, we're done! */
   187 				break;
   189 				break;
   188 			}
   190 			}
   189 		}
   191 		}
   190 	}
   192 	}
   191 
   193 
   198 
   200 
   199 #ifdef QUEUE_DEBUG
   201 #ifdef QUEUE_DEBUG
   200 	printf("[BinaryHeap] Deleting an element. There are %d elements left\n", q->data.binaryheap.size);
   202 	printf("[BinaryHeap] Deleting an element. There are %d elements left\n", q->data.binaryheap.size);
   201 #endif
   203 #endif
   202 
   204 
   203 	// First, we try to find the item..
   205 	/* First, we try to find the item.. */
   204 	do {
   206 	do {
   205 		if (BIN_HEAP_ARR(i + 1).item == item) break;
   207 		if (BIN_HEAP_ARR(i + 1).item == item) break;
   206 		i++;
   208 		i++;
   207 	} while (i < q->data.binaryheap.size);
   209 	} while (i < q->data.binaryheap.size);
   208 	// We did not find the item, so we return false
   210 	/* We did not find the item, so we return false */
   209 	if (i == q->data.binaryheap.size) return false;
   211 	if (i == q->data.binaryheap.size) return false;
   210 
   212 
   211 	// Now we put the last item over the current item while decreasing the size of the elements
   213 	/* Now we put the last item over the current item while decreasing the size of the elements */
   212 	q->data.binaryheap.size--;
   214 	q->data.binaryheap.size--;
   213 	BIN_HEAP_ARR(i + 1) = BIN_HEAP_ARR(q->data.binaryheap.size + 1);
   215 	BIN_HEAP_ARR(i + 1) = BIN_HEAP_ARR(q->data.binaryheap.size + 1);
   214 
   216 
   215 	// Now the only thing we have to do, is resort it..
   217 	/* Now the only thing we have to do, is resort it..
   216 	// On place i there is the item to be sorted.. let's start there
   218 	 * On place i there is the item to be sorted.. let's start there */
   217 	{
   219 	{
   218 		uint j;
   220 		uint j;
   219 		BinaryHeapNode temp;
   221 		BinaryHeapNode temp;
   220 		/* Because of the fact that Binary Heap uses array from 1 to n, we need to
   222 		/* Because of the fact that Binary Heap uses array from 1 to n, we need to
   221 		 * increase i by 1
   223 		 * increase i by 1
   222 		 */
   224 		 */
   223 		i++;
   225 		i++;
   224 
   226 
   225 		for (;;) {
   227 		for (;;) {
   226 			j = i;
   228 			j = i;
   227 			// Check if we have 2 childs
   229 			/* Check if we have 2 childs */
   228 			if (2 * j + 1 <= q->data.binaryheap.size) {
   230 			if (2 * j + 1 <= q->data.binaryheap.size) {
   229 				// Is this child smaller than the parent?
   231 				/* Is this child smaller than the parent? */
   230 				if (BIN_HEAP_ARR(j).priority >= BIN_HEAP_ARR(2 * j).priority) i = 2 * j;
   232 				if (BIN_HEAP_ARR(j).priority >= BIN_HEAP_ARR(2 * j).priority) i = 2 * j;
   231 				// Yes, we _need_ to use i here, not j, because we want to have the smallest child
   233 				/* Yes, we _need_ to use i here, not j, because we want to have the smallest child
   232 				//  This way we get that straight away!
   234 				 *  This way we get that straight away! */
   233 				if (BIN_HEAP_ARR(i).priority >= BIN_HEAP_ARR(2 * j + 1).priority) i = 2 * j + 1;
   235 				if (BIN_HEAP_ARR(i).priority >= BIN_HEAP_ARR(2 * j + 1).priority) i = 2 * j + 1;
   234 			// Do we have one child?
   236 			/* Do we have one child? */
   235 			} else if (2 * j <= q->data.binaryheap.size) {
   237 			} else if (2 * j <= q->data.binaryheap.size) {
   236 				if (BIN_HEAP_ARR(j).priority >= BIN_HEAP_ARR(2 * j).priority) i = 2 * j;
   238 				if (BIN_HEAP_ARR(j).priority >= BIN_HEAP_ARR(2 * j).priority) i = 2 * j;
   237 			}
   239 			}
   238 
   240 
   239 			// One of our childs is smaller than we are, switch
   241 			/* One of our childs is smaller than we are, switch */
   240 			if (i != j) {
   242 			if (i != j) {
   241 				temp = BIN_HEAP_ARR(j);
   243 				temp = BIN_HEAP_ARR(j);
   242 				BIN_HEAP_ARR(j) = BIN_HEAP_ARR(i);
   244 				BIN_HEAP_ARR(j) = BIN_HEAP_ARR(i);
   243 				BIN_HEAP_ARR(i) = temp;
   245 				BIN_HEAP_ARR(i) = temp;
   244 			} else {
   246 			} else {
   245 				// None of our childs is smaller, so we stay here.. stop :)
   247 				/* None of our childs is smaller, so we stay here.. stop :) */
   246 				break;
   248 				break;
   247 			}
   249 			}
   248 		}
   250 		}
   249 	}
   251 	}
   250 
   252 
   259 	printf("[BinaryHeap] Popping an element. There are %d elements left\n", q->data.binaryheap.size);
   261 	printf("[BinaryHeap] Popping an element. There are %d elements left\n", q->data.binaryheap.size);
   260 #endif
   262 #endif
   261 
   263 
   262 	if (q->data.binaryheap.size == 0) return NULL;
   264 	if (q->data.binaryheap.size == 0) return NULL;
   263 
   265 
   264 	// The best item is always on top, so give that as result
   266 	/* The best item is always on top, so give that as result */
   265 	result = BIN_HEAP_ARR(1).item;
   267 	result = BIN_HEAP_ARR(1).item;
   266 	// And now we should get rid of this item...
   268 	/* And now we should get rid of this item... */
   267 	BinaryHeap_Delete(q, BIN_HEAP_ARR(1).item, BIN_HEAP_ARR(1).priority);
   269 	BinaryHeap_Delete(q, BIN_HEAP_ARR(1).item, BIN_HEAP_ARR(1).priority);
   268 
   270 
   269 	return result;
   271 	return result;
   270 }
   272 }
   271 
   273 
   277 	q->del = BinaryHeap_Delete;
   279 	q->del = BinaryHeap_Delete;
   278 	q->clear = BinaryHeap_Clear;
   280 	q->clear = BinaryHeap_Clear;
   279 	q->free = BinaryHeap_Free;
   281 	q->free = BinaryHeap_Free;
   280 	q->data.binaryheap.max_size = max_size;
   282 	q->data.binaryheap.max_size = max_size;
   281 	q->data.binaryheap.size = 0;
   283 	q->data.binaryheap.size = 0;
   282 	// We malloc memory in block of BINARY_HEAP_BLOCKSIZE
   284 	/* We malloc memory in block of BINARY_HEAP_BLOCKSIZE
   283 	//   It autosizes when it runs out of memory
   285 	 *   It autosizes when it runs out of memory */
   284 	q->data.binaryheap.elements = CallocT<BinaryHeapNode*>((max_size - 1) / BINARY_HEAP_BLOCKSIZE + 1);
   286 	q->data.binaryheap.elements = CallocT<BinaryHeapNode*>((max_size - 1) / BINARY_HEAP_BLOCKSIZE + 1);
   285 	q->data.binaryheap.elements[0] = MallocT<BinaryHeapNode>(BINARY_HEAP_BLOCKSIZE);
   287 	q->data.binaryheap.elements[0] = MallocT<BinaryHeapNode>(BINARY_HEAP_BLOCKSIZE);
   286 	q->data.binaryheap.blocks = 1;
   288 	q->data.binaryheap.blocks = 1;
   287 #ifdef QUEUE_DEBUG
   289 #ifdef QUEUE_DEBUG
   288 	printf("[BinaryHeap] Initial size of elements is %d nodes\n", BINARY_HEAP_BLOCKSIZE);
   290 	printf("[BinaryHeap] Initial size of elements is %d nodes\n", BINARY_HEAP_BLOCKSIZE);
   426 		}
   428 		}
   427 	}
   429 	}
   428 	h->size = 0;
   430 	h->size = 0;
   429 }
   431 }
   430 
   432 
   431 /* Finds the node that that saves this key pair. If it is not
   433 /** Finds the node that that saves this key pair. If it is not
   432  * found, returns NULL. If it is found, *prev is set to the
   434  * found, returns NULL. If it is found, *prev is set to the
   433  * node before the one found, or if the node found was the first in the bucket
   435  * node before the one found, or if the node found was the first in the bucket
   434  * to NULL. If it is not found, *prev is set to the last HashNode in the
   436  * to NULL. If it is not found, *prev is set to the last HashNode in the
   435  * bucket, or NULL if it is empty. prev can also be NULL, in which case it is
   437  * bucket, or NULL if it is empty. prev can also be NULL, in which case it is
   436  * not used for output.
   438  * not used for output.
   480 }
   482 }
   481 
   483 
   482 void* Hash_Delete(Hash* h, uint key1, uint key2)
   484 void* Hash_Delete(Hash* h, uint key1, uint key2)
   483 {
   485 {
   484 	void* result;
   486 	void* result;
   485 	HashNode* prev; /* Used as output var for below function call */
   487 	HashNode* prev; // Used as output var for below function call
   486 	HashNode* node = Hash_FindNode(h, key1, key2, &prev);
   488 	HashNode* node = Hash_FindNode(h, key1, key2, &prev);
   487 
   489 
   488 	if (node == NULL) {
   490 	if (node == NULL) {
   489 		/* not found */
   491 		/* not found */
   490 		result = NULL;
   492 		result = NULL;