您的位置:首页 > 编程语言 > C语言/C++

C语言编写无类型的快速排序和归并排序

2013-12-12 11:25 405 查看
刚看了李先静老师的《系统程序员成长计划》,里面有一部分是讲解排序的,就按着他的讲解顺序自己尝试着写了适用于任何类型的快速排序和归并排序的代码。写一个无类型的排序要注意两个方面:

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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: