几种排序方法的对比(快排,归并,插入,计数)

本文对比了非递归快速排序、递归快速排序、归并排序、插入排序和两种计数排序的实现。通过测试,展示了不同排序算法在不同数据规模下的性能差异,强调在选择排序算法时要考虑效率因素。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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多秒,效率可算很低,因此选择排序方法时需慎重考虑。

       同时读者可采用上述排序方法自行测试,或增大数据量,或增大随机数的范围,测试的结果也会不同,本文只是简单举个例子进行测试。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值