Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Related Pages

vector.c

00001 /* 00002 00003 The BLAH library, a container library 00004 Copyright (C) 1997-2004 The CDG Team <cdg@nats.informatik.uni-hamburg.de> 00005 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 2 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program; if not, write to the Free Software 00018 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00019 00020 Contact: blah@nats.informatik.uni-hamburg.de 00021 00022 $Id: vector.c,v 1.17 2004/03/30 10:07:59 foth Exp $ 00023 00024 */ 00025 00026 /* ------------------------------------------------------------------- */ 00027 00028 /* ---------------------------------------------------------------------- 00029 * @defgroup Vector Vectors 00030 * implementation of vectors. 00031 * 00032 * A Vector is a one-dimensional array but allows for automatic resizing.i.e,the size 00033 * need not be known in advance. 00034 * @{ 00035 */ 00036 00037 /* ----INCLUDES------------------------------------------------------ */ 00038 00039 #include <stdio.h> 00040 #include <string.h> 00041 #include "blah.h" 00042 00043 /* ------------------------------------------------------------------- */ 00044 #define RESIZEFACTOR 2 00045 00046 /* ---------------------------------------------------------------------- 00047 * internal representation of a vector 00048 */ 00049 struct VectorStruct { 00050 #if VECTOR_DEBUG 00051 char *id; /**< identification string */ 00052 #endif 00053 int count; /**< number of entries */ 00054 int capacity; /**< capacity of table */ 00055 void **entries; /**< table of entries */ 00056 }; 00057 00058 /* ------------------------------------------------------------------- */ 00059 #if VECTOR_DEBUG 00060 static char *vectorID = "Ingo"; 00061 00062 static void checkVector(Vector v, char *s) 00063 { 00064 if (!v) 00065 { 00066 fprintf( stderr, "ERROR: %s: vector must not be NULL\n", s ); 00067 abort(); 00068 } 00069 if (v->id != vectorID) 00070 { 00071 fprintf( stderr, "ERROR: %s: not a vector\n", s ); 00072 abort(); 00073 } 00074 } 00075 #else 00076 #define checkVector(v, s) 00077 #endif 00078 00079 /* ---------------------------------------------------------------------- 00080 * resize vector, double capacity. 00081 * 00082 * @param v the vector that has to be resized. 00083 * @returns the new vector after resizing. 00084 */ 00085 static void resizeVector(Vector v) 00086 { 00087 checkVector(v, "resizeVector"); 00088 00089 v->capacity=(int)(RESIZEFACTOR*v->capacity); 00090 v->entries=(Pointer *)memRealloc(v->entries, sizeof(Pointer)*v->capacity); 00091 memset(&(v->entries[v->count]), 00092 0, 00093 (v->capacity - v->count) * sizeof(Pointer)); 00094 } 00095 00096 /*----------------------------------------------------------------------- 00097 * creates a new vector with an initial capacity. 00098 * 00099 * specifying a correct or nearly correct capacity may slightly improve the efficiency. 00100 * 00101 * @param capacity the capacity with which the new vector has to be created. 00102 * @returns the new vector created with size capacity. 00103 */ 00104 Vector vectorNew(int capacity) 00105 { 00106 Vector v; 00107 int i; 00108 00109 v = (Vector)memMalloc( sizeof(VectorStruct) ); 00110 #if VECTOR_DEBUG 00111 v->id = vectorID; 00112 #endif 00113 v->count = 0; 00114 if(capacity <= 0) { 00115 capacity = 1; 00116 } 00117 v->capacity = capacity; 00118 v->entries = (Pointer *)memMalloc( sizeof(Pointer) * capacity ); 00119 for ( i = 0; i < capacity; i++ ) 00120 v->entries[i] = NULL; 00121 00122 return( v ); 00123 } 00124 00125 /* ---------------------------------------------------------------------- 00126 * deletes vector, but can't free memory for the content. 00127 * 00128 * @param v the vector that has to be deleted. 00129 */ 00130 void vectorDelete(Vector v) 00131 { 00132 checkVector(v, "vectorDelete" ); 00133 00134 memFree( v->entries ); 00135 memFree( v ); 00136 } 00137 00138 /* ---------------------------------------------------------------------- 00139 * adds a new element to the end of the vector. 00140 * 00141 * if necessary the vector automatically increases its capacity. 00142 * 00143 * @param v the vector to which the new element has to be added. 00144 * @param element the element that has to be added to the vector v. 00145 * @returns the index of the vector after addition. 00146 */ 00147 int vectorAddElement(Vector v, void *element) 00148 { 00149 checkVector(v, "vectorAddElement"); 00150 00151 /* The number of entries exceeds the capacity. Resize the table. */ 00152 if ( v->count >= v->capacity ) { resizeVector( v ); } 00153 00154 v->entries[v->count] = element; 00155 return( v->count++ ); 00156 } 00157 00158 00159 /* ---------------------------------------------------------------------- 00160 * sets the element at a specific index to a new element. 00161 * 00162 * if necessary the vector automatically increases its capacity. 00163 * 00164 * @param v the vector in which the element has to be set. 00165 * @param index the index at which the element that has to be set is located. 00166 * @returns the old element (or \a NULL) at that index. 00167 */ 00168 Pointer vectorElement(Vector v, int index) 00169 { 00170 checkVector( v, "vectorElement" ); 00171 00172 if ( index >= 0 && index < v->count ) 00173 return( v->entries[index] ); 00174 00175 fprintf( stderr, "WARNING: vectorElement: index %d out of range\n", index); 00176 abort(); 00177 } 00178 00179 /* ---------------------------------------------------------------------- 00180 * removes element at the index. 00181 * 00182 * all later elements move one position in front and size decreases. 00183 * inefficient, not recommended. 00184 * 00185 * @param v the vector from which the element has to be removed. 00186 * @param index the index at which the element that has to be removed is located. 00187 * @returns the old element at the specified index. 00188 */ 00189 Pointer vectorRemoveElementAt(Vector v, int index) 00190 { 00191 checkVector(v, "vectorRemoveElementAt"); 00192 00193 if ( index >= 0 && index < v->count ) { 00194 Pointer p = v->entries[index]; 00195 int i; 00196 00197 for ( i = index + 1; i < v->count; i++) 00198 v->entries[i - 1] = v->entries[i]; 00199 v->entries[v->count - 1] = NULL; 00200 v->count--; 00201 return( p ); 00202 } 00203 00204 fprintf( stderr, 00205 "WARNING: vectorRemoveElementAt: index %d out of range\n", 00206 index); 00207 abort(); 00208 } 00209 00210 /* ---------------------------------------------------------------------- 00211 * removes the specified element from the vector. 00212 * 00213 * If the element occurs multiple times, the first item will be removed. 00214 * If the element does not belong to the vector the program is aborted. 00215 * Not efficient,not recommended. 00216 * 00217 * @param v the vector from which the element to be removed is present. 00218 * @param element the element that has to be removed from the vector v. 00219 * @returns the associated index of the vector after removal. 00220 */ 00221 int vectorRemoveElement(Vector v, void *element) 00222 { 00223 int i; 00224 00225 checkVector(v, "vectorRemoveElement"); 00226 00227 i = vectorIndexOf( v, element, 0 ); 00228 if ( i < 0 ) { 00229 fprintf( stderr, "WARNING: vectorRemoveElement: no such element\n" ); 00230 abort(); 00231 } else { 00232 vectorRemoveElementAt( v, i ); 00233 } 00234 return( i ); 00235 } 00236 00237 00238 /* ---------------------------------------------------------------------- 00239 * inserts a new element at the specified index. 00240 * 00241 * Size increases automatically if necessary. 00242 * Inefficient method,Not recommended. 00243 * 00244 * @param v the vector into which the new element has to be added. 00245 * @param element the element that has to be added in the vector v. 00246 * @param index the specified index at which the insertion has to be done. 00247 * @returns the old element at that index (or \a NULL). 00248 */ 00249 Pointer vectorInsertElement(Vector v, 00250 void *element, 00251 int index ) 00252 { 00253 int i; 00254 Pointer p; 00255 00256 checkVector( v, "vectorInsertElement" ); 00257 00258 if ( index < 0 ) { 00259 fprintf( stderr, 00260 "WARNING: vectorInsertElement: index %d out of range\n", 00261 index); 00262 abort(); 00263 } 00264 00265 while (v->capacity<=index) { resizeVector(v); } 00266 00267 for (i=v->count-1; i>=index; i--) { v->entries[i+1]=v->entries[i]; } 00268 00269 p = v->entries[index]; 00270 v->entries[index] = element; 00271 v->count = max( v->count + 1, index + 1); 00272 return( p ); 00273 } 00274 00275 /* ---------------------------------------------------------------------- 00276 * sets the element at the given index. 00277 * 00278 * size may increase automatically if necessary. 00279 * 00280 * @param v the vector in which the specified element has to be set. 00281 * @param element the element that has to be set in the vector v. 00282 * @param index the index at which the element has to be set. 00283 * @returns the old element at that index. 00284 */ 00285 Pointer vectorSetElement(Vector v, void *element, int index) 00286 { 00287 Pointer p; 00288 00289 checkVector( v, "vectorSetElement" ); 00290 00291 if ( index < 0 ) { 00292 fprintf( stderr, "WARNING: vectorSetElement: index %d out of range\n", 00293 index); 00294 abort(); 00295 } 00296 00297 while (v->capacity<=index ) { resizeVector(v); } 00298 00299 p = v->entries[index]; 00300 v->entries[index] = element; 00301 v->count = max( v->count, index + 1); 00302 return( p ); 00303 } 00304 00305 /* ---------------------------------------------------------------------- 00306 * sets all elements between \a FROM and \a TO(excluding to) to a new value. 00307 * 00308 * size may increase automatically if necessary. 00309 * 00310 * @param v the vector in which the elements have to be set. 00311 * @param element determines the element that is being set. 00312 * @param from this is the source index from which the elements are set. 00313 * @param to this is the destination index until which the elements are set. 00314 * @returns the new vector after setting the elements. 00315 */ 00316 void vectorSetElements(Vector v, void *element, int from, int to) 00317 { 00318 int i; 00319 00320 checkVector(v, "vectorSetElements"); 00321 00322 if (from<0 || to<0) 00323 { 00324 fprintf(stderr, 00325 "ERROR: vectorSetElements: region from %d to %d out of range\n", 00326 from, to); 00327 abort(); 00328 } 00329 00330 if (from>to) 00331 { 00332 int tmp; 00333 00334 tmp = from; 00335 from = to; 00336 to = tmp; 00337 } 00338 00339 while (v->capacity<to) { resizeVector(v); } 00340 00341 if (!element) 00342 { 00343 memset(&(v->entries[from]), 0, (to-from)*sizeof(void *)); 00344 } 00345 else 00346 { 00347 for (i=from; i<to; i++) { v->entries[i]=element; } 00348 } 00349 00350 v->count=max(v->count, to); 00351 } 00352 00353 /* ---------------------------------------------------------------------- 00354 * sets all the elements to a new value. 00355 * 00356 * Size increases to the current capacity of the vector. 00357 * 00358 * @param v the vector in which all the elements have to be set to the new value. 00359 * @param element determines the element that is being set in vector v. 00360 */ 00361 void vectorSetAllElements(Vector v, void *element) 00362 { 00363 checkVector(v, "vectorSetAllElements"); 00364 00365 vectorSetElements(v, element, 0, v->capacity); 00366 } 00367 00368 /* ---------------------------------------------------------------------- 00369 * finds the index of an entry in the vector. 00370 * 00371 * @param v the vector in which the index of the element has to be retrieved. 00372 * @param element the element whose index has to be retrieved in the vector v. 00373 * @param index determines the index of all the elements in the vector. 00374 * @returns index of a given element in the vector or '-1' if the element does not belong to 00375 * that specified vector. 00376 */ 00377 int vectorIndexOf(Vector v, void *element, int index) 00378 { 00379 int i; 00380 00381 checkVector( v, "vectorIndexOf" ); 00382 00383 for ( i = index; i < v->count; i++ ) 00384 if ( v->entries[i] == element ) 00385 return( i ); 00386 00387 return( -1 ); 00388 } 00389 00390 /* ---------------------------------------------------------------------- 00391 * returns the current capacity of vector. 00392 * 00393 * @param v the vector whose capacity has to be retrieved. 00394 * @returns the capacity of the vector v. 00395 */ 00396 int vectorCapacity(Vector v) 00397 { 00398 checkVector( v, "vectorCapacity" ); 00399 00400 return( v->capacity ); 00401 } 00402 00403 /* ---------------------------------------------------------------------- 00404 * returns the current number of entries in the vector. 00405 * 00406 * @param v the vector whose current number of entries has to be determined. 00407 * @returns the total number of entries in the vector v. 00408 */ 00409 int vectorSize(Vector v) 00410 { 00411 checkVector( v, "vectorSize" ); 00412 00413 return( v->count ); 00414 } 00415 00416 /* ---------------------------------------------------------------------- 00417 * checks if the vector is empty or not. 00418 * 00419 * @param v the vector for which the emptiness is checked. 00420 * @returns \a TRUE if the vector is empty and \a FALSE otherwise. 00421 */ 00422 Boolean vectorIsEmpty(Vector v) 00423 { 00424 checkVector( v, "vectorIsEmpty" ); 00425 00426 return( v->count == 0 ? TRUE : FALSE ); 00427 } 00428 00429 /* ---------------------------------------------------------------------- 00430 * checks if a vector contains a given element. 00431 * 00432 * @param v the vector in which a particular number has to be searched. 00433 * @param element the element which has to be checked in the vector v. 00434 * @returns \a TRUE if vector contains the element and \a FALSE otherwise. 00435 */ 00436 Boolean vectorContains(Vector v, void *element) 00437 { 00438 int i; 00439 00440 checkVector( v, "vectorContains" ); 00441 00442 for ( i = 0; i < v->count; i++ ) 00443 if ( v->entries[i] == element ) 00444 return( TRUE ); 00445 00446 return( FALSE ); 00447 } 00448 00449 /* ---------------------------------------------------------------------- 00450 * clones a vector. 00451 * 00452 * @param v the vector that has to be cloned. 00453 * @returns a new vector after cloning is done. 00454 */ 00455 Vector vectorClone(Vector v) 00456 { 00457 Vector new; 00458 00459 checkVector( v, "vectorClone" ); 00460 00461 new = vectorNew( vectorCapacity( v ) ); 00462 vectorCopy(new, v); 00463 return( new ); 00464 } 00465 00466 /* ---------------------------------------------------------------------- 00467 * copies all the entries of one vector \a src to another vector \a dst. 00468 * 00469 * @param src source vector from which the copying is done. 00470 * @param dst destination vector to which copying is done. 00471 * @returns the dst vector with the entries copied. 00472 */ 00473 Vector vectorCopy(Vector dst, Vector src) 00474 { 00475 checkVector( dst, "vectorCopy dst" ); 00476 checkVector( src, "vectorCopy src" ); 00477 00478 if (dst->capacity < src->capacity) 00479 { 00480 dst->entries = (Pointer *) 00481 memRealloc(dst->entries, sizeof(Pointer) * src->capacity); 00482 } 00483 00484 memcpy(dst->entries, src->entries, sizeof(Pointer) * src->capacity); 00485 00486 dst->count = src->count; 00487 dst->capacity = src->capacity; 00488 00489 return dst; 00490 } 00491 00492 /* ---------------------------------------------------------------------- 00493 * internal helper function for sorting. 00494 * 00495 * @param v the vector in which the sorting operation has to be done. 00496 * @param f the function that is used for the sorting of the vector f. 00497 * @param data some additional data that is handed over to the comparison function. 00498 * @param use determines the usage in the program 00499 */ 00500 static void doSorting(Vector v, BooleanFunction *f, void *data, char use) 00501 { 00502 Pointer a, b; 00503 int i, j; 00504 int size=vectorSize(v); 00505 00506 /* straight insertion, quickly coded, slowly running */ 00507 for (i=1; i<size; i++) 00508 { 00509 for (j=i-1; j>=0; j--) 00510 { 00511 a=vectorElement(v, j+1); 00512 b=vectorElement(v, j); 00513 /* compare */ 00514 if (use) { 00515 if (!f(a, b, data)) 00516 break; 00517 } else { 00518 if (!f(a, b)) 00519 break; 00520 } 00521 /* swap a and b */ 00522 vectorSetElement(v, a, j); 00523 vectorSetElement(v, b, j+1); 00524 } 00525 } 00526 } 00527 00528 /* ---------------------------------------------------------------------- 00529 * sorts a vector using a user-specified compare function. 00530 * 00531 * The function f is called as f(a,b) 00532 * @param v the vector that has to be sorted. 00533 * @param f the function that is used for sorting. 00534 * @returns should return \a TRUE if the element \a a should be before element \a b. 00535 */ 00536 Vector vectorSort(Vector v, BooleanFunction *f) 00537 { 00538 checkVector(v, "vectorSort"); 00539 00540 doSorting(v, f, NULL, FALSE); 00541 return v; 00542 } 00543 00544 /* ---------------------------------------------------------------------- 00545 * sorts a vector, using a user-specified compare function and some extra data. 00546 * 00547 * The function f is called as f(a,b,)and some data. 00548 * 00549 * @param v the vector that has to be sorted. 00550 * @param f the function that is used for sorting. 00551 * @param clientData the additional data that is handed over to the comparison function. 00552 * @returns should return \a TRUE if the element \a a should be before element \a b 00553 */ 00554 Vector vectorSortWithData(Vector v, BooleanFunction *f, void *clientData) 00555 { 00556 checkVector(v, "vectorSortWithData"); 00557 00558 doSorting(v, f, clientData, TRUE); 00559 return v; 00560 } 00561 00562 /* ---------------------------------------------------------------------- 00563 * converts a vector into a list. 00564 * 00565 * @param v the vector that has to be converted into a list l. 00566 * @returns the list l corresponding to the vector v. 00567 */ 00568 List vectorToList(Vector v) 00569 { 00570 List l; 00571 int i; 00572 00573 if (v == NULL) 00574 return NULL; 00575 00576 l = NULL; 00577 for (i = vectorSize(v)-1; i >= 0; i--) { 00578 l = listPrependElement(l, vectorElement(v, i)); 00579 } 00580 00581 return l; 00582 } 00583 00584 /* ---------------------------------------------------------------------- */ 00585 /* ---------------------------------------------------------------------- */ 00586 /** @} */

BLAH 0.95 (20 Oct 2004)