2014-09-05 4 views
1

У меня есть небольшая головоломка, которая дает мне головные боли и должна быть довольно приятной для решения.сортировка массива и получение индексов в Delphi

У меня есть набор массивов

arrayX : array of real; 
arrayY : array of real; 

, которые представляют ряд точек х, у такие, что (arrayX [0], arrayY [0]) представляет собой точку. Теперь я хочу сортировать эти массивы относительно X, и я думаю, что путь должен состоять в том, чтобы получить список отсортированных индексов с помощью arrayX и применить это к обоим массивам, и здесь возникает моя проблема:

напишите функцию, которая дает мне отсортированные индексы (возрастание) массива X, предпочтительно в массиве целых чисел? ArrayX может содержать повторяющиеся значения

+1

Почему бы не использовать массив или RealPoint? 'type TRealPoint = Запись x: Двойной; y: Двойной; Конец; aArray = Array of TRealPoint; ' – bummi

+0

Фактическая проблема была упрощена, чтобы объяснить, что я пытаюсь сделать, и на самом деле представляет собой большое количество массивов, которые являются частью еще большей структуры, которая потребует большой работы перепишите так, как вы предлагаете ура для устаревшего кода, который слишком сильно опасен для перезаписи –

ответ

1

Я думаю, что я понял, как это можно сделать: 1) сделать временный массив, который является копией входного 2) найти минимальное значение временного массива 3) хранить индекс минимального значения 4) установить минимальное значение NaN во временном массиве 5) повторять 2-5 до тех пор, временный массив больше не имеет номера

Function indexedSort(inputArray : array of real) : array of integer; 
var 
    i,j : integer; 
    n : integer; 
    minVal : real; 
    tempArray : TArrayOfReal; 
begin 
    n := length(inputArray); 
    setLength(result,n); 
    tempArray := copy(inputArray,0,n); 
    for i:= 0 to n-1 do begin 
    for j := 0 to n-1 do begin 
     if not(IsNan(tempArray[j])) then begin //find any non-NaN value for minimum 
     minVal := tempArray[j]; 
     break; 
     end; 
    end; 
    for j:=0 to n-1 do begin //find actual min val 
     if not(isNan(tempArray[j])) then begin 
     if tempArray[j] <= minVal then begin 
      minVal := tempArray[j]; 
      result[i] := j; 
     end; 
     end; 
    end; 
    tempArray[result[i]] := NaN; 
    end; 
end; 
+0

Это отличное решение. Не в последнюю очередь потому, что сортировка неэффективна, O (N ** 2). Он также исключает значения сортировки, которые могут содержать NaN. И в более общем плане это может быть применимо только к типам, которые допускают часовые. Отдельный массив логических значений, чтобы отметить, что значение было обработано, обойдется всем этим. Тем не менее, поиск косвенности является более чистым. –

9

Я предполагаю, что у вас уже есть возможность сортировки в вашем коде, и я не буду пытаться объяснить, как сортировать здесь. Для этой цели RTL предоставляет TArray.Sort<T>.

Вместо сортировки значений, индексы сортировки. Добавьте уровень косвенности.

  1. Создайте массив целых чисел, Indices, содержащий индексы 0, 1, ..., N-1.
  2. Сортировка этого массива целых чисел.
  3. При сравнении двух значений L и R из массива индексов вместо сравнения L и R сравните X[L] и X[R].

Таким образом, чтобы расширить свое присутствие на конечной точке, стандартную функцию сравнения при сортировке чисел выглядит следующим образом:

function Compare(L, R: Integer): Integer; 
begin 
    if L<R then 
    Result := -1 
    else if L>R then 
    Result := 1 
    else 
    Result := 0; 
end; 

Но вместо этого, вы применяете косвенность на данный момент:

function Compare(L, R: Integer): Integer; 
begin 
    if X[L]<X[R] then 
    Result := -1 
    else if X[L]>X[R] then 
    Result := 1 
    else 
    Result := 0; 
end; 

В конце этого процесса у вас есть индексы, которые сообщают вам порядок очков. Я й точка:

X[Indices[i]], Y[Indices[i]] 

Этот метод известен как непрямой сортировки.


Проблема, которую вы представляете, предполагает, что вы, возможно, не правильно определили свои структуры данных.Вместо двух отдельных массивов, один, содержащие координаты X, и один, содержащий Y координаты, казалось бы, более целесообразно хранить один массив точек:

type 
    TPoint = record 
    X: Real; 
    Y: Real; 
    end; 

var 
    Points: array of TPoint; 

Теперь вы можете сортировать Points при заказе на X значений , но обмениваясь целыми точками. Когда вы представляете данные таким образом, нет никакой возможности для смещения координат. А координата X никогда не может быть отделена от соответствующей координаты Y.

+0

Очень полезный ответ. Я буду учитывать это Я согласен с тем, что дизайн испорчен и что структура записей будет служить мне лучше. Увы, структура намного больше, чем я позволяю здесь, и многие функции зависят от текущего дизайна (не все ли мы любим проекты, которые мы берем с предыдущих сотрудников?), Что делает переписывание неосуществимым. Иногда вы просто нужно держать нос и делать все возможное –

+0

Не должно быть проблем, чтобы получить «массив реальных» из 'массива TPoint':' function arrayX (Points: TPoints): array of real; 'не нарушать ваши зависимостей до тех пор, пока вы не реструктурируете весь источник. –

+0

@user Я понимаю, но я чувствовал себя вынужденным сделать вывод о полноте –

Смежные вопросы