排序函数具体操作
下面是函数具体操作:(文件名称:sort.c)
//FILE: sort.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
//函数声明
void bubbleSort(int *a, int n); //冒泡排序
void selectSort(int *a, int n); //选择排序
void insertSort(int *a, int n); //插入排序
void MergeArray(int *a, int begin, int mid, int end, int *temp); //归并排序(合并数组)
void MergeSort(int *a, int begin, int end, int *temp); //归并排序
void QuickSort_Recursion(int *a, int begin, int end); //快速排序(递归)
void PartitionQuickSort(int *a, int begin, int end); //快速排序(枢轴存放)
int NumberOfThree(int *a, int begin, int end);//枢轴为三数取中
void Swap(int *x, int *y); //数据交换
void CountSort(int *a, int size , int max); //计数排序
void RadixCountSort(int *a, int size); //基数排序
int arrayMax(int *arr, int size); //数组中的最大值
int getDigitNum(int x); //得到数据的位数
//函数具体操作
//冒泡排序
void bubbleSort(int *a, int n)
{
int i, j, temp;
for (i = 0; i < n - 1; i++)
{
for (j = 0; j < n - i; j++)
{
if (a[j] > a[j+1])
{
temp = a[j];
a[j] = a[j + 1];
a[j+1] = temp;
}
}
}
}
//选择排序
void selectSort(int *a, int n)
{
int i, j, min, temp;
for (i = 0; i < n - 1; i++)
{
min = i;
for (j = i + 1; j < n; j++)
{
if (a[min] > a[j])
{
min = j;
}
}
temp = a[min];
a[min] = a[i];
a[i] = temp;
}
}
//插入排序
void insertSort(int *a,int n)
{
int i, j, temp;
for(i = 1; i < n; i++)
{
temp = a[i];
for(j = i - 1; j >= 0 && a[j] > temp; j--)
{
a[j + 1] = a[j];
}
a[j + 1] = temp;
}
}
//归并排序(合并数组)
void MergeArray(int *a,int begin,int mid,int end,int *temp)
{
int k = begin;
int left_begin = begin, left_end = mid;
int right_begin = mid + 1, right_end = end;
while(left_begin <= left_end && right_begin <= right_end)
{
if(a[left_begin] < a[right_begin])
{
temp[k++] = a[left_begin++];
}
else
{
temp[k++] = a[right_begin++];
}
}
while(left_begin <= left_end)
{
temp[k++] = a[left_begin++];
}
while(right_begin <= right_end)
{
temp[k++] = a[right_begin++];
}
for(k = begin; k <= end; k++)
{
a[k] = temp[k];
}
}
//归并排序
void MergeSort(int *a,int begin,int end,int *temp)
{
if(begin >= end)
{
return;
}
else
{
int mid = (begin + end) / 2;
MergeSort(a, begin, mid, temp);
MergeSort(a, mid + 1, end, temp);
MergeArray(a, begin, mid, end, temp);
}
}
//快速排序(递归)
void QuickSort_Recursion(int *a, int begin, int end)
{
int i = begin, j = end;
int temp;
int pivot = a[begin]; //选取第一个元素为基准点
while(i <= j)
{
//找到左边大于基准点的元素
while(a[i] < pivot)
{
i++;
}
//找到右边小于基准点的元素
while(a[j] > pivot)
{
j--;
}
//当左边下标小于右边时,互换元素
if(i <= j)
{
temp = a[i];
a[i] = a[j];
a[j] = temp;
//互换后i, j继续靠近
i++;
j--;
}
}
//左边进行递归
if(i < end)
{
QuickSort_Recursion(a, i, end);
}
//右边进行递归
if(begin < j)
{
QuickSort_Recursion(a, begin, j);
}
}
//快速排序(枢轴存放)
void PartitionQuickSort(int *a, int begin, int end)
{
int i = begin, j = end;
int temp;
int pivot = NumberOfThree(a, begin, end); //三数取中作为基准元素
while(i <= j)
{
//找到左边大于基准点的元素
while(a[i] < pivot)
{
i++;
}
//找到右边小于基准点的元素
while(a[j] > pivot)
{
j--;
}
//当左边下标小于右边时,互换元素
if(i <= j)
{
temp = a[i];
a[i] = a[j];
a[j] = temp;
//互换后i, j继续靠近
i++;
j--;
}
}
//左边进行递归
if(i < end)
{
QuickSort_Recursion(a, i, end);
}
//右边进行递归
if(begin < j)
{
QuickSort_Recursion(a, begin, j);
}
}
//枢轴为三数取中
int NumberOfThree(int *a,int begin,int end)
{
int mid = (begin + end) / 2 + begin;
if (a[mid] > a[end])
{
Swap(&a[mid], &a[end]);
}
if (a[begin] > a[end])
{
Swap(&a[begin], &a[end]);
}
if (a[mid] > a[begin])
{
Swap(&a[mid], &a[begin]);
}
//此时a[mid] <= a[begin] <= a[end]
return a[begin];
}
//数据交换
void Swap(int *x, int *y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
//计数排序
void CountSort(int *a, int size , int max)
{
int i;
int *count, *sorted;
//给计数器和已排序数组分配空间
count = (int *)malloc(sizeof(int) * (max + 1));
sorted = (int *)malloc(sizeof(int) * size);
if(count == NULL || sorted == NULL)
{
printf("内存分配失败\n");
system("pause");
exit(0);
}
//计数数组初始化为0
for(i = 0; i < max + 1; i++)
{
count[i] = 0;
}
//收集原数组中每种值的个数
for(i = 0; i < size; i++)
{
count[a[i]]++;
}
//统计所有小于等于该值的元素个数
for(i = 1; i < max + 1; i++)
{
count[i] += count[i - 1];
}
//将所有元素按收集表分配到对应位置,反向填充目标数组
for(i = size - 1; i >= 0; i--)
{
//先将计数数组中对应值-1
count[a[i]]--;
sorted[count[a[i]]] = a[i];
}
//已排序数组替代原数组
for(i = 0; i < size; i++)
{
a[i] = sorted[i];
}
//释放内存
free(count);
free(sorted);
}
/* 下面是基数排序,第二个在第一个的基础上进行了优化,
改变了循环位数的方法,在20万个范围为0-999的随机数的排序测试下,
第一个基数排序耗时十几分钟,第二个基数排序耗时十几毫秒(质的飞跃) */
/* //基数排序
void RadixCountSort(int *a,int size)
{
int base = 10; //基数设为10
int i, n, index, max, maxnum, pval;
int *count, *sorted;
//计算数组中的最大值
max = arrayMax(a, size);
//计算数据最高位
maxnum = getDigitNum(max);
//给计数器和已排序数组分配空间
count = (int *)malloc(sizeof(int) * base);
sorted = (int *)malloc(sizeof(int) * size);
if(count == NULL || sorted == NULL)
{
printf("内存分配失败\n");
system("pause");
exit(0);
}
for(n = 0; n < maxnum; n++)
{
//计数数组初始化为0
for(i = 0; i < base; i++)
{
count[i] = 0;
}
//计算位置值
pval = pow(base, n);
//统计当前位上每个数值出现的次数
for(i = 0; i < size; i++)
{
index = a[i] / pval % base;
count[index]++;
}
//统计所有小于等于该值的元素个数
for(i = 1; i < base; i++)
{
count[i] += count[i - 1];
}
//将所有元素按收集表分配到对应位置
for(i = size - 1; i >= 0; i--)
{
index = a[i] / pval % base;
count[index]--;
sorted[count[index]] = a[i];
}
//已排序数组替代原数组
memcpy(a, sorted, sizeof(int) * size);
}
//释放内存
free(count);
free(sorted);
} */
//优化后的基数排序
void RadixCountSort(int *a,int size)
{
int i, index, max;
int rad = 1; //从个位开始
int *count, *sorted;
//计算数组中的最大值
max = arrayMax(a, size);
//给计数器和已排序数组分配空间
count = (int *)malloc(sizeof(int) * 10);
sorted = (int *)malloc(sizeof(int) * size);
if(count == NULL || sorted == NULL)
{
printf("内存分配失败\n");
system("pause");
exit(0);
}
while(max / rad > 0)
{
//计数数组初始化为0
for(i = 0; i < 10; i++)
{
count[i] = 0;
}
//统计当前位上每个数值出现的次数
for(i = 0; i < size; i++)
{
index = a[i] / rad % 10;
count[index]++;
}
//统计所有小于等于该值的元素个数
for(i = 1; i < 10; i++)
{
count[i] += count[i - 1];
}
//将所有元素按收集表分配到对应位置
for(i = size - 1; i >= 0; i--)
{
index = a[i] / rad % 10;
count[index]--;
sorted[count[index]] = a[i];
}
//已排序数组替代原数组
for(i = 0; i < size; i++)
{
a[i] = sorted[i];
}
rad *= 10; //位数乘10
}
//释放内存
free(count);
free(sorted);
}
//求数组最大值
int arrayMax(int *arr, int size)
{
int i, max = arr[0];
for(i = 0; i < size; i++)
{
if(arr[i] > max)
{
max = arr[i];
}
}
return max;
}
//得到数据的位数
int getDigitNum(int x)
{
if(x == 0)
{
return 1;
}
else
{
int res;//数据最高位
while(x != 0)
{
x /= 10;
res++;
}
return res;
}
}
main函数
下面是调用排序函数(文件名称:sort_main.c)
//FILE: sort_main.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<windows.h>
#include "sort.c"
//main函数
int main(void)
{
int len, max, i; //数组长度,数组最大值,计数器
int *data; //存入原始数据
int *arr1, *arr2, *arr3, *arr4, *arr5, *arr6, *arr7, *arr8; //进行各种排序的数组
int *temp = NULL;
printf("没有写防脸滚键盘的功能,测试的时候请按要求输入!\n");
//录入数据
printf("请输入数组长度:");
scanf("%d", &len);
data = (int *)malloc(sizeof(int) * len);
if(data == NULL)
{
printf("内存分配失败\n");
system("pause");
return -1;
}
printf("请录入整型数据(以回车间隔):\n");
for(i = 0; i < len; i++)
{
scanf("%d", data + i);
}
//打印原始数据
printf("数据录入完毕\n录入的数据为:\n");
for(i = 0; i < len; i++)
{
printf("%d\t", *(data + i));
}
printf("\n");
//进行冒泡排序
arr1 = (int *)malloc(sizeof(int) * len);
if(arr1 == NULL)
{
printf("内存分配失败\n");
system("pause");
return -1;
}
memcpy(arr1, data, sizeof(int) * len);
bubbleSort(arr1, len);
printf("冒泡排序后结果:\n");
for(i = 0; i < len; i++)
{
printf("%d\t", *(arr1 + i));
}
printf("\n");
//进行选择排序
arr2 = (int *)malloc(sizeof(int) * len);
if(arr2 == NULL)
{
printf("内存分配失败\n");
system("pause");
return -1;
}
memcpy(arr2, data, sizeof(int) * len);
selectSort(arr2, len);
printf("选择排序后结果:\n");
for(i = 0; i < len; i++)
{
printf("%d\t", *(arr2 + i));
}
printf("\n");
//进行插入排序
arr3 = (int *)malloc(sizeof(int) * len);
if(arr3 == NULL)
{
printf("内存分配失败\n");
system("pause");
return -1;
}
memcpy(arr3, data, sizeof(int) * len);
insertSort(arr3, len);
printf("插入排序后结果:\n");
for(i = 0; i < len; i++)
{
printf("%d\t", *(arr3 + i));
}
printf("\n");
//进行归并排序
arr4 = (int *)malloc(sizeof(int) * len);
if(arr4 == NULL)
{
printf("内存分配失败\n");
system("pause");
return -1;
}
temp = (int *)malloc(sizeof(int) * len);
if(temp == NULL)
{
printf("内存分配失败\n");
system("pause");
return -1;
}
memcpy(arr4, data, sizeof(int) * len);
MergeSort(arr4, 0, len - 1, temp);
printf("归并排序后结果:\n");
for(i = 0; i < len; i++)
{
printf("%d\t", *(arr4 + i));
}
free(temp);
printf("\n");
//进行快速排序(递归)
arr5 = (int *)malloc(sizeof(int) * len);
if(arr5 == NULL)
{
printf("内存分配失败\n");
system("pause");
return -1;
}
memcpy(arr5, data, sizeof(int) * len);
QuickSort_Recursion(arr5, 0, len - 1);
printf("快速排序(递归)后结果:\n");
for(i = 0; i < len; i++)
{
printf("%d\t", *(arr5 + i));
}
printf("\n");
//进行快速排序(枢轴存放)
arr6 = (int *)malloc(sizeof(int) * len);
if(arr6 == NULL)
{
printf("内存分配失败\n");
system("pause");
return -1;
}
memcpy(arr6, data, sizeof(int) * len);
PartitionQuickSort(arr6, 0, len - 1);
printf("快速排序(枢轴存放)后结果:\n");
for(i = 0; i < len; i++)
{
printf("%d\t", *(arr6 + i));
}
printf("\n");
//进行计数排序
arr7 = (int *)malloc(sizeof(int) * len);
if(arr7 == NULL)
{
printf("内存分配失败\n");
system("pause");
return -1;
}
memcpy(arr7, data, sizeof(int) * len);
//找到数组中的最大值
max = arrayMax(arr7, len);
CountSort(arr7, len, max);
printf("计数排序后结果:\n");
for(i = 0; i < len; i++)
{
printf("%d\t", *(arr7 + i));
}
printf("\n");
//进行基数排序
arr8 = (int *)malloc(sizeof(int) * len);
if(arr8 == NULL)
{
printf("内存分配失败\n");
system("pause");
return -1;
}
memcpy(arr8, data, sizeof(int) * len);
RadixCountSort(arr8, len);
printf("基数排序后结果:\n");
for(i = 0; i < len; i++)
{
printf("%d\t", *(arr8 + i));
}
printf("\n");
//释放内存
free(data);
free(arr1);
free(arr2);
free(arr3);
free(arr4);
free(arr5);
free(arr6);
free(arr7);
free(arr8);
system("pause");
return 0;
}
测试程序
下面是对排序算法的测试
PS:快排会压栈,测试快排请注释掉其他排序
//FILE: sort_test.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<time.h>
#include<windows.h>
#include "sort.c"
//宏定义常量
#define LEN 10000 //测试大数据下排序的数组长度
#define N 100000 //执行次数
#define M 100 //每个数组的长度
#define RANGE 1000 //随机数范围
int main(void)
{
int i, j, max;
int test1[LEN], test2[M];
int *temp;
clock_t start, end;
//生成大数据
for(i = 0; i < LEN; i++) //生成LEN个随机数
{
test1[i] = rand() % RANGE; //生成0~999的数据(range - 1)
}
//大数据测试
printf("下面是%d个数据的排序情况:\n", LEN);
//插入排序
start = clock();
insertSort(test1, LEN);
end = clock();
printf("插入排序:%d ms\n", end - start);
//归并排序
temp = (int *)malloc(sizeof(int) * LEN);
if(temp == NULL)
{
printf("内存分配失败\n");
system("pause");
exit(0);
}
start = clock();
MergeSort(test1, 0, LEN - 1, temp);
end = clock();
printf("归并排序:%d ms\n", end - start);
free(temp);
//快速排序(递归)
start = clock();
QuickSort_Recursion(test1, 0, LEN - 1);
end = clock();
printf("快速排序(递归):%d ms\n", end - start);
//快速排序(枢轴存放)
start = clock();
PartitionQuickSort(test1, 0, LEN - 1);
end = clock();
printf("快速排序(枢轴存放):%d ms\n", end - start);
//计数排序
start = clock();
max = arrayMax(test1, LEN);
CountSort(test1, LEN, max);
end = clock();
printf("计数排序:%d ms\n", end - start);
//基数排序
start = clock();
RadixCountSort(test1, LEN);
end = clock();
printf("基数排序:%d ms\n", end - start);
//测试大量小数组
//进行100k次排序,每次对大小为100的数组进行排序
printf("下面测试大量小数组\n");
//插入排序
start = clock();
for(i = 0; i < N; i++)
{
for(j = 0; j < M; j++)
{
test2[j] = rand() % RANGE;
}
insertSort(test2, M);
}
end = clock();
printf("插入排序:%d ms\n", end - start);
//归并排序
start = clock();
for(i = 0; i < N; i++)
{
temp = (int *)malloc(sizeof(int) * M);
if(temp == NULL)
{
printf("内存分配失败\n");
system("pause");
exit(0);
}
for(j = 0; j < M; j++)
{
test2[j] = rand() % RANGE;
}
MergeSort(test2, 0, M - 1, temp);
free(temp);
}
end = clock();
printf("归并排序:%d ms\n", end - start);
//快速排序(递归)
start = clock();
for(i = 0; i < N; i++)
{
for(j = 0; j < M; j++)
{
test2[j] = rand() % RANGE;
}
QuickSort_Recursion(test2, 0, M - 1);
}
end = clock();
printf("快速排序(递归):%d ms\n", end - start);
//快速排序(枢轴存放)
start = clock();
for(i = 0; i < N; i++)
{
for(j = 0; j < M; j++)
{
test2[j] = rand() % RANGE;
}
PartitionQuickSort(test2, 0, M - 1);
}
end = clock();
printf("快速排序(枢轴存放):%d ms\n", end - start);
//计数排序
start = clock();
for(i = 0; i < N; i++)
{
for(j = 0; j < M; j++)
{
test2[j] = rand() % RANGE;
}
max = arrayMax(test2, M);
CountSort(test2, M, max);
}
end = clock();
printf("计数排序:%d ms\n", end - start);
//基数排序
start = clock();
for(i = 0; i < N; i++)
{
for(j = 0; j < M; j++)
{
test2[j] = rand() % RANGE;
}
RadixCountSort(test2, M);
}
end = clock();
printf("基数排序:%d ms\n", end - start);
system("pause");
return 0;
}
以上就是全部内容,有错误还请在评论中指出来,一起学习,一起进步。还有很多的排序方法,有时间学习后再进行补充。