基数排序实现对某些输入失败

时间:2018-07-30 00:29:26

标签: c++ sorting radix-sort

编辑:我发现了我的问题。我对快捷通行证的最大检查不适用于负数。我有负数,然后检查> 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;
}

0 个答案:

没有答案