C语言编写无类型的快速排序和归并排序
来源:互联网 发布:一个算法应具备的特性 编辑:程序博客网 时间:2024/06/11 17:06
刚看了李先静老师的《系统程序员成长计划》,里面有一部分是讲解排序的,就按着他的讲解顺序自己尝试着写了适用于任何类型的快速排序和归并排序的代码。写一个无类型的排序要注意两个方面:
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);}
0 0
- C语言编写无类型的快速排序和归并排序
- c语言归并排序和快速排序
- 归并排序和快速排序的比较
- 归并排序和快速排序的浅析
- 单链表的快速排序和归并排序
- 归并排序和快速排序的实现
- 归并排序和快速排序的比较
- 快速排序和归并排序的实现
- 快速排序和归并排序
- 归并排序和快速排序
- 归并排序和快速排序
- 归并排序和快速排序
- 归并排序和快速排序
- 归并排序和快速排序
- 归并排序和快速排序
- 快速排序和归并排序
- 归并排序和快速排序
- 快速排序和归并排序
- 堆栈的数组实现
- LeetCode | N-Queens II
- Android 日志工具类
- ROC曲线,AUC,
- 串口与并口介绍
- C语言编写无类型的快速排序和归并排序
- 让C#自动缩进排列代码的快捷键
- 二级指针及链表操作中遇到的一点小问题
- Raw Socket和Socket编程
- Android TextView使用HTML处理字体样式、显示图片等
- Highcharts使用jsonp格式数据demo
- ListView的item选中后保持选中时的高亮颜色。
- 椭圆曲线加密算法的证书
- java -Xms -Xmx -XX:PermSize -XX:MaxPermSize