编辑:我发现了我的问题。我对快捷通行证的最大检查不适用于负数。我有负数,然后检查> 0值,然后当我回到负数时忘记了添加最大检查。您关心最大的设置位。对于任何负数为1 << 63。
#pragma once
#ifndef SORT_H
#define SORT_H
#include <algorithm>
#include <type_traits>
typedef int radix_type;
void lsdradix(radix_type* idx, radix_type length)
{
if (idx == nullptr || length < 2)
return;
if (length < 100)
{
std::sort(idx, idx + length);
return;
}
constexpr radix_type r = 8;
radix_type counters[1 << r];
radix_type positions[1 << r];
radix_type* temp = new radix_type[length];
constexpr radix_type mask = (1 << r) - 1;
radix_type max = std::numeric_limits<radix_type>::min();
for (radix_type i = 0; i < length; i++)
{
radix_type val = abs(idx[i]);
if (max < val) max = val;
}
radix_type msb = 0;
while ((max >> msb) != 0) msb++;
msb = ((msb + (r-1))/r)*r;
radix_type shift;
for (shift = 0; shift < msb; shift += r)
{
for (radix_type j = 0; j < (1 << r); ++j)
counters[j] = 0;
for (radix_type j = 0; j < length; ++j)
counters[(idx[j] >> shift) & mask]++;
positions[0] = 0;
for (radix_type j = 1; j < (1 << r); ++j)
positions[j] = positions[j - 1] + counters[j - 1];
for (radix_type j = 0; j < length; ++j)
temp[positions[(idx[j] >> shift) & mask]++] = idx[j];
std::swap(temp, idx); //We don't want to actually perform a memcpy till the end
}
if ((msb/r) & 1 == 1)
{
std::swap(idx, temp);
}
constexpr radix_type negIndex = (1 << (r-1)) - 1;
if (std::numeric_limits<radix_type>::is_signed && positions[negIndex] < length)
{
radix_type negativeCount = length - positions[negIndex];
memcpy(idx, temp + (length - negativeCount), sizeof(radix_type)*negativeCount);
memcpy(idx + negativeCount, temp, sizeof(radix_type)*(length - negativeCount));
}
else
{
memcpy(idx, temp, sizeof(radix_type)*length);
}
delete[] temp;
}
测试
#include "stdafx.h"
#include "sort.h"
#include <vector>
#include <random>
#include <chrono>
#include <iostream>
#include <algorithm>
int main()
{
constexpr int count = 1000000;
std::vector<radix_type> data, data2;
data.resize(count);
bool success = true;
std::default_random_engine engine;
radix_type min = -(1 << 32), max = (1 << 32);
std::uniform_int_distribution<radix_type> range(min,max); engine.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());
for (int i = 1; i < data.size(); i++)
{
data[i] = range(engine);
}
data[0] = max;
data[data.size()-1] = min;
data2 = data;
auto t1 = std::chrono::high_resolution_clock::now();
lsdradix(data2.data(), data2.size());
auto t2 = std::chrono::high_resolution_clock::now();
std::cout << "lsd radix: " << (t2 - t1).count() / 1000000.0 << " ms" << std::endl;
t1 = std::chrono::high_resolution_clock::now();
std::sort(data2.begin(), data2.end());
t2 = std::chrono::high_resolution_clock::now();
std::cout << "std::sort: " << (t2 - t1).count() / 1000000.0 << " ms" << std::endl;
for (int i = 0; i < data.size(); i++)
{
if (data[i] != data2[i])
{
success = false;
break;
}
}
if (!success)
{
for (int i = 0; i < data.size(); i++)
{
//std::cout << data3[i] << " " << data2[i] << std::endl;
}
}
std::cout << (success ? "match!" : "don't match!") << std::endl;
return 0;
}