下面给出了整数Radix Sort的代码,它使用修改后的Bucket Sort对数组进行排序。 bucket Sort使用一个列表数组,其中列表的数量与基数相同(8-octal,10-decimal,16-hex)。
数字' 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())创建自定义List(用于保存存储桶)是一个好主意(它会运行得更快),其中一个从开头删除一个项目(需要在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
答案 0 :(得分:0)
提高算法速度的其他任何方法?
代替使用列表列表,代码可以分配矩阵,并在原始数组的单个传递中用原始数组的每个元素的每个“数字”的出现次数填充它。然后可以将计数转换为每个“数字”的桶边界的起始(或结束)索引。这允许使用与原始数组相同大小的单个临时数组来包含每个基数排序过程中的“桶”。在基数排序期间,在temp和original之间交换引用(在C或C ++中这将是交换指针)的方法是最佳的。
基本256基数排序的示例C ++代码:
Radix Sort Base 16 (Hexadecimals)
性能取决于基数?如果是,那么最佳基数是什么?
最佳基数取决于每个元素的大小和要排序的元素数量。这个帖子的答案解释了理想的情况,以及由于缓存问题引起的现实情况:
有关如何将其转换为多线程版本的任何想法
最简单的方法是将数组拆分为k个子数组(假设k个有效内核),并行排序k个子数组(使用任何排序方法,包括基数排序),然后合并k个排序子阵列。