C语言编写无类型的快速排序和归并排序
2013-12-12 11:25
405 查看
刚看了李先静老师的《系统程序员成长计划》,里面有一部分是讲解排序的,就按着他的讲解顺序自己尝试着写了适用于任何类型的快速排序和归并排序的代码。写一个无类型的排序要注意两个方面:
1) 用指针,并且是void*作为传入参数,这样可以接纳任何的类型。
2)利用回调函数,通过调用不同的比较函数(DataCompareFunc)实现对多种数据类型的可行性
3)排序不可避免的要用到数据的交换,即swap函数,由于我们传入的数据类型不同,因此相应的swap函数也是不同。这里也可以用回调函数来实现,不过有一种更简单的方法实现。就是将void*转换为char*,如果已知数据类型的字节大小,那么可以通过逐个字节的交换,实现数据的交换。库函数中的qsort函数就是用的这种方法。具体的代码可以参考下面的代码。
1) 用指针,并且是void*作为传入参数,这样可以接纳任何的类型。
2)利用回调函数,通过调用不同的比较函数(DataCompareFunc)实现对多种数据类型的可行性
3)排序不可避免的要用到数据的交换,即swap函数,由于我们传入的数据类型不同,因此相应的swap函数也是不同。这里也可以用回调函数来实现,不过有一种更简单的方法实现。就是将void*转换为char*,如果已知数据类型的字节大小,那么可以通过逐个字节的交换,实现数据的交换。库函数中的qsort函数就是用的这种方法。具体的代码可以参考下面的代码。
#ifndef SORT_H_ #define SORT_H_ #include <sys/types.h> typedef int (*CompareFunc)(void *ctx, void *data); typedef int (*SortFunc)(void **array, size_t size, CompareFunc cmp); int bubble_sort(void *array, size_t size, size_t width, CompareFunc cmp); int quick_sort_recursion(void *array, size_t size, size_t width, CompareFunc cmp); int merge_sort_recursion(void *array, size_t size, size_t width, CompareFunc cmp); int cmp_int(void *ctx, void *data); int cmp_char(void *ctx, void *data); int cmp_str(void *ctx, void *data); #endif
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <string.h> #include "mysort.h" #define return_if_fail(p) if(!(p))\ {printf("%s : %d Warning: "#p" failed!\n",__func__,__LINE__);return 0;} static void swap(char *thiz, char *data, size_t width) //转换函数 { char temp; if(thiz != data) { while(width --) { temp = *thiz; *(thiz++) = *data; *(data++) = temp; } } } static void assign(char *thiz, char *data, size_t width) //赋值函数,用于归并排序 { if(thiz != data) { while(width --) { *data = *thiz; data ++; thiz ++; } } } static void bubble_sort_re(char *start, char *end, size_t width, CompareFunc cmp) //冒泡排序 { char *p, *q; size_t flag = 1; for(p = end; p > start; p -= width) { flag = 1; for(q = start; q < p; q += width) { if(cmp(q, q + width) > 0) { flag = 0; swap(q, q+width, width); } } if(flag == 1) return; } } static void quick_sort_recursion_re(char *start, char *end, size_t width, CompareFunc cmp) // 递归快速排序 { char *p = start + width; char *q = end; char *pivot = start; while(p < q) { while(cmp(q, pivot) > 0 && q > p) { q -= width; } while(cmp(p, pivot) < 0 && q > p) { p += width; } if(q > p) { swap(p , q , width); } } if(cmp(pivot , q) > 0) { swap(pivot, q, width); } if( start < q - width) { quick_sort_recursion_re(start, q - width, width, cmp); } if(q < end) { quick_sort_recursion_re(q , end , width, cmp); } return; } int bubble_sort(void *array, size_t size, size_t width, CompareFunc cmp) //冒泡排序 { return_if_fail(array != NULL && size > 0 && cmp != NULL); if(size < 2) return 0; char *start = (char *)array; char *end = (char*)array + (size-1)*width; bubble_sort_re(start, end, width, cmp); return 0; } int quick_sort_recursion(void *array, size_t size, size_t width, CompareFunc cmp) //快速排序 { return_if_fail(array != NULL && size > 0 && cmp != NULL); if(size < 2) return 0; char *start = (char *)array; char *end = (char*)array + (size -1)*width; quick_sort_recursion_re(start, end, width, cmp); return 0; } static int merge(char *start, char *middle_pointer, char *end, size_t size, size_t width, CompareFunc cmp) //归并排序 { char *p = start; char *q = middle_pointer + width; char *data = (char *)malloc(size*width); char *temp = data; while(p <= middle_pointer && q <= end) { while(cmp(p, q) <= 0 && p <= middle_pointer) { assign(p, temp, width); temp += width; p += width; } while(cmp(p,q) > 0 && q <= end) { assign(q, temp, width); temp += width; q += width; } } while(p <= middle_pointer) { assign(p, temp, width); temp += width; p += width; } while(q <= end) { assign(q, temp, width); temp += width; q += width; } p = start; q = end; temp = data; while(p <= q) { assign(temp, p, width); temp += width; p += width; } free(data); data = NULL; } static int merge_sort_recursion_re(char *start, char *end, size_t size, size_t width, CompareFunc cmp)//归并排序 { if(start == end) return 0; if(end > start) { size_t front_size = size>>1; size_t back_size = size - front_size; char * middle_pointer = start + (front_size-1)*width; //printf("%d, 0%s\n", __LINE__, __func__); merge_sort_recursion_re(start, middle_pointer, front_size, width, cmp); //printf("%d, 1%s\n", __LINE__, __func__); merge_sort_recursion_re(middle_pointer + width, end, back_size, width, cmp); //printf("%d, 2%s\n", __LINE__, __func__); merge(start , middle_pointer, end, size, width, cmp); //printf("%d, 3%s\n", __LINE__, __func__); } return 0; } int merge_sort_recursion(void *array, size_t size, size_t width, CompareFunc cmp) //归并排序 { return_if_fail(array != NULL && size > 0 && cmp != NULL); if(size < 2) return 0; char *start = (char *)array; char *end = (char *)array + (size - 1)*width; merge_sort_recursion_re(start, end, size, width, cmp); return 0; } int cmp_int(void *ctx, void *data) { return (*(int*)ctx - *(int*)data); } int cmp_char(void *ctx, void *data) { return (*(char*)ctx - *(char*)data); } int cmp_str(void *ctx, void *data) { return strcmp((char*)ctx, (char*)data); }
相关文章推荐
- c语言归并排序和快速排序
- 算法导论之插入排序,选择排序,归并排序,冒泡排序,希尔排序,堆排序,快速排序的c语言实现
- 算法导论之插入排序,选择排序,归并排序,冒泡排序,希尔排序,堆排序,快速排序的c语言实现
- 快速排序和归并排序(C语言)
- C语言实现 编写一个函数,传入a,b两个int类型的变量,返回两个值的最大公约数。
- 快速排序和归并排序(C语言)
- 【C语言】编写一个函数,传入a,b两个int类型的变量,返回两个值的最大公约数。(辗转相除法和常规求法)
- 使用C语言编写Python扩展——创建自定义类型(1)
- 使用C语言编写Python扩展——创建自定义类型(2)
- C语言 编写一个函数,传入a,b两个int类型的变量,返回两个值的最大公约数。
- 参考C语言的qsort函数实现一个一个能对任意数据类型(包括结构体)的数组进行排序的函数(里面用的不是快速排序)
- 用c语言实现 编写一个函数reverse_string(char * string)
- c语言变量的作用域,链接属性,储存类型&&static关键字
- C语言编写cgi程序(上)
- C语言中time_t数据类型详细介绍
- C语言数据类型
- 对C语言中补码和char数据类型的理解
- c语言:编写折半查找函数
- 《C语言编写 学生成绩管理系统》
- C语言笔记1--类型、运算符与表达式