求助!求解子结点的难题!

[复制链接]
查看11 | 回复9 | 2012-5-21 10:19:41 | 显示全部楼层 |阅读模式
本帖最后由 201212311209 于 2015-12-11 09:19 编辑

create table tmp_replacement(node varchar2(20),child varchar2(20));
insert into tmp_replacement values('10301875','10301871');
insert into tmp_replacement values('10301875','10405557');
insert into tmp_replacement values('10301871','10301875');
insert into tmp_replacement values('10301871','10301877');
insert into tmp_replacement values('10301871','10301879');
insert into tmp_replacement values('10301871','10301883');
insert into tmp_replacement values('10301871','10301905');
insert into tmp_replacement values('1030435df','10r435ed');
insert into tmp_replacement values('10r435ed','01rer435e');
insert into tmp_replacement values('435435ed','01rer435e');
insert into tmp_replacement values('87434','86665454');
commit;
node和child是对等的,即可以互换.如:10301875 10301871 可以换为10301871 10301875
计算出来的结果是:
10301871,10301875,10301877,10301879,10301883,10301905,10405557
1030435df,10r435ed,01rer435e,435435ed
87434,86665454
一共三条,结果不必排序
求高效的方法!谢谢!
回复

使用道具 举报

千问 | 2012-5-21 10:19:41 | 显示全部楼层
请把关系解释得更明白些
回复

使用道具 举报

千问 | 2012-5-21 10:19:41 | 显示全部楼层
估计是找团伙算法:
DECLARE
TYPE t_str IS TABLE OF VARCHAR2(1000) INDEX BY tmp_replacement.child%TYPE;
parents t_str;
TYPE t_num IS TABLE OF NUMBER INDEX BY tmp_replacement.child%TYPE;
ranks t_num;
TYPE t_result IS TABLE OF tmp_replacement%ROWTYPE INDEX BY PLS_INTEGER;
v_result t_result;
parentX tmp_replacement.node%TYPE;
parentY tmp_replacement.node%TYPE;
rankX int;
rankY int;
last_child tmp_replacement.child%TYPE;
v_output t_str;

vstr tmp_replacement.node%TYPE;
FUNCTION find_parent(p_current IN tmp_replacement.node%TYPE)
RETURN tmp_replacement.node%TYPE
AS
BEGIN
IF parents(p_current)p_current THEN

parents(p_current) :=find_parent(parents(p_current));
END IF;
RETURN parents(p_current);
END find_parent;
BEGIN
SELECT node, child BULK COLLECT INTO v_result
FROM (SELECT LEAST(node,child) node,GREATEST(node, child) child FROM tmp_replacement

UNION SELECT LEAST(node,child),LEAST(node,child) FROM tmp_replacement
);

FOR i IN 1..v_result.COUNT LOOP
parents(v_result(i).node) := v_result(i).node;
ranks(v_result(i).node) := 0;
END LOOP;
last_child :='*';
FOR cur IN (select LEAST(node, child) AS node, GREATEST(node, child) AS child from tmp_replacement

UNION SELECT LEAST(node,child),LEAST(node,child) FROM tmp_replacement

order by 2,1)
LOOP
if cur.childlast_child then
-- find parent for x
parentX := find_parent(cur.node);
rankX := ranks(parentX);
last_child := cur.child;
ELSE
-- find parent for y

parentY := find_parent(cur.node);
rankY := ranks(parentY);

--- union x and y
CASE
WHEN parentX = parentY THEN

continue;
WHEN rankXrankY THEN

parents(parentY) := parentX;
WHEN rankX = rankY THEN

parents(parentY) := parentX;

ranks(parentX) := ranks(parentX)+1;
END CASE;
END IF;
END LOOP;
FOR i IN 1..v_result.COUNT LOOP
v_result(i).node := find_parent(v_result(i).node);
IF v_output.EXISTS(v_result(i).node) THEN
v_output(v_result(i).node):=v_output(v_result(i).node)||','||v_result(i).child;
ELSE
v_output(v_result(i).node):=v_result(i).child;
END IF;

END LOOP;
vstr := v_output.first;
while vstr is not null loop

DBMS_OUTPUT.PUT_LINE(v_output(vstr));

vstr := v_output.next(vstr);
end loop;
END;
/

01rer435e,10r435ed,435435ed,1030435df,10r435ed
10301871,10301875,10301877,10301879,10301883,10301905,10301875,10405557
86665454,87434
PL/SQL procedure successfully completed.

回复

使用道具 举报

千问 | 2012-5-21 10:19:41 | 显示全部楼层
newkid 发表于 2015-12-11 01:06
估计是找团伙算法:
DECLARE

newkid先生,程序比较复杂,本人小白,没看明白,请问这个程序是要两次循环吗?如果源表数据是n,一共要循环n*n次吗?
回复

使用道具 举报

千问 | 2012-5-21 10:19:41 | 显示全部楼层
就是找出表中一个数据可以和哪些数据互换,或者说是团伙,1030435df,10r435ed,01rer435e,435435ed,他们之间都是关联的
回复

使用道具 举报

千问 | 2012-5-21 10:19:41 | 显示全部楼层
不要沉了,谁告诉我这个算法要循环多少次?是N*N吗?
回复

使用道具 举报

千问 | 2012-5-21 10:19:41 | 显示全部楼层
上面用了四个循环,分别有不同用途,你自己可以根据需要修改,比如最后一个输出的地方你可能就用不到。
算法来自这里:
https://zh.wikipedia.org/zh/并查集
回复

使用道具 举报

千问 | 2012-5-21 10:19:41 | 显示全部楼层
newkid 发表于 2015-12-11 22:21
上面用了四个循环,分别有不同用途,你自己可以根据需要修改,比如最后一个输出的地方你可能就用不到。
算 ...

find_parent()这个算法是迭代算法,相当于遍历字符串。如果表的记录有20万条,遍历这样的字符串效果会比较慢,算法的复杂度相当于N*N,不知道我理解的对不对?
回复

使用道具 举报

千问 | 2012-5-21 10:19:41 | 显示全部楼层
"这两种技术可以互补,可以应用到另一个上,每个操作的平均时间仅为O(\alpha (n)),\alpha (n)是n=f(x)=A(x,x)的反函数,并且A是急速增加的阿克曼函数。因为\alpha (n)是其的反函数,\alpha (n)对于可观的巨大n还是小于5。因此,平均运行时间是一个极小的常数。"
find_parent是递归函数,它效率很高,很快就到头了。
20万数据不算多,你为什么不试试看?
回复

使用道具 举报

千问 | 2012-5-21 10:19:41 | 显示全部楼层
感觉就是在找有向图的每个可连通的子图的所有节点。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题

0

回帖

4882万

积分

论坛元老

Rank: 8Rank: 8

积分
48824836
热门排行