环境:我使用的是专有脚本语言,其中没有用户定义的功能。我有各种循环和基本类型的局部变量,我可以创建和使用它。
我有两个相关的数组,“时间”和“值”。它们都包含浮点值。我想在数字上对“时间”数组进行排序,但必须确保在“values”数组上应用相同的操作。如果没有像递归这样的好处,我能做到这一点最有效的方法是什么?
答案 0 :(得分:5)
您可以维护索引表并改为对索引表进行排序。
这样您就不必担心时间和价值的一致性。
无论何时需要排序值,您都可以查找已排序的索引。
如果您将来确定将会有第三个值,那么排序代码将不需要任何更改。
以下是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();
}
注意:我在那里使用了一个天真的泡泡排序,警告。在您的情况下,插入排序可能是一个很好的候选人。因为你不需要复杂的递归。
答案 1 :(得分:2)
只需使用您喜欢的排序算法(例如Quicksort或Mergesort)并使用它来对“values”数组进行排序。只要在“值”中交换两个值,也可以在“times”数组中使用相同的索引交换值。
所以基本上你可以采用任何快速排序算法并修改swap()操作,以便交换两个数组中的元素。
答案 2 :(得分:2)
看看Bottom-Up mergesort at Algorithmist。这是执行mergesort的非递归方式。那里提供的版本使用函数调用,但可以很容易地内联。
就像马丁努斯所说的那样,每次更改一个数组中的值时,都要在并行数组中执行完全相同的操作。
这是一个类似C的版本的stable-non-recursive mergesort,它不进行任何函数调用,并且不使用递归。
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;
}
答案 3 :(得分:-3)
我不建议编写自己的排序例程,因为作为Java语言的一部分提供的排序例程已经过很好的优化。
我解决这个问题的方法是将java.util.Arrays类中的代码复制到您自己的类中,即org.mydomain.util.Arrays。并添加一些注释,告诉自己不要使用该类,除非您必须具有要添加的其他功能。 Arrays类非常稳定,因此它看起来不那么理想,但它仍然不太理想。但是,您需要更改的方法是私有的,因此您没有真正的选择。
然后,您想要创建一个界面:
public static interface SwapHook {
void swap(int a, int b);
}
You then need to add this to the sort method you're going to use, and to every subordinate method called in the sorting procedure, which swaps elements in your primary array. You arrange for the hook to get called by your modified sorting routine, and you can then implement the SortHook interface to achieve the behaviour you want in any secondary (e.g. parallel) arrays.
HTH.