全部博文(136)
分类: C/C++
2011-03-18 08:51:53
Growing a sorted array by inserting n elements one at a time is an O(n2) operation that should be avoided if n is large.
Often, though, we need to keep track of a variable but small number of things, and arrays can still be the method of choice. To minimize the cost of allocation, the array should be resized in chunks, and for cleanliness the array shoud gathered together with the information necessary to maintain it. In C++ or Java, this would be done with classes from standard libraries; in C, we can achieve a similar result with a struct.
The following code defines a growable array of Nameval items; new items are added at the end of the array, which is grown as necessary to make room. Any element can be accessed through its subscript in constant time. This is analogous to the vector classes in the Java and C++ libraries.
The function addname returns the index of the item just added, or -1 if some error occurred.
The call to realloc grows the array to the new size, preserving the existing elements, and returns a pointer to it or NULL if there isn't enough memory. Doubling the size in each realloc keeps the expected cost of copying each element constant: if the array grew by just one element on each call, the performance could be O(n2).
The return value of realloc does not need to be cast to its final type because C promotes the void* automatically. But C++ does not; there the cast is required.
Deleting a name can be tricky, because we must decide what to do with the resulting gap in the array. If the order of elements does not matter, it is easiest to swap the last element into the hole. If order is to be preserved, however, we must move the elements beyond the hold down by one position:
The call to memmove squeezes the array by moving the elements down one position; memmove is a standard library routine for copying arbitrary-size blocks of memory.
Rules: