基于非比较的排序:计数排序(countSort),桶排序(bucketSort),基数排序(radixSort)

计数排序

条件:要排序的数组的元素必须是在一定范围的,比如是1~100。在排序之前我们必须知道数组元素的范围。
思路:顾名思义:就是用一个数组来计数的。
步骤:
1、用一个数组来计数count[ ],将要排序的数组arr[ ]的元素记为数组count[ ]数组的下标,如果数组arr[]中有两个数相同就在count[]++.如count[arr[i]]++.
2、 再一次遍历数组count[ ],将count[i]  +=  count[i-1]+count[i-2]+....+count[0],为的是记录该下标对应的元素在数组中的位置
3、开始进行排序,我们用一个数组来记录排好序的元素sorted[ ]。
4、由步骤2我们可以清楚的知道count[ ]中下标对应的的元素在所有元素的排位(即排到第几个数)。但是必须减一(因为比如排到第五位对应的数组下标应该是4)
5、具体的表达式为:
count[arr[i ] ]--;//就是在sorted[]中下标减一
sorted[ count[arr[i ] ] ]  = a[ i ];//count[ arr[ i] ]在sorted[ ]中对应的位置,等于a[ i ]就是对应元素的值。
6、按步骤5的方式遍历完数组的长度就能得到排序好的数组sorted[].
时间复杂度:O(N + K)
代码:show you my code!
public class CountSort {
	static int[] countSort(int[] a, int range/*数组元素的范围*/){
		int count[] = new int[range];
		for (int i = 0; i < a.length; i++) {
			count[a[i]]++;
		}
		for (int i = 1; i < count.length; i++) {
			count[i] += count[i-1];
		}
		int sortArr[] = new int[a.length];
		for (int i = 0; i < sortArr.length; i++) {
			count[a[i]]--;
			sortArr[count[a[i]]] = a[i];
		}
		return sortArr;
	}
	
	public static void main(String[] args) {
		int[] a = {1,34,66,90,99,34,56,2,3,47,66,99};
		
		int[] sortArr = countSort(a,100);
		for (int i = 0; i < sortArr.length; i++) {
			System.out.print(sortArr[i]+" ");
		}
	}
}

桶排序

条件:类似于计数排序,必须知道要排序的元素的范围(如0~N)。
思路:
1、我们可以把根据元素的范围将范围分成K个范围(每个范围对应一个桶)(K=N/常数)。
2、接着我们可以对将要排序的数组元素分派到对应的桶中。
3、我们再对各个桶进行排序(用插入排序)。(如果每个桶的数据都是一样的或者是桶的范围为1,此时就退化成计数排序)。
4、排好后的各个桶的排列就是排好序的。
时间复杂度为:O(N +K),最坏为(N^2)就是全部都在一个桶里(对桶进行插入排序时间复杂度就是为N^2),空间复杂度为(N*K)。
适用:适用于大数据排序,牛逼闪闪,哈哈!
CODE:参考自点击打开链接
#include <time.h>
#include <iostream>
#include <iomanip>
using namespace  std;

/*initial arr*/
void InitialArr(double *arr,int n)
{
	srand((unsigned)time(NULL));
	for (int i = 0; i<n;i++)
	{
arr[i] = rand()/double(RAND_MAX+1);   //(0.1)
}
}

/* print arr*/
void PrintArr(double *arr,int n)
{
	for (int i = 0;i < n; i++)
	{
		cout<<setw(15)<<arr[i];
		if ((i+1)%5 == 0 || i ==  n-1)
		{
			cout<<endl;
		}
	}
}

void BucketSort(double * arr,int n)     
{
	double **bucket = new double*[10];
	for (int i = 0;i<10;i++)
	{
		bucket[i] = new double[n];
	}
	int count[10] = {0};
	for (int i = 0 ; i < n ; i++)
	{
		double temp = arr[i];
int flag = (int)(arr[i]*10); //flag标识小树的第一位 
bucket[flag][count[flag]] = temp; //用二维数组的每个向量来存放小树第一位相同的数据
int j = count[flag]++;

/* 利用插入排序对每一行进行排序 */
for(;j > 0 && temp < bucket[flag][j - 1]; --j)
{
	bucket[flag][j] = bucket[flag][j-1];
}
bucket[flag][j] =temp;
}

/* 所有数据重新链接 */
int k=0;
for (int i = 0 ; i < 10 ; i++)
{
	for (int j = 0 ; j< count[i];j++)
	{
		arr[k] = bucket[i][j];
		k++;
	}
}
for (int i = 0 ; i<10 ;i++)
{
	delete bucket[i];
	bucket[i] =NULL;
}
delete []bucket;
bucket = NULL;
}

void main()
{
	double *arr=new double[10];
	InitialArr(arr, 10);
	BucketSort(arr, 10);
	PrintArr(arr,10);
	delete [] arr;
}



基数排序

条件相对比较宽松:可以使比较无规律的范围,但是尽量不要参进来负数,不然就得另作考虑。
思路:
1、我们可以每次取各元素的一个位来进行比较从各位到最大的位依次进行比较。这样最终就能得到已排好序的元素。
2、如:现在有一下元素:9, 23,34, 78,345.
A:对个位进行排序:23, 34, 345, 78, 9.
B:对十位进行排序:9(注:9的十位是0), 23, 34, 345,78.
C:对百位进行排序:9, 23, 34, 78, 345.
3、每次进行的排序用的是计数排序。
时间复杂度:O(K*N)
#include<stdio.h>
#define MAX 20
#define SHOWPASS
#define BASE 10

void print(int *a, int n) {
  int i;
  for (i = 0; i < n; i++) {
    printf("%d\t", a[i]);
  }
}

void radixsort(int *a, int n) {
  int i, b[MAX], m = a[0], exp = 1;
  //寻找最大位数的那个数
  for (i = 1; i < n; i++) {
    if (a[i] > m) {
      m = a[i];
    }
  }

  while (m / exp > 0) {
    int bucket[BASE] = { 0 };
    //进行计数排序
    for (i = 0; i < n; i++) {
      bucket[(a[i] / exp) % BASE]++;
    }

    for (i = 1; i < BASE; i++) {
      bucket[i] += bucket[i - 1];
    }

    for (i = n - 1; i >= 0; i--) {
      b[--bucket[(a[i] / exp) % BASE]] = a[i];
    }

    for (i = 0; i < n; i++) {
      a[i] = b[i];
    }
    //计数排序结束
    exp *= BASE;//进入下个位数

#ifdef SHOWPASS
    printf("\nPASS   : ");
    print(a, n);
#endif
  }
}

int main() {
  int arr[MAX];
  int i, n;

  printf("Enter total elements (n <= %d) : ", MAX);
  scanf("%d", &n);
  n = n < MAX ? n : MAX;

  printf("Enter %d Elements : ", n);
  for (i = 0; i < n; i++) {
    scanf("%d", &arr[i]);
  }

  printf("\nARRAY  : ");
  print(&arr[0], n);

  radixsort(&arr[0], n);

  printf("\nSORTED : ");
  print(&arr[0], n);
  printf("\n");

  return 0;
}

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基数排序是一种基于桶排序排序算法,它通过将待排序的数字按照个位、十位、百位等位数进行排序,从而实现整体的排序。下面是一个简单的基数排序的C语言实现示例: ```c #include <stdio.h> // 获取数组中的最大值 int getMax(int arr[], int n) { int max = arr[0]; for (int i = 1; i < n; i++) { if ([i] > max) { max = arr[i]; } } return max; } // 使用计数排序对数组按照指定的位数进行排序 void countSort(int arr[], int n, int exp) { int output[n]; // 存储排序后的结果 int count[10] = {0}; // 存储每个数字出现的次数 // 统计每个数字出现的次数 for (int i = 0; i < n; i++) { count[(arr[i] / exp) % 10]++; } // 计算每个数字在排序后的数组中的位置 for (int i = 1; i < 10; i++) { count[i] += count[i - 1]; } // 将数字按照指定位数排序 for (int i = n - 1; i >= 0; i--) { output[count[(arr[i] / exp) % 10] - 1] = arr[i]; count[(arr[i] / exp) % 10]--; } // 将排序后的结果复制回原数组 for (int i = 0; i < n; i++) { arr[i] = output[i]; } } // 基数排序函数 void radixSort(int arr[], int n) { int max = getMax(arr, n); // 获取数组中的最大值 // 对每个位数进行排序 for (int exp = 1; max / exp > 0; exp *= 10) { countSort(arr, n, exp); } } int main() { int arr[] = {170, 45, 75, 90, 802, 24, 2, 66}; int n = sizeof(arr) / sizeof(arr[0]); radixSort(arr, n); printf("排序后的数组:"); for (int i = 0; i < n; i++) { printf("%d ", arr[i]); } return 0; } ``` 运行以上代码,输出结果为:2 24 45 66 75 90 170 802,表示数组已经按照从小到大的顺序进行了排序
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值