【问题标题】:Creating Customized List for Radix Sort为基数排序创建自定义列表
【发布时间】:2017-07-13 18:27:28
【问题描述】:

下面给出的是整数基数排序的代码,它使用修改后的桶排序对数组进行排序。桶排序使用列表数组,其中列表的数量与基数相同(8-八进制,10-十进制,16-十六进制)。

基数运算得到的数字'i'被压入列表数组的List'i'中。实际上它不是数字,而是输入数组中被推送到列表中的索引。这需要扫描输入数组,因此花费的时间是 O(n)。之后,逐个列表检索索引,即先处理上一个列表中的所有索引,然后再移动到下一个列表是列表数组,然后将临时结果放入 temp_array。

最后,数组指针的交换避免了将 temp_array 复制到 input_array 的需要。当基数递减时,列表数组被重新初始化到新的内存位置。这种方式避免了由于元素的移动而需要时间复杂度为 O(n) 的 list.remove(index) 方法。 JVM会在执行过程中清除旧的内存位置还是最终导致内存溢出?

从索引 0 和最后一个索引处的列表中删除 (=N), ( list.remove(0), list.remove(N) ) 这些方法中哪个更快?

使用 2 个删除方法(remove1()、remove2())创建一个自定义列表(用于存放桶)是一个好主意(它会运行得更快吗),其中一个从头开始删除一个项目(需要列表在 O(1) 时间内升序排列,其他在最后(降序排列需要)在相同 O(1) 时间内(不需要移动元素并且还支持 arrayList 的随机访问)? (我认为不可能两者兼得。)

如果是,那么必要的代码行和导入的类是什么?

如果没有,还有其他方法可以提高算法的速度吗?

改变基数是否会改变性能,即性能是否取决于基数?如果是的话,最佳的基数是多少?

关于如何将其转换为多线程版本的任何想法?我认为这是不可能的。

import java.util.List ;
import java.util.ArrayList ;

public class Radix_Sort
{
    // input_array[] -> the array to be sorted
    // temp_array[] -> the array to hold the temporary result, must be equal to or larger than input_array in size
    // radix -> is the number of digits in maxiumum value in array : floor of log(MaxValue)
    // length -> length of input_array[]
    // base -> Base of the number system used

    public static int[] ASC(int input_array[], int temp_array[], int radix, int length, int base)
    {
        int div = 1 ;
        int swap[] ;
        int i, s_indx, Y, j ;
        while(radix > 0)
        {
            List<List<Integer>> buckets = new ArrayList<List<Integer>>(base) ;
            i = 0 ;
            while(i < base)
            {
                buckets.add(new ArrayList<Integer>()) ;
                i++ ;
            }
            i = 0 ;
            while(i < length)
            {
                buckets.get(( input_array[i] / div ) % base ).add(i) ;
                i++ ;
            }
            s_indx = 0 ;
            i = 0 ;
            while(i < base)
            {
                Y = buckets.get(i).size() ;
                j = 0 ;
                while(j < Y)
                {
                    temp_array[s_indx++] = input_array[buckets.get(i).get(j)] ;
                    j++ ;
                }
                i++ ;
            }
            swap = input_array ;
            input_array = temp_array ;
            temp_array = swap ;
            div = div * base ;
            radix--;
        }
        return input_array ;
    }

    public static int[] DSC(int input_array[], int temp_array[], int radix, int length, int base)
    {
        int div = 1 ;
        int swap[] ;
        int i, s_indx, Y ;
        while(radix > 0)
        {
            List<List<Integer>> buckets = new ArrayList<List<Integer>>(base) ;
            i = 0 ;
            while(i < base)
            {
                buckets.add(new ArrayList<Integer>()) ;
                i++ ;
            }
            i = 0 ;
            while(i < length)
            {
                buckets.get(( input_array[i] / div ) % base ).add(i) ;
                i++ ;
            }
            s_indx = length - 1 ;
            i = 0 ;
            while(i < base)
            {
                Y = buckets.get(i).size() ;
                while(Y > 0)
                {
                    Y-- ;
                    temp_array[s_indx--] = input_array[buckets.get(i).get(Y)] ;
                }
                i++ ;
            }
            swap = input_array ;
            input_array = temp_array ;
            temp_array = swap ;
            div = div * base ;
            radix--;
        }
        return input_array ;
    }
}// end of class

【问题讨论】:

  • 添加'java'标签,最大化查看人数!!!
  • @J.Piquard,非常感谢

标签: java sorting arraylist linked-list radix-sort


【解决方案1】:

还有其他方法可以提高算法的速度吗?

代码可以分配一个矩阵,并在原始数组的单次遍历中为原始数组的每个元素填充每个“数字”的出现次数,而不是使用列表的列表。然后可以将计数转换为每个“数字”的桶边界的开始(或结束)索引。这允许使用与原始数组相同大小的单个临时数组来包含每个基数排序过程中的“桶”。您在基数排序期间在 temp 和 original 之间交换引用(在 C 或 C++ 中,这将是交换指针)的方法是最佳的。

基于 256 基数排序的示例 C++ 代码:

Radix Sort Base 16 (Hexadecimals)

性能取决于基础吗?如果是的话,最佳基数是多少?

最佳基数取决于每个元素的大小和要排序的元素数量。此线程中的答案解释了理想情况以及由于缓存问题导致的实际情况:

Why is the running time of radix-sort minimized when the base of the digits is equal to the number of numbers to be sorted?

关于如何将其转换为多线程版本的任何想法

最简单的方法是将数组拆分为k个子数组(假设k个有效核),将k个子数组并行排序(使用任何排序方法,包括基数排序),然后将k个排序后的子数组合并数组。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-09
    • 1970-01-01
    • 2017-11-06
    • 2012-08-04
    • 2011-03-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多