double类型数组排序

#include<algorithm>
#include<vector>
#include<string>
#include<iostream>

using namespace std;

//double类型数据排序,要求时间复杂度为O(n)
//O(n)复杂度的排序算法主要是计数排序、基数排序和桶排序。
//采用基数排序的方式求解这个问题

void RadixSort(vector<double> &nums) {   
     if (nums.empty()) {
	return;
     }  
     int n = nums.size();
     vector<long long> t(n), a(n);
	
     //这部分的作用是消除小数点,只保留符号,这样就能用基于字节的基数排序来做。
     for (int i = 0; i < n; i++){
	a[i] = *(long long*)(&nums[i]);//将数组中每个元素地址类型转换成long long类型再取元素值。
     }

     //将long long类型数组分为4部分
     int groupLength = 16;
     int bitLength = 64;
     int len = 1 << groupLength;//len=65536

     vector<int> count(len), pref(len);

     int groups = bitLength / groupLength;
     int mask = len - 1;
     int negatives = 0, positives = 0;

     for (int c = 0, shift = 0; c < groups; c++, shift += groupLength) {  
     // 重置数组
	fill(count.begin(), count.end(), 0);

	// 计算元素属于哪一个段,从低16位开始排序
	for (int i = 0; i < n; i++) {
	    ++count[(a[i] >> shift) & mask];

	    // 额外考虑负数问题,记录负数的个数,只统计一次就够了
	    if (c == 0 && a[i] < 0)
	       ++negatives;
	 }
	 if (c == 0)
	    positives = n - negatives;

	 // 计算每一段的起始位置
	 pref[0] = 0;
	 for (int i = 1; i < len; i++)
	     pref[i] = pref[i - 1] + count[i - 1];

	 // 将数组中的数复制到临时数组t中
	 for (int i = 0; i < n; i++) {
	     int index = pref[(a[i] >> shift) & mask]++;
	     if (c == groups - 1) {//如果是负数,则从大向小排列,索引逆序
		if (a[i] < 0)
		   index = n - index - 1;
		else
		   index += negatives;
	     }
	     t[index] = a[i];
	  }

	   //将临时数组中的数复制到原数组
	   if (c != groups - 1) {
	      for (int j = 0; j < n; j++)
		 a[j] = t[j];
	  }
	  //输出每次排序的结果
	  //for (int i = 0; i < n; i++) {
	  //	cout << *(double*)(&t[i]) << " ";
	  //}
	  //cout << endl;
	}

	// 返回到原double类型的数组中
	for (int i = 0; i < n; i++) {
	  nums[i] = *(double*)(&t[i]);
	}
}


int main(){
  vector<double> input = { 3.23,6.854,12.8,79.5,-2.3,1.0,0.23,-0.9 };
  RadixSort(input);
  for (int i = 0; i < input.size(); i++){  
    cout << input[i] << " ";
  }
  cout << endl;
  system("pause");
  return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值