2012-12-02 43 views
5

我有以下程序,旨在檢測無向圖中的週期,其中包含邊(單邊)和邊集(邊集)。還有兩個參數:left_set(意思是存儲必須傳遞到遞歸中的邊)和循環(這是一個布爾值,最終確定圖是否是循環的)MySQL遞歸循環檢測程序

由於某些原因,不過去的第一遞歸在這裏工作是解釋細節的註釋代碼:

以下功能實施了本人在MYSQL(以避免混淆):

-concat_set():返回兩套的連接計算錯位','在空集的情況下

-remove_first():刪除從設置

-get_left_node()/ get_right_node第一構件:返回邊緣的節點,所述邊緣之間的分隔符是「:」這樣的邊緣看起來像這樣'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 
+1

我只是將遞歸放到一個循環中。它可能會使代碼變得有點醜陋,但它已經非常難看了。 – siride

回答

2

嘗試重置這個MySQL變量:max_sp_recursion_depth,thread_stack

SET SESSION max_sp_recursion_depth = 10; 
SET SESSION thread_stack = 250000; 

上面的命令執行調用你的程序之後。連續執行兩個語句。 根據您的要求增加thread_stack變量的大小。

+0

這實際上工作,我以前像這樣設置遞歸深度:'SET GLOBAL max_sp_recursion_depth = 150; 「兩者有什麼區別?在檢查較大集合上的循環時,我也會得到以下錯誤:'#1436 - 線程堆棧溢出'我應該手動指定一個更大的堆棧還是更好地修復代碼並防止出現這種情況? – Mike

+0

全局關鍵字全局重置變量意味着重置爲150,直到你的MySQL服務重新啓動。並且您不必在全局範圍內重置此變量,因此,您可以在每個會話中重置該變量。 –

+0

我從來沒有得到我發佈的代碼,沒有拋出'Thread stack overrun'錯誤。 – Mike