Реализация учебника MergeSort в SQL (Postgres) - PullRequest
0 голосов
/ 18 марта 2019

Я пытаюсь реализовать учебник версии Mergesort на SQL и стараюсь не использовать plpgsql.Я просто хочу использовать SQL.Я использую Postgres как свою систему баз данных.Я перепробовал все, но, к сожалению, я не могу продолжить.

Моя функция Mergesort до сих пор выглядит так:

CREATE OR REPLACE FUNCTION mergesort(A double precision[], p integer, r integer)
RETURNS double precision[] AS $$
    SELECT 
        CASE WHEN p < r THEN mergesort(A,p,floor((p+r)/2)::integer) 
             WHEN p < r THEN mergesort(A,floor((p+r)/2)::integer+1,r)
             WHEN p < r THEN merge(A,p,floor((p+r)/2)::integer,r)
             ELSE A
    END;
$$ LANGUAGE SQL;

Я пытаюсь получить что-то вроде этого исполняемого файлаи работает (я знаю, что в моем примере кода CASE не выполняет все три вызова, которые необходимы, я пока не нашел решения и, к сожалению, я не знаю, как назначить результат Mergesort в рекурсивном вызовевернуться к переменной A).

Кто-нибудь знает, как я могу решить эту проблему?

Только для информации: функция слияния уже реализована и выполняется в plpgsql.(Возможно, я попытаюсь переписать его на SQL в следующем шаге).

CREATE FUNCTION merge(A double precision[], p integer, q integer, r integer) 
RETURNS double precision[] AS $$
DECLARE
 n1 integer := q-p+1;
 n2 integer := r-q;
 L double precision[]; 
 Ri double precision[];
 g integer;
 h integer; 
BEGIN
 L = ARRAY[n1+1]; 
 Ri = ARRAY[n2+1];
 FOR i in 1..(n1+1) LOOP
    L[i] = A[p+i-1];
 END LOOP;
 FOR j in 1..n2+1 LOOP
    Ri[j] = A[q+j];
 END LOOP;
 L[n1+1] = 'Infinity';
 Ri[n2+1] = 'Infinity';
 g = 1;
 h = 1;
 FOR k in p..r LOOP
    IF L[g] <= Ri[h] THEN
        A[k] = L[g];
        g = g + 1;
    ELSE
        A[k] = Ri[h];
        h = h + 1; 
    END IF;
 END LOOP;
 RETURN A;
END;
$$ LANGUAGE plpgsql;

1 Ответ

0 голосов
/ 26 марта 2019

Я уже выяснил и хотел поделиться с вами решением.Теперь я выбрал функциональный алгоритм, который легче реализовать в SQL, чем императивный.

Слияние:

CREATE OR REPLACE FUNCTION mergesort(A double precision[]) 
RETURNS double precision[] AS $$
    SELECT 
        CASE WHEN 1 < array_length(A,1) 
              THEN merge(mergesort(A[1:floor((1+array_length(A,1))/2)::integer]),
                         mergesort(A[floor((1+array_length(A,1))/2)::integer+1:array_length(A,1)]),
                         1,
                         1,
                         ARRAY[]::double precision[])
             ELSE A
        END;
$$ LANGUAGE SQL;

Слияние:

CREATE OR REPLACE FUNCTION merge(A1 double precision[],A2 double precision[], i integer, j integer,acc double precision[]) 
RETURNS double precision[] AS $$
    SELECT 
        CASE WHEN (i > array_length(A1,1) and j > array_length(A2,1)) THEN acc
             WHEN i > array_length(A1,1) THEN merge(A1,A2,i,j+1,array_append(acc,A2[j]))
             WHEN j > array_length(A2,1) THEN merge(A1,A2,i+1,j,array_append(acc,A1[i]))
             WHEN A1[i] <  A2[j] THEN merge(A1,A2,i+1,j,array_append(acc, A1[i]))
             WHEN A1[i] >= A2[j] THEN merge(A1,A2,i,j+1,array_append(acc, A2[j]))                
        END;
$$ LANGUAGE SQL;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...