1、非递归快排
首先建立结构体存储两个下标
struct Node{
int first;
int last;
};
void Quicksort(int first, int last, int a[]){
int key = a[first];
int i = first;
int j = last;
int temp;
struct Node stack[100];
int top = 0;
stack[top].first = first;
stack[top].last = last;
while (top>-1) //栈不为空时
{
i = first = stack[top].first;
j = last = stack[top].last;
top--;
key = a[first];
while (i<j){
while ((i<j) && (key <= a[j])) //处理左区间
j--;
if (i < j){
temp = a[i];
a[i] = a[j];
a[j] = temp;
i++;
}
while ((i<j) && (key >= a[i])) //处理右区间
i++;
if (i < j){
temp = a[i];
a[i] = a[j];
a[j] = temp;
j--;
}
}
if (first < i - 1){
top++;
stack[top].first = first;
stack[top].last = i - 1;
}
if (last>i + 1){
top++;
stack[top].first = i + 1;
stack[top].last = last;
}
}
}
2、递归快排
a是待排序的数组,left是数组的左边界,right是数组的右边界
void quicksort(int *a, int left, int right){
if (left >= right)
return ;
int i = left;
int j = right;
int key = a[left];
while (i < j){
while (i < j && key <= a[j]) //从右到左找小于key的数
j--;
a[i] = a[j];
while (i < j && key >= a[i]) //从左到右找大于等于key的数
i++;
a[j] = a[i];
}
a[i] = key; //分割成两部分进行递归处理
quicksort(a, left, i - 1);
quicksort(a, i + 1, right);
}
3、归并排序
void merge(int a[], int first, int mid, int last, int temp[]){
int p = 0;
int p1 = first;
int i;
int p2 = mid + 1;
while (p1 <= mid && p2 <= last)
{
if(a[p1] < a[p2])
temp[p++] = a[p1++];
else
temp[p++] = a[p2++];
}
while (p1 <= mid)
temp[p++] = a[p1++];
while (p2 <= last)
temp[p++] = a[p2++];
for ( i = 0; i < last - first + 1; i++)
a[first + i] = temp[i];
}
void mergesort(int a[], int first, int last, int temp[]){
if (first < last)
{
int mid = first + (last - first) / 2;
mergesort(a, first, mid, temp); //左边有序
mergesort(a, mid+1, last, temp); //右边有序
merge(a, first, mid, last, temp); //将两个有序数列合并
}
}
4、插入排序
void insertsort(int a[], int len){
int temp,i,j;
for ( i = 1; i < len; i++)
{
temp = a[i]; //保存当前位置的元素,其中[0,i-1]已经有序
for ( j = i; j > 0 && a[j - 1] > temp; j--)
{
a[j] = a[j - 1]; // 后移一位
}
a[j] = temp; // 插入到合适的位置
}
}
5、计数排序
//size为要排序的数组长度
void countsort(int array[], int size){
int max = 0;
int i;
for( i = 0; i < size; i++){
max = a[i] > max ? a[i] : max;
}
//记录比某个数小的其他数字的个数,大小应为数组中最大数的大小
int *countArray = (int *)malloc(sizeof(int)*(max+1));
//记录排序好了的数列的数组,大小应为size
int *sortedArray = (int *)malloc(sizeof(int)*size);
for( i = 0;i < max + 1; ++i){
countArray[i] = 0; //给有序数组初始化
}
for(i = 0;i < size; ++i){
countArray[array[i]]++; //计算要排序的数组中各个元素的个数
}
for( i = 1;i < max + 1; ++i){
countArray[i] += countArray[i - 1]; //计算出各个元素在数组中的位置
}
for(i = size - 1; i >= 0; --i){
sortedArray[countArray[array[i]] - 1] = array[i]; //从数组的后面开始排序
--countArray[array[i]];
}
for( i = 0;i < size;++i)
array[i] = sortedArray[i]; //用已排序的数组替换原数组
free(countArray);
free(sortedArray);
}
6、简单的计数排序(利用一个桶)
int Max(int *pArr, int len) { // 求出数组最大值
int i;
int max = pArr[0];
for ( i = 0; i < len; i++) {
if (max < pArr[i]) {
max = pArr[i];
}
}
return max;
}
pArr是待排序数组,len是数组的长度,并且数组中数据的范围是[0,max)
void Bucket_sort(int *pArr, int len, int max) {
int *bucket;
int i,j;
bucket = (int *)malloc((max+1)*sizeof(int)); // 动态分配内存,注意要max+1,因为编号是从0开始的。
if(bucket == NULL){
return;
}
memset(bucket, 0, (max+1)*sizeof(int)); // 将数组内的元素全部置0
for ( i = 0; i < len; i++) {
++bucket[pArr[i]]; // 其实数组内的数字对应的就是桶的下标
}
for (i = 0, j = 0; i < max; i++) //排序
while((bucket[i]--) > 0)
pArr[j++] = i;
free(bucket);
}
该算法不能对负数进行排序,也不是真正的桶排,算是一种简单的计数排序,桶排序是将待排序数据分成N个段,即N个桶,再将数据按照插入排序的方式放入各自的桶中,最后按桶次序输出。(桶排序将在以后博文再给出)
7、测试
分为三组测试,数组长度分别为20w,5w和1w,数组元素值是随机数,随机数的取值范围是0〜30000
经过测试分析,总结六种排序的对比,如下图所示
,
图中部分测试耗时显示为0,其实并不是不耗时,而是排序所用的时间极极极少。
插入排序在数据量为20w排序的时候就需要我们等待48多秒,效率可算很低,因此选择排序方法时需慎重考虑。
同时读者可采用上述排序方法自行测试,或增大数据量,或增大随机数的范围,测试的结果也会不同,本文只是简单举个例子进行测试。