最近教小家伙C语言,很快就要教到排序了,所以写了个通用的冒泡排序程序。这个函数可以对任意类型数组中的数据排序。
需要用到的数据类型和函数声明如下(sort.h):
#ifndef __SORT_H
#define __SORT_H
#include <stdlib.h>
#ifndef __cplusplus
typedef enum
{
false,
true,
} bool;
#endif // __cplusplus
typedef enum
{
SD_ASCEND,
SD_DESCEND
} SortDirection;
typedef unsigned char byte;
/**
* Comparator - function pointer to user defined comparator function.
* @param one - data one, the first data to be compared.
* @param two - data two, the second data to be compared.
* @return - if one gt two, return positive integer; else if one lt two, return negative integer; else, return 0.
*/
typedef int (*Comparator)(void *one, void *two, size_t elemSize);
void swap(void *one, void *two, size_t size);
/**
* sortBubbly - generic bubble sort function
* @param unsorted - void pointer, point to an unsorted array.
* @param sorted - void pointer, point to the sorted array.
* @param cmpr - a comparator function. see the definition of Comparator.
* @param dir - sort by ascend or descend.
* @param elemCount - how many elements in the sorting array.
* @param elemSize - the memory size of the single element in the array.
*/
void sortBubbly(void *unsorted, void *sorted, Comparator cmpr, SortDirection dir, int elemCount, size_t elemSize);
#endif /* __SORT_H_ */
函数实现代码如下(sort.c):
#include <string.h>
#include <stdlib.h>
#include "sort.h"
void swap(void *one, void *two, size_t size)
{
void *relay = malloc(size);
memcpy(relay, one, size);
memcpy(one, two, size);
memcpy(two, relay, size);
free(relay);
}
void sortBubbly(void *unsorted, void *sorted, Comparator cmpr, SortDirection dir, int elemCount, size_t elemSize)
{
void *onePtr, *twoPtr;
bool willSwap;
memcpy(sorted, unsorted, elemSize * elemCount);
for(int index = 0; index < (elemCount - 1); index ++)
{
for(int swapIndex = 0; swapIndex < (elemCount - 1 - index); swapIndex ++)
{
onePtr = sorted + swapIndex * elemSize;
twoPtr = sorted + (swapIndex + 1) * elemSize;
if (dir == SD_DESCEND)
{
willSwap = (cmpr(onePtr, twoPtr, elemSize) < 0) ? true : false;
}
else
{
willSwap = (cmpr(onePtr, twoPtr, elemSize) > 0) ? true : false;
}
if (willSwap)
{
swap(onePtr, twoPtr, elemSize);
}
}
}
}
测试验证代码如下:
#include <stdio.h>
#include <string.h>
#include "sort.h"
int integerComparator(void *one, void *two, size_t elemSize)
{
return (*(int *)one) - (*(int *)two);
}
int floatComparator(void *one, void *two, size_t elemSize)
{
float sub = (*(float *)one) - (*(float *)two);
return ((sub > 0) ? 1 : ((sub < 0) ? -1 : 0));
}
int charComparator(void *one, void *two, size_t elemSize)
{
return (*(char *)one) - (*(char *)two);
}
int stringComparator(void *one, void *two, size_t elemSize)
{
return strcmp(*(char **)one, *(char **)two);
}
int main()
{
// demostration for sort integer array.
int unsortedIntegers[] = {1, 4, 2, 8, 5, 7};
int sortedIntegers[sizeof unsortedIntegers / sizeof(int)];
int intArraySize = sizeof unsortedIntegers / sizeof(int);
printf("%-16s: ", "unsorted");
for(int index = 0; index < intArraySize; index ++)
{
printf("%8d", unsortedIntegers[index]);
}
printf("\n");
sortBubbly(unsortedIntegers, sortedIntegers, integerComparator, SD_DESCEND, intArraySize, sizeof(int));
printf("%-16s: ", "sorted descendly");
for(int index = 0; index < intArraySize; index ++)
{
printf("%8d", sortedIntegers[index]);
}
printf("\n");
sortBubbly(unsortedIntegers, sortedIntegers, integerComparator, SD_ASCEND, intArraySize, sizeof(int));
printf("%-16s: ", "sorted ascendly");
for(int index = 0; index < intArraySize; index ++)
{
printf("%8d", sortedIntegers[index]);
}
printf("\n");
// demostration for sort float array.
float unsortedFloats[] = {3.142, 1.414, 1.732, 1.428, 5.714, 0.500};
float sortedFloats[sizeof unsortedFloats / sizeof(float)];
int floatArraySize = sizeof unsortedFloats / sizeof(float);
printf("%-16s: ", "unsorted");
for(int index = 0; index < floatArraySize; index ++)
{
printf("%8.3f", unsortedFloats[index]);
}
printf("\n");
sortBubbly(unsortedFloats, sortedFloats, floatComparator, SD_DESCEND, floatArraySize, sizeof(float));
printf("%-16s: ", "sorted descendly");
for(int index = 0; index < floatArraySize; index ++)
{
printf("%8.3f", sortedFloats[index]);
}
printf("\n");
sortBubbly(unsortedFloats, sortedFloats, floatComparator, SD_ASCEND, floatArraySize, sizeof(float));
printf("%-16s: ", "sorted ascendly");
for(int index = 0; index < floatArraySize; index ++)
{
printf("%8.3f", sortedFloats[index]);
}
printf("\n");
// demostration for sort char array.
char unsortedChars[] = {'k', 'i', 'n', 'g', 'f', 'o', 'x'};
char sortedChars[sizeof unsortedChars / sizeof(char)];
int charArraySize = sizeof unsortedChars / sizeof(char);
printf("%-16s: ", "unsorted");
for(int index = 0; index < charArraySize; index ++)
{
printf("%7c", unsortedChars[index]);
}
printf("\n");
sortBubbly(unsortedChars, sortedChars, charComparator, SD_DESCEND, charArraySize, sizeof(char));
printf("%-16s: ", "sorted descendly");
for(int index = 0; index < charArraySize; index ++)
{
printf("%7c", sortedChars[index]);
}
printf("\n");
sortBubbly(unsortedChars, sortedChars, charComparator, SD_ASCEND, charArraySize, sizeof(char));
printf("%-16s: ", "sorted Ascendly");
for(int index = 0; index < charArraySize; index ++)
{
printf("%7c", sortedChars[index]);
}
printf("\n");
// demostration for sort string array.
char *unsortedStrings[] = {"kingfox", "apple", "ivy", "world", "yuyu", "guoguo"};
char *sortedStrings[sizeof unsortedStrings / sizeof(char *)];
int stringArraySize = sizeof unsortedStrings / sizeof(char *);
printf("%-16s: ", "unsorted");
for(int index = 0; index < stringArraySize; index ++)
{
printf("%8s", unsortedStrings[index]);
}
printf("\n");
sortBubbly(unsortedStrings, sortedStrings, stringComparator, SD_DESCEND, stringArraySize, sizeof (char *));
printf("%-16s: ", "unsorted");
for(int index = 0; index < stringArraySize; index ++)
{
printf("%8s", sortedStrings[index]);
}
printf("\n");
sortBubbly(unsortedStrings, sortedStrings, stringComparator, SD_ASCEND, stringArraySize, sizeof (char *));
printf("%-16s: ", "unsorted");
for(int index = 0; index < stringArraySize; index ++)
{
printf("%8s", sortedStrings[index]);
}
printf("\n");
return 0;
}
运行结果如下:
unsorted : 3.142 1.414 1.732 1.428 5.714 0.500
sorted descendly: 5.714 3.142 1.732 1.428 1.414 0.500
sorted ascendly : 0.500 1.414 1.428 1.732 3.142 5.714
unsorted : k i n g f o x
sorted descendly: x o n k i g f
sorted Ascendly : f g i k n o x
unsorted : kingfox apple ivy world yuyu guoguo
unsorted : yuyu world kingfox ivy guoguo apple
unsorted : apple guoguo ivy kingfox world yuyu
这个排序函数之所以可以通用化,有以下原因:
1、sort函数的参数之一是一个比较器函数指针,指向用户自定义的比较器函数。这个比较器函数会比较两个数据的大小,当第一个数据大于第二个数据时,返回正整数;若第一个数据小于第二个数据,返回负整数;若两个数相等,则返回0。
2、sort函数使用无类型指针来指向被排序的数据,并且在形参中给出了被排序数据的空间大小,这样就可以不用在意被排序数据究竟是什么类型。
这个练习涵盖了C语言的数组、指针、字符串、基础数据类型、条件分支、定长循环、标准格式化输出,是个综合性练习。