Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sorting 负整数的基数排序_Sorting_Language Agnostic_Radix Sort_Radix - Fatal编程技术网

Sorting 负整数的基数排序

Sorting 负整数的基数排序,sorting,language-agnostic,radix-sort,radix,Sorting,Language Agnostic,Radix Sort,Radix,我正在尝试实现整数的基数排序,包括负整数。对于非负整数,我计划为数字0-9创建一个由10个队列组成的队列,并实现LSD算法。但我有点被负整数搞糊涂了。我现在想的是,继续为它们创建另一个包含10个队列的队列,并分别对它们进行排序,然后在最后,我将给出两个列表,一个包含已排序的负整数,另一个包含非负整数。最后我会合并它们 你觉得这个怎么样?有没有更有效的方法来处理负整数 谢谢大家! 您可以将符号视为一种特殊的数字。你在单位上排序,然后是十等,最后在标志上排序。这确实会为负片生成一个相反的顺序,然后您

我正在尝试实现整数的基数排序,包括负整数。对于非负整数,我计划为数字0-9创建一个由10个队列组成的队列,并实现LSD算法。但我有点被负整数搞糊涂了。我现在想的是,继续为它们创建另一个包含10个队列的队列,并分别对它们进行排序,然后在最后,我将给出两个列表,一个包含已排序的负整数,另一个包含非负整数。最后我会合并它们

你觉得这个怎么样?有没有更有效的方法来处理负整数


谢谢大家!

您可以将符号视为一种特殊的数字。你在单位上排序,然后是十等,最后在标志上排序。这确实会为负片生成一个相反的顺序,然后您只需反转该桶中的内容即可。这就是旧的机械卡片分拣机的工作方式。

还有一种解决方案是从数组中分离出负整数,使其为正,使用基数排序为正值,然后将其反转,并用排序后的非负数组追加

绝对!当然,你必须注意将消极因素从积极因素中分离出来,但幸运的是这很容易。在排序算法开始时,您需要做的就是围绕值0对数组进行分区。之后,基数排序在分区的下方和上方

下面是实际中的算法。我从Kevin Wayne和Bob Sedgewick的MSD基数排序中得出:

private static final int CUTOFF=15;
私有静态最终整数位每整数=32;
私有静态最终整数位每字节=8;
专用静态最终整数R=256;
公共无效排序(int[]a){
int firstPositiveIndex=分区(0,a,0,a.length-1);
int[]aux=新的int[a.length];
如果(第一个正指数>0){
recSort(a,第一个正索引,a.length-1,0,aux);
recSort(a,0,第一正索引-1,0,辅助);
}否则{//全部为正
recSort(a,0,a.length-1,0,aux);
}
}
私有void recSort(int[]a、int-lo、int-hi、int-d、int[]aux){
如果(d>4)返回;
if(hi lobitsToShift)和mask;
计数[c+1]++;
}
//计算指数
用于(int i=0;ibitsToShift)和掩码;
辅助[计数[c]+lo]=a[i];
计数[c]++;
}
//复写
对于(int i=lo;i0)
recSort(a、lo、lo+计数[0]-1、d+1、aux);
对于(int i=1;i0)
recSort(a,lo+计数[i-1],lo+计数[i]-1,d+1,辅助);
}
}
//插入排序a[lo..hi],从dth字符开始
私有void insertionSort(int[]a,int-lo,int-hi){
对于(inti=lo;ilo&a[j]如果((curHi-1)注意到符号位是有符号整数中的最高位,但默认情况下,所有数字都按基数排序处理为无符号整数。因此,您需要告诉算法负数小于正数。对于32位有符号整数,您可以先对三个较低字节进行排序,然后对第四个字节(较高)进行排序符号位反转的字节,所以0将用于负数,而不是1,因此它们将首先出现


我强烈建议按字节而不是按十进制数字对数字进行排序,因为机器提取字节要比提取数字容易得多。

处理有符号值的最简单方法可能是偏移累积的起始位置(即,生成位置偏移)对最高有效位进行操作时。转换输入使所有数字都可以被视为无符号也是一个选项,但需要对值数组至少应用两次操作(一次用于准备输入,另一次用于恢复输出)

这使用了第一种技术以及字节大小的数字(字节访问通常更有效):

void lsdradixsort(int*a,size\n)
{
//按索引隔离整数字节。
自动bmask=[](整数x,大小i)
{
返回(静态_cast(x)>>i*8)&0xFF;
};
//分配临时缓冲区。
自动m=标准::使_唯一(n);
int*b=m.get();
//对于整数中的每个字节(假设为4字节整数)。
对于(尺寸i,j=0;j<4;j++){
//将计数器初始化为零;
大小\u t h[256]={},开始;
//直方图。
//计算索引字节值的每次出现次数。
对于(i=0;i0;i--)
b[--h[b任务(a[i-1],j)]]=a[i-1];
标准:交换(a,b);
}
}

注意:代码未经测试。对于任何错误/打字错误,我们深表歉意。

如果不使用“位移位”和“按位与”进行基数计算,则基数排序不会比著名的比较排序快

计算机使用2的补码来表示有符号的数字,这里的符号位位于二进制数字的最左端,在内存中表示

例如
436163157(作为32位数字)=000110011111111 01010010 01010101
-436163157(作为32位数字)=1110000000000 10101101

1(作为32位数字)=000000000000000000000000000000000000001
-1(作为32位数字)=111111111111111111111111111111111111

0表示为=000000000000000000000000000
高地
private static final int CUTOFF = 15;
private static final int BITS_PER_INT = 32;
private static final int BITS_PER_BYTE = 8;
private static final int R = 256;

public void sort(int[] a){
    int firstPositiveIndex = partition(0, a, 0, a.length-1);
    int[] aux =new int[a.length];
    if(firstPositiveIndex>0){
        recSort(a, firstPositiveIndex, a.length-1, 0,aux);
        recSort(a, 0, firstPositiveIndex-1, 0,aux);
    }else{//all positive
        recSort(a, 0, a.length-1, 0, aux);
    }
}

private void recSort(int[] a, int lo, int hi, int d, int[] aux){
    if(d>4)return;
    if(hi-lo<CUTOFF){
        insertionSort(a,lo, hi);
        return;
    }

    int[] count = new int[R+1];

    //compute counts
    int bitsToShift = BITS_PER_INT-BITS_PER_BYTE*d-BITS_PER_BYTE;
    int mask = 0b1111_1111;
    for(int i = lo; i<=hi; i++){
        int c = (a[i]>>bitsToShift) & mask;
        count[c+1]++;
    }

    //compute indices
    for(int i = 0; i<R; i++){
        count[i+1]=count[i]+count[i+1];
    }

    //distribute
    for(int i = lo; i<=hi; i++){
        int c = (a[i]>>bitsToShift) & mask;
        aux[count[c]+lo] = a[i];
        count[c]++;
    }
    //copy back
    for(int i = lo; i<=hi; i++){
        a[i]=aux[i];
    }

    if(count[0]>0)
        recSort(a, lo, lo+count[0]-1, d+1, aux);
    for(int i = 1; i<R; i++){
        if(count[i]>0)
            recSort(a, lo+count[i-1], lo+count[i]-1, d+1, aux);
    }
}

// insertion sort a[lo..hi], starting at dth character
private void insertionSort(int[] a, int lo, int hi) {
    for (int i = lo; i <= hi; i++)
        for (int j = i; j > lo && a[j] < a[j-1]; j--)
            swap(a, j, j-1);
}


//returns the index of the partition or to the right of where it should be if the pivot is not in the array 
public int partition(int pivot, int[] a, int lo, int hi){
    int curLo = lo;
    int curHi = hi;
    while(curLo<curHi){
        while(a[curLo]<pivot){
            if((curLo+1)>hi)return hi+1;
            curLo++;
        }

        while(a[curHi]>pivot){
            if((curHi-1)<lo)return lo-1;
            curHi--;
        }
        if(curLo<curHi){
            swap(a, curLo, curHi);
            if(a[curLo]!=pivot)curLo++;
            if(a[curHi]!=pivot)curHi--;             
        }
    }
    return curLo;
}


private void swap(int[] a, int i1, int i2){
    int t = a[i1];
    a[i1]=a[i2];
    a[i2]=t;
}
V = ( A[i] >> 24 ) & 255
public class RadixSortsInterviewQuestions {
    private static final int MSB = 64;

    static Map.Entry<Integer, Integer> twoSum(long[] a, long sum) {
        int n = a.length - 1;
        sort(a, MSB, 0, n);

        for (int i = 0, j = n; i < j; ) {
            long t = a[i] + a[j];
            if (t == sum) {
                return new SimpleImmutableEntry<>(i, j);
            } else if (t < sum) {
                i++;
            } else {
                j--;
            }
        }
        return null;
    }

    // Binary MSD radix sort: https://en.wikipedia.org/wiki/Radix_sort#In-place_MSD_radix_sort_implementations
    private static void sort(long[] a, int d, int lo, int hi) {
        if (hi < lo || d < 1) return;

        int left = lo - 1;
        int right = hi + 1;

        for (int i = left + 1; i < right; ) {
            if (isBitSet(a[i], d)) {
                swap(a, i, --right);
            } else {
                left++;
                i++;
            }
        }
        sort(a, d - 1, lo, left);
        sort(a, d - 1, right, hi);
    }

    private static boolean isBitSet(long x, int k) {
        boolean set = (x & 1L << (k - 1)) != 0;

        // invert signed bit so that all positive integers come after negative ones
        return (k == MSB) != set;
    }

    private static void swap(long[] a, int i, int j) {
        long tmp = a[i];
        a[i] = a[j];
        a[j] = tmp;
    }
}
Binary    | 2s-comp  | Flip sign
----------+----------+----------
0000      | 00       | -8
0001      | +1       | -7
0010      | +2       | -6
0011      | +3       | -5
0100      | +4       | -4
0101      | +5       | -3
0110      | +6       | -2
0111      | +7       | -1
1000      | -8       | 00
1001      | -7       | +1
1010      | -6       | +2
1011      | -5       | +3
1100      | -4       | +4
1101      | -3       | +5
1110      | -2       | +6
1111      | -1       | +7
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

static void sortbno(const int32_t* tab, // table of entries
                    int tabsz,    // #entries in tab
                    int bno,      // byte number in T
                    int* inidx,   // current sorted index before this byte
                    int* outidx)  // indices after sorting this byte
{
    int count[256];
    memset(count, 0, sizeof(count));

    // count occurrences of each byte value
    for (int i = 0; i < tabsz; i++) {
        int32_t x = tab[i];
        int v = (x >> (8 * bno)) & 0xff;
        count[v]++;
    }

    // change count[i] so it now reflects the actual
    // position of this byte value in outidx
    if (bno == sizeof(tab[0]) - 1) {
        /* account for signed bit for most-significant-byte */
        for (int i = 129; i < 256; i++) {
            count[i] += count[i - 1];
        }
        count[0] += count[255];
        for (int i = 1; i < 128; i++) {
            count[i] += count[i - 1];
        }
    } else {
        for (int i = 1; i < 256; i++) {
            count[i] += count[i - 1];
        }
    }

    // fill outidx[]
    for (int i = tabsz - 1; i >= 0; i--) {
        int in = inidx[i];
        int32_t x = tab[in];
        int v = (x >> (8 * bno)) & 0xff;
        outidx[--count[v]] = in;
    }
}

/**
 *  Sort tab[].
 *  Return the indices into tab[] in ascending order.
 */
int* rsort(const int32_t* tab, int tabsz)
{
    int* r[2];

    r[0] = malloc(tabsz * sizeof(*r[0]));
    r[1] = malloc(tabsz * sizeof(*r[1]));
    if (! (r[0] && r[1]))
        goto bail;

    // Artificially assign indices to items
    for (int i = 0; i < tabsz; i++) {
        r[0][i] = i;
    }

    // Sort byte by byte. byte #0 is x & 0xff.
    int bin = 0;
    for (int i = 0; i < (int)sizeof(tab[0]); i++) {
        sortbno(tab, tabsz, i, r[bin], r[1-bin]);
        bin = !bin;
    }

    free(r[1-bin]);
    return r[bin];

    bail:
    if (r[0]) free(r[0]);
    if (r[1]) free(r[1]);
    return 0;
}