我有一个爱好项目,关于创建一个存储标识号的树。我曾经使用过数字,存储在节点,节点可以是0 1 2 3 4 5 6 7 8 9。
创建树后,我想从树中创建列表。但是,我找不到一个算法来管理我的目标。
我想要的是什么:
"recompose tree" will return list of numbers. For below tree it should be
[ 2, 21, 243, 245, 246, 78, 789 ]
Root
/ \
2* 7
/ \ \
1* 4 8*
/ \ \ \
3* 5* 6* 9*
my data type : data ID x = ID ( ( x, Mark ), [ ID x ] )
data Mark = Marked | Unmarked
EDIT:
for convenience : * shows it is marked
I have stored digit as char, actually not 1,
it is stored as'1'
你有建议我怎么做吗? (建议被认为是算法)
答案 0 :(得分:3)
怎么样?
recompose :: Num a => ID a -> [a]
recompose = go 0
where
go acc (ID ((n, Marked), ids)) =
let acc' = 10 * acc + n
in acc' : concatMap (go acc') ids
go acc (ID ((n, Unmarked), ids)) =
let acc' = 10 * acc + n
in concatMap (go acc') ids
也就是说,我们遍历树,同时累积从根到节点的路径的值。在每个节点,我们通过将路径的值乘以10并将节点的值与其相加来更新累加器。遍历生成标记节点的所有累加器值的列表:因此,在标记节点处,我们将累加器值添加到列表中,对于未标记的节点,我们只传播我们为节点的子节点收集的列表。
我们如何计算节点子节点的列表?我们通过将它映射到子列表上来递归调用遍历函数(go
)给所有子节点。这给了我们一个列表,我们连接这些列表以获得单个列表。 (concatMap f xs
只是concat (map f xs))
或concat . map f
。)
在属性 - 语法术语中:累加器用作继承属性,而返回的列表是合成属性。
作为一种改进,我们可以引入一个辅助函数isMarked
,
isMarked :: Mark -> Bool
isMarked Marked = True
isMarked Unmarked = False
这样我们就可以简明扼要地写了
recompose :: Num a => ID a -> [a]
recompose = go 0
where
go acc (ID ((n, m), ids)) =
let acc' = 10 * acc + n
prefix = if isMarked m then (acc' :) else id
in prefix (concatMap (go acc') ids)
答案 1 :(得分:2)
BTW:这甚至可以在sql中完成:
DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path='tmp';
CREATE TABLE the_tree
( id CHAR(1) NOT NULL PRIMARY KEY
, parent_id CHAR(1) REFERENCES the_tree(id)
);
INSERT INTO the_tree(id,parent_id) VALUES
( '@', NULL)
,( '2', '@')
,( '7', '@')
,( '1', '2')
,( '4', '2')
,( '3', '4')
,( '5', '4')
,( '6', '4')
,( '8', '7')
,( '9', '8')
;
WITH RECURSIVE sub AS (
SELECT id, parent_id, ''::text AS path
FROM the_tree t0
WHERE id = '@'
UNION
SELECT t1.id, t1.parent_id, sub.path || t1.id::text
FROM the_tree t1
JOIN sub ON sub.id = t1.parent_id
)
SELECT sub.id,sub.path
FROM sub
ORDER BY path
;
结果:(postgresql)
NOTICE: drop cascades to table tmp.the_tree
DROP SCHEMA
CREATE SCHEMA
SET
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "the_tree_pkey" for table "the_tree"
CREATE TABLE
INSERT 0 10
id | path
----+------
@ |
2 | 2
1 | 21
4 | 24
3 | 243
5 | 245
6 | 246
7 | 7
8 | 78
9 | 789
(10 rows)