私は、エッジ(シングルエッジ)とエッジセット(エッジセット)を取る無向グラフのサイクルを検出するための次の手順があります。さらに2つの引数、left_set(再帰に渡すために必要な辺を格納することを意図している)と巡回(最終的にグラフが巡回したかどうかを決定するブール値です)。MySQL再帰的サイクル検出手順
何らかの理由で、最初の再帰を超えて動作しません。ここでは詳細を説明するコメントとコードは次のとおりです。
次の関数が(混乱を避けるために)MySQLでME BY実装されました:
-concat_set():返します置き換えられた2つのセットの連結 '、'空のセットの場合
-remove_first():これエッジこの'12のようになります「」:15' 、エッジ間の区切り文字であるエッジノードを戻します。設定
-get_left_node()/ get_right_nodeから最初のメンバーを削除
CREATE PROCEDURE `is_cyclic`(
IN `singleedge` VARCHAR(15),
IN `edgeset` VARCHAR(1024),
IN 'left_set' VARCHAR(512),
OUT `cyclic` BOOLEAN)
BEGIN
DECLARE se_left VARCHAR(5);
DECLARE es_left VARCHAR(5);
DECLARE se_right VARCHAR(5);
DECLARE es_right VARCHAR(5);
Call get_left_node(singleedge, se_left);
Call get_left_node(SUBSTRING_INDEX(edgeset, ',', 1), es_left);
Call get_right_node(singleedge, se_right);
Call get_right_node(SUBSTRING_INDEX(edgeset, ',', 1), es_right);
--is edgeset emptY?
IF LENGTH(edgeset)= 0 AND LENGTH(left_set) = 0 THEN
BEGIN
SET cyclic= false;
END;
--are singeeledge and first edge in edgeset the same?
ELSEIF ((se_left = es_left
OR se_left= es_right)
AND(se_right = es_left
OR se_right = es_right)) THEN
BEGIN
set cyclic= true;
END;
--do singleedge and first edge in edgeset share any vertices?
ELSEIF se_left = es_left
OR se_left= es_right
OR se_right = es_left
OR se_right = es_right
THEN
--check for all possiblities
BEGIN
--if left vertex of singleedge and left vertex of current edge in front of edgeset are the same
IF se_left=es_left THEN
BEGIN
--test if the edge of combined uncommon vertices (forming concat(se_right,':',es_right)) exists in the remaining edgeset concatanated with the left_set
CALL is_cyclic(concat(se_right,':',es_right),concat_set(left_set,remove_first(edgeset)), '', cyclic);
--if the recursion returns cyclic=false, then remove the considered edge from edgeset and continue trying to match the original singleedge with the rest of edgeset
IF cyclic=false THEN
CALL is_cyclic(singleedge, remove_first(edgeset), left_set, cyclic);
END IF;
END;
ELSEIF se_left= es_right THEN
BEGIN
CALL is_cyclic(concat(se_right,':',es_left), concat_set(left_set, remove_first(edgeset)), '', cyclic);
IF cyclic=false THEN
CALL is_cyclic(singleedge, remove_first(edgeset), left_set, cyclic);
END IF;
END;
ELSEIF se_right=es_left THEN
BEGIN
CALL is_cyclic(concat(se_left,':',es_right), concat_set(left_set, remove_first(edgeset)), '', cyclic);
IF cyclic=false THEN
CALL is_cyclic(singleedge, remove_first(edgeset), left_set, cyclic);
END IF;
END;
ELSE
BEGIN
CALL is_cyclic(concat(se_left,':',es_left), concat_set(left_set, remove_first(edgeset)), '', cyclic);
IF cyclic=false THEN
CALL is_cyclic(singleedge, remove_first(edgeset), left_set, cyclic);
END IF;
END;
END IF;
END;
ELSE
BEGIN
--if the current edge being considered from the edgeset does not contain any vertex in common with singleedge, set it aside into left_set and call is_cyclic recurisvely with the edge removed
SET left_set = concat_set(left_set, SUBSTRING_INDEX(edgeset, ',', 1));
CALL is_cyclic(singleedge, remove_first(edgeset), left_set, cyclic);
END;
END IF;
END
ループへの再帰を巻き戻すだけです。コードが少し醜いかもしれませんが、それはすでにかなり醜いです。 – siride