gpt4 book ai didi

c++ - 使用位运算的基数排序

转载 作者:太空宇宙 更新时间:2023-11-04 16:20:45 26 4
gpt4 key购买 nike

首先这是作业,我找到了另一个主题谈论同一主题但没有答案。这是问题所在:

Sorting by bit based on the assumption that the values ​​to be sorted are integers coded B bits (and therefore between 0 and 2B-1).

主要问题是如何进行这种排序。我应该将每个整数转换为位并进行比较吗?请不要给我解决方案,只是提示或解释如何操作。感谢您的帮助 ![编辑]我在互联网上找到了这个脚本,但我不明白它是如何工作的:

#include <cstdlib>
#include <iostream>
#include <string>
#include <cctype>
#include<algorithm>
#include<string>
#include <iterator>
using namespace std;

// Radix sort comparator for 32-bit two's complement integers
class radix_test
{
const int bit; // bit position [0..31] to examine
public:
radix_test(int offset) : bit(offset) {} // constructor

bool operator()(int value) const // function call operator
{
if (bit == 31) // sign bit
return value < 0; // negative int to left partition
else
return !(value & (1 << bit)); // 0 bit to left partition
}
};

// Least significant digit radix sort
void lsd_radix_sort(int *first, int *last)
{
for (int lsb = 0; lsb < 32; ++lsb) // least-significant-bit
{
std::stable_partition(first, last, radix_test(lsb));
}
}

// Most significant digit radix sort (recursive)
void msd_radix_sort(int *first, int *last, int msb = 31)
{
if (first != last && msb >= 0)
{
int *mid = std::partition(first, last, radix_test(msb));
msb--; // decrement most-significant-bit
msd_radix_sort(first, mid, msb); // sort left partition
msd_radix_sort(mid, last, msb); // sort right partition
}
}

int main(int argc, char *argv[])
{

int data[] = { 170, 45, 75, -90, -802, 24, 2, 66 };

lsd_radix_sort(data, data + 8);
// msd_radix_sort(data, data + 8);

std::copy(data, data + 8, std::ostream_iterator<int>(std::cout, " "));

system("PAUSE");
return EXIT_SUCCESS;
}

最佳答案

首先,您不需要将整数转换为位,因为它已经存储为位。一个int通常是 4 个字节,所以是 32 位。您可以使用位运算符访问这些位。

这里详细展示了基数排序。 https://en.wikipedia.org/wiki/Radix_sort

此示例基于 10 位数字进行排序。

要根据位排序,您可以稍微更改算法以在所有位置使用 2 而不是 10:

void radixsort(int *a, int n) {
...
while (m / exp > 0) {
int bucket[2] = { 0 };
for (i = 0; i < n; i++) bucket[a[i] / exp % 2]++;
bucket[1] += bucket[0];
for (i = n - 1; i >= 0; i--) b[--bucket[a[i] / exp % 2]] = a[i];
for (i = 0; i < n; i++) a[i] = b[i];
exp *= 2;
...
}
}

但是如果您需要改用按位运算符,您会发现除以 2 的任何值都只是 >> 1 , 乘以 2 是 << 1 , 模 2 是 &1 .通过替换 exp有了位的位置,我们可以改写如下:

void radixsort(int *a, int n) {
int i, b[MAX], m = a[0], bit = 0;
for (i = 0; i < n; i++) if (a[i] > m) m = a[i];

while ((m>>bit) > 0) {
int bucket[2] = { 0 };
for (i = 0; i < n; i++) bucket[(a[i]>>bit) & 1]++;
bucket[1] += bucket[0];
for (i = n - 1; i >= 0; i--) b[--bucket[(a[i]>>bit) & 1]] = a[i];
for (i = 0; i < n; i++) a[i] = b[i];
bit++;
...
}
}

这使用单个位进行排序。要使用多个位,您需要使其更通用:

#define BITS 2
void radixsort(int *a, int n) {
int i, b[MAX], m = a[0], pos = 0;
int buckets=1<<BITS;
int mask=buckets-1;
for (i = 0; i < n; i++) if (a[i] > m) m = a[i];

while ((m>>(pos*BITS)) > 0) {
int bucket[1<<BITS] = { 0 };
for (i = 0; i < n; i++) bucket[(a[i]>>(pos*BITS)) & mask]++;
for (i = 1; i < buckets; i++) bucket[i] += bucket[i - 1];
for (i = n - 1; i >= 0; i--) b[--bucket[(a[i]>>(pos*BITS)) & mask]] = a[i];
for (i = 0; i < n; i++) a[i] = b[i];
pos++;
...
}
}

这使用两位进行排序,因此 4 个桶用于 00、01、10 和 11。3 位将使用 8 个桶(000、001、010、011、100、101、110、111)。

您可以看到增加 BITS 如何减少传递次数,但每次传递的工作量更大。

关于c++ - 使用位运算的基数排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17043492/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com