利用C实现泛型(generics)效果---原地洗牌,快速排序
2013-11-27 23:46
369 查看
用一个函数实现一个算法,能够应用在不同的数据类型(int,double,字符数组)上,这在C++,python等高级语言中是很常见的。
灵活地利用C中的void指针,内存操作,函数指针也可以实现类似的效果。
用void指针指向特定元素的地址,如果传入元素占内存大小(如sizeof(int),sizeof(double)),可以用memcpy实现赋值操作。
如果实现了用于元素间比较或四则运算的函数并将其指针传入(如int (*cmp)(void*,void*)),则能在算法中不考虑数据类型实现更多功能。
比如下面一段函数,实现了原地洗牌,快速排序两种算法:
在《C++编程思想》那本书中的,“一个袖珍的C库”那一小节,利用类似的思想实现了一个stash,不过那里使用的是字符拷贝,而且只考虑了元素存取,没有更复杂的操作。
灵活地利用C中的void指针,内存操作,函数指针也可以实现类似的效果。
用void指针指向特定元素的地址,如果传入元素占内存大小(如sizeof(int),sizeof(double)),可以用memcpy实现赋值操作。
如果实现了用于元素间比较或四则运算的函数并将其指针传入(如int (*cmp)(void*,void*)),则能在算法中不考虑数据类型实现更多功能。
比如下面一段函数,实现了原地洗牌,快速排序两种算法:
#include <stdlib.h> #include <string.h> #include <time.h> //omit ptr check when malloc and realloc void swap(void* ap, void* bp, int elem_size) { void* buffer = malloc(elem_size); memcpy(buffer, ap, elem_size); memcpy(ap, bp, elem_size); memcpy(bp, buffer, elem_size); free(buffer); } void randomize_in_place(void* arr, int n, int elem_size) { int rand_place; srand((unsigned int)time(NULL)); for(int i=0; i<n; i++) { rand_place = rand() % (n-i) + i; swap((char*)arr+i*elem_size, (char*)arr+rand_place*elem_size, elem_size); } } int int_cmp(const void* ap, const void* bp) { return *(int*)ap - *(int*)bp; } int double_cmp(const void* ap, const void* bp) { if(*(double*)ap - *(double*)bp < 0) return -1; else if(*(double*)ap - *(double*)bp == 0) return 0; else return 1; } int charptr_cmp(const void* ap, const void* bp) { return strcmp(*(char**)ap, *(char**)bp); } int randomized_partition(void* arr, int p, int r, int elem_size, int (*compar)(const void*, const void*)) { srand((unsigned int)time(NULL)); int rand_elem_index = rand() % (r-p+1) + p; char* rand_elem_ptr = (char*)arr + rand_elem_index * elem_size; char* pivot_ptr = (char*)arr + r * elem_size; swap(rand_elem_ptr, pivot_ptr, elem_size); // start to partition, arr[r]=pivot // p<=k<=i arr[k]<=pivot, i+1<=k<=j-1 arr[k]>pivot int i = p - 1; char* ith_elem_ptr = NULL; char* jth_elem_ptr = NULL; for(int j=p; j<r; j++) { jth_elem_ptr = (char*)arr + j * elem_size; if(compar(jth_elem_ptr, pivot_ptr) <= 0) { i = i + 1; ith_elem_ptr = (char*)arr + i * elem_size; swap(ith_elem_ptr, jth_elem_ptr, elem_size); } } swap((char*)arr+(i+1)*elem_size, pivot_ptr, elem_size); return i+1; } void recursive_qsort(void* arr, int p, int r, int elem_size, int (*compar)(const void*, const void*)) { if(p < r) { int q = randomized_partition(arr, p, r, elem_size, compar); recursive_qsort(arr, p, q-1, elem_size, compar); recursive_qsort(arr, q+1, r, elem_size, compar); } } void generic_qsort(void* arr, int n, int elem_size, int (*compar)(const void*, const void*)) { recursive_qsort(arr, 0, n-1, elem_size, compar); }
int main(int argc, char** argv) { int int_array[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; randomize_in_place(int_array, 10, sizeof(int)); //test generic_qsort(int_array, 10, sizeof(int), int_cmp); //test double double_array[6] = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0}; randomize_in_place(double_array, 6, sizeof(double)); //test generic_qsort(double_array, 6, sizeof(double), double_cmp); //test char* charptr_array[6] = {"generics", "hccc", "spring", "summer", "autumn", "winter"}; randomize_in_place(charptr_array, 6, sizeof(char*)); //test generic_qsort(charptr_array, 6, sizeof(char*), charptr_cmp); //test }
在《C++编程思想》那本书中的,“一个袖珍的C库”那一小节,利用类似的思想实现了一个stash,不过那里使用的是字符拷贝,而且只考虑了元素存取,没有更复杂的操作。
相关文章推荐
- 利用C实现泛型效果(generics)---vector
- iOS 8.0 毛玻璃效果利用UIVisualEffectView快速实现
- 利用Python实现快速算法排序
- C#中的delegate以及利用List<T>中delegate快速实现排序、查找
- asp.net实现利用反射,泛型,静态方法快速获取表单值到Model的方法
- asp.net实现利用反射,泛型,静态方法快速获取表单值到Model的方法
- 利用jquery快速实现查询效果
- 利用随机化快速排序求带权中位数C++实现
- 利用c++模板实现快速排序
- 通用排序函数的功能实现(利用接口和委托实现泛型[通用]排序)
- 利用GestureDetector快速实现页面切换滑动效果
- .NET泛型List实现快速排序、查找功能
- 快速排序与堆排序的Java实现(泛型)
- Android中ListView字母排序,实现字母挤压效果以及右侧快速选中字母,搜索关键字功能
- 利用qsort库函数实现快速排序
- PHP利用ICU扩展intl快速实现汉字转拼音以及按拼音首字母分组排序
- 利用php_imagick实现复古效果的方法
- ACM -- 算法小结(一)利用数组存放实现排序
- 快速排序C++代码实现
- .net 快速排序 (实现)