Tôi có quy trình sau đây có nghĩa là phát hiện các chu kỳ trong đồ thị vô hướng lấy cạnh (cạnh đơn) và bộ cạnh (cạnh). Có hai đối số nữa, left_set (có nghĩa là lưu trữ các cạnh cần thiết để được chuyển vào các cuộc truy tìm) và tuần hoàn (là giá trị boolean cuối cùng xác định xem biểu đồ có theo chu kỳ hay không)Quy trình phát hiện chu trình đệ quy MySQL
Vì lý do nào đó không hoạt động quá khứ đệ quy đầu đây là mã với ý kiến giải thích chi tiết:.
các chức năng sau được thực hiện bởi ME IN MYSQL (để tránh nhầm lẫn):
-concat_set(): trả về ghép hai bộ kế toán cho vị trí không đúng chỗ ',' trong trường hợp tập hợp trống
-remove_first(): loại bỏ các thành viên đầu tiên từ thiết
-get_left_node()/get_right_node: trả về các nút của các cạnh, các dấu phân cách giữa các cạnh là ':' nên một cạnh trông như thế này '12: 15'
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
Tôi sẽ chỉ xả bỏ sự đệ quy vào vòng lặp. Nó có thể làm cho mã một chút xấu xí hơn, nhưng nó đã khá xấu xí. – siride