Algorithm 在受限特征语言中对并行数组排序的最有效方法
环境:我使用的是一种专有的脚本语言,其中没有用户定义的函数。我可以创建和使用各种循环和基本类型的局部变量Algorithm 在受限特征语言中对并行数组排序的最有效方法,algorithm,sorting,scripting,Algorithm,Sorting,Scripting,环境:我使用的是一种专有的脚本语言,其中没有用户定义的函数。我可以创建和使用各种循环和基本类型的局部变量 我有两个相关的数组,“时间”和“值”。它们都包含浮点值。我想对“times”数组进行数字排序,但必须确保对“values”数组应用相同的操作。没有递归之类的好处,我能做的最有效的方法是什么?只需使用您最喜欢的排序算法(例如快速排序或合并排序)并使用它对“值”数组进行排序。每当在“值”中交换两个值时,也要在“时间”数组中交换具有相同索引的值 因此,基本上您可以采用任何快速排序算法并修改swap
我有两个相关的数组,“时间”和“值”。它们都包含浮点值。我想对“times”数组进行数字排序,但必须确保对“values”数组应用相同的操作。没有递归之类的好处,我能做的最有效的方法是什么?只需使用您最喜欢的排序算法(例如快速排序或合并排序)并使用它对“值”数组进行排序。每当在“值”中交换两个值时,也要在“时间”数组中交换具有相同索引的值 因此,基本上您可以采用任何快速排序算法并修改swap()操作,以便交换两个数组中的元素。请看下面的示例。这是执行合并排序的非递归方式。这里介绍的版本使用函数调用,但是可以很容易地内联 就像martinus说的,每次在一个数组中更改一个值时,在并行数组中执行完全相同的操作 这是一个稳定的非递归mergesort的类似C的版本,它不进行函数调用,也不使用递归
const int arrayLength = 40;
float times_array[arrayLength];
float values_array[arrayLength];
// Fill the two arrays....
// Allocate two buffers
float times_buffer[arrayLength];
float values_buffer[arrayLength];
int blockSize = 1;
while (blockSize <= arrayLength)
{
int i = 0;
while (i < arrayLength-blockSize)
{
int begin1 = i;
int end1 = begin1 + blockSize;
int begin2 = end1;
int end2 = begin2 + blockSize;
int bufferIndex = begin1;
while (begin1 < end1 && begin2 < end2)
{
if ( values_array[begin1] > times_array[begin2] )
{
times_buffer[bufferIndex] = times_array[begin2];
values_buffer[bufferIndex++] = values_array[begin2++];
}
else
{
times_buffer[bufferIndex] = times_array[begin1];
values_buffer[bufferIndex++] = values_array[begin1++];
}
}
while ( begin1 < end1 )
{
times_buffer[bufferIndex] = times_array[begin1];
values_buffer[bufferIndex++] = values_array[begin1++];
}
while ( begin2 < end2 )
{
times_buffer[bufferIndex] = times_array[begin2];
values_buffer[bufferIndex++] = values_array[begin2++];
}
for (int k = i; k < i + 2 * blockSize; ++k)
{
times_array[k] = times_buffer[k];
values_array[k] = values_buffer[k];
}
i += 2 * blockSize;
}
blockSize *= 2;
}
const int arraylelength=40;
浮点时间_数组[arrayLength];
浮点值_数组[arrayLength];
//填充两个数组。。。。
//分配两个缓冲区
浮动时间_缓冲区[排列长度];
浮点值_缓冲区[arrayLength];
int blockSize=1;
while(块大小乘以数组[begin2])
{
times_buffer[bufferIndex]=times_数组[begin2];
值\缓冲区[bufferIndex++]=值\数组[begin2++];
}
其他的
{
times_buffer[bufferIndex]=times_数组[begin1];
值\缓冲区[bufferIndex++]=值\数组[begin1++];
}
}
while(begin1
您可以维护索引表并对索引表进行排序。
这样你就不必担心时间和价值观的一致性
无论何时需要排序值,都可以在排序索引上查找
如果将来您决定有第三个值,排序代码将不需要任何更改
下面是C#中的一个示例,但适应您的脚本语言应该不难:
static void Main() {
var r = new Random();
// initialize random data
var index = new int[10]; // the index table
var times = new double[10]; // times
var values = new double[10]; // values
for (int i = 0; i < 10; i++) {
index[i] = i;
times[i] = r.NextDouble();
values[i] = r.NextDouble();
}
// a naive bubble sort
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++)
// compare time value at current index
if (times[index[i]] < times[index[j]]) {
// swap index value (times and values remain unchanged)
var temp = index[i];
index[i] = index[j];
index[j] = temp;
}
// check if the result is correct
for (int i = 0; i < 10; i++)
Console.WriteLine(times[index[i]]);
Console.ReadKey();
}
static void Main(){
var r=新的随机变量();
//初始化随机数据
var index=new int[10];//索引表
var times=新的双精度[10];//次
var values=新的双精度[10];//值
对于(int i=0;i<10;i++){
指数[i]=i;
乘以[i]=r.NextDouble();
值[i]=r.NextDouble();
}
//天真的泡沫
对于(int i=0;i<10;i++)
对于(int j=0;j<10;j++)
//比较当前索引的时间值
if(倍[指数[i]]<倍[指数[j]]){
//交换索引值(时间和值保持不变)
var temp=指数[i];
指数[i]=指数[j];
指数[j]=温度;
}
//检查结果是否正确
对于(int i=0;i<10;i++)
Console.WriteLine(times[index[i]]);
Console.ReadKey();
}
注意:我在那里使用了一个天真的气泡排序,注意。在您的例子中,插入排序可能是一个很好的选择。因为您不需要复杂的递归。我不建议您编写自己的排序例程,因为作为Java语言的一部分提供的排序例程经过了很好的优化 解决这个问题的方法是将java.util.Arrays类中的代码复制到您自己的类中,即org.mydomain.util.Arrays。并添加一些注释,告诉自己不要使用该类,除非您必须具有要添加的附加功能。Arrays类相当稳定,因此这比看起来的要不太理想,但仍然不太理想。但是,您需要更改的方法是私有的,因此您没有真正的选择 然后,您需要创建一个如下的界面:
公共静态接口SwapHook{
无效交换(整数a,整数b);
}
然后需要将其添加到将要使用的排序方法中,以及在排序过程中调用的每个从属方法中,这些方法交换主数组中的元素。您可以安排修改后的排序例程调用钩子,然后可以实现SortHook接口,以在任何辅助(例如并行)数组中实现所需的行为
嗯。
他可能想内联swap(),因为他使用的语言不允许用户定义函数。