database.sarang.net
UserID
Passwd
Database
DBMS
MySQL
PostgreSQL
Firebird
ㆍOracle
Informix
Sybase
MS-SQL
DB2
Cache
CUBRID
LDAP
ALTIBASE
Tibero
DB 문서들
스터디
Community
공지사항
자유게시판
구인|구직
DSN 갤러리
도움주신분들
Admin
운영게시판
최근게시물
Oracle Q&A 40816 게시물 읽기
No. 40816
쿼리퀴즈입니다. SQL로 leaf node가 n개인 모든 이진 트리 구조를 구하기
작성자
김흥수(protokhs)
작성일
2015-06-03 13:11ⓒ
2015-06-03 13:40ⓜ
조회수
9,462

leaf node가 n개인 이진 트리를 구하는 것이다.

예를 들어보자

leaf node가 하나인또는 둘인 이진 트리는 한가지 밖에 없다.

아래는 둘인 경우

 

 트리번호

 노드번호

 부모노드

 순서

 노드값

 1

 1

 

 1

 

 1

 2

 1

 1

 1

 1

 3

 1

 2

 2

 

이런 형태가 되고

수식 형태로 표현하면 (1+2) 라고 볼 수 있다.

 

leaf node가 세개 인 경우는 두가지가 있는데

 

트리번호

 노드번호

 부모노드

 순서

 노드값

 1

 1

 

 1

 

 1

 2

 1

 1

 1

 1

 3

 1

 2

 

 1

 4

 3

 1

 2

 1

 5

 3

 2

 3

 2

 1

 

 1

 

 2

 2

 1

 1

 

 2

 3

 2

 1

 1

 2

 4

 2

 2

 2

 2

 5

 1

 2

 3

 

이런 형태가 된다.

수식형태로 표현하면 (1+(2+3)) 과 ((1+2)+3) 이라고 볼 수 있다.

임의의 숫자를 받아서 leaf-node가 해당 숫자만큼이 되는 모든 이진 트리의 구조를 구하는 것이 문제이다.

답은 두가지 형태로 출력하여도 되는데

한가지는 트리번호,노드번호,부모노드,순서,노드값을 컬럼으로 갖는 위와 같은 형태로 출력하되 노드번호와 부모노드는 위와같이 숫자가 아니어도 상관없다.

두번째 방식은 수식형태로 출력하는 것이다.

즉 숫자가 5라면 다음과 같이 출력하면 된다.

1 + ( 2 + ( 3 + ( 4 + 5 ) ) )

1 + ( 2 + ( ( 3 + 4 ) + 5 ) )

1 + ( ( 2 + 3 ) + ( 4 + 5 ) )

1 + ( ( 2 + ( 3 + 4 ) ) + 5 )

1 + ( ( ( 2 + 3 ) + 4 ) + 5 )

( 1 + 2 ) + ( 3 + ( 4 + 5 ) )

( 1 + 2 ) + ( ( 3 + 4 ) + 5 )

( 1 + ( 2 + 3 ) ) + ( 4 + 5 )

( ( 1 + 2 ) + 3 ) + ( 4 + 5 )

( 1 + ( 2 + ( 3 + 4 ) ) ) + 5

( 1 + ( ( 2 + 3 ) + 4 ) ) + 5

( ( 1 + 2 ) + ( 3 + 4 ) ) + 5

( ( 1 + ( 2 + 3 ) ) + 4 ) + 5

( ( ( 1 + 2 ) + 3 ) + 4 ) + 5

 

 

이 글에 대한 댓글이 총 1건 있습니다.

 제가 생각한 답은 

 

with base_data as

(

    select

        listagg(level,',') within group ( order by level ) v

    from    dual

    connect by

        level <= 4

)

, base_recur ( v , vs ,cnt) as

(

    select

        a.v

        , a.v || '@1@ '||'@1' vs

        ,0

    from    base_data a

    union all

    select

        a.v

        ,replace(a.vs,regexp_substr(b.column_value,'[^$]+',1,2),replace(regexp_substr(b.column_value,'[^$]+',1,2),',','~')) || '#'||

        substr(regexp_substr(regexp_substr(b.column_value,'[^$]+',1,2),'[^@]+',1,1),1,instr(regexp_substr(regexp_substr(b.column_value,'[^$]+',1,2),'[^@]+',1,1),',',1,to_number(regexp_substr(b.column_value,'[^$]+',1,1))) - 1) || '@' ||

        (a.cnt * 2 + 2 ) ||'@'||

        regexp_substr(regexp_substr(b.column_value,'[^$]+',1,2),'[^@]+',1,2) ||'@1'||'#'||

        substr(regexp_substr(regexp_substr(b.column_value,'[^$]+',1,2),'[^@]+',1,1),1 + instr(regexp_substr(regexp_substr(b.column_value,'[^$]+',1,2),'[^@]+',1,1),',',1,to_number(regexp_substr(b.column_value,'[^$]+',1,1)))) ||'@' ||

        (a.cnt * 2 + 3 ) ||'@' ||

        regexp_substr(regexp_substr(b.column_value,'[^$]+',1,2),'[^@]+',1,2) ||'@2'

        ,cnt + 1

    from    base_recur a

            , table(

                select

                    collect(level ||'$'||column_value)

                from

                    table(

                        select

                            collect(column_value)

                        from

                            table(

                                select

                                    collect(regexp_substr(a.vs,'[^#]+',1,level))

                                from    dual

                                connect by

                                    level <= regexp_count(a.vs,'[^#]+')

                            )

                        where   regexp_count(column_value,'[,]+') > 0

                        and     rownum < 2

                    )

                connect by

                    level <= regexp_count(regexp_substr(column_value , '[^@]+',1,1),'[,]+')

            ) b

    where   cnt < 100

)

, base_make as

(

    select

        a.v

        ,a.vs

        ,rownum grp

    from    base_recur a

    where   instr(a.vs ,',') = 0

)

    select

        a.grp 산식번호

        ,regexp_substr(b.column_value,'[^@]+',1,2) 노드번호

        ,trim(regexp_substr(b.column_value,'[^@]+',1,3)) 부모노드

        ,to_number(regexp_substr(b.column_value,'[^@]+',1,4)) 순서

        ,to_number(case when instr(regexp_substr(b.column_value,'[^@]+',1,1),'~') > 0 then null else regexp_substr(b.column_value,'[^@]+',1,1) end) 노드값

        ,case when instr(regexp_substr(b.column_value,'[^@]+',1,1),'~') > 0 then '+' else null end 연산자

    from    base_make a

            , table ( select collect (regexp_substr(a.vs,'[^#]+',1,level)) from dual connect by level <= regexp_count(a.vs,'[^#]+',1)) b

/

 

자세한 설명은

 

김흥수(protokhs)님이 2015-06-10 15:53에 작성한 댓글입니다.
[Top]
No.
제목
작성자
작성일
조회
40819숫자구간으로 조회하는 정규식 질의 [1]
슈렉
2015-06-05
7446
40818recursive-with의 이상한 오류에 대하여 문의드립니다.
김흥수
2015-06-04
7769
40817쿼리 퀴즈입니다. SQL로 카운트다운 문제 풀기 [1]
김흥수
2015-06-04
10039
40816쿼리퀴즈입니다. SQL로 leaf node가 n개인 모든 이진 트리 구조를 구하기 [1]
김흥수
2015-06-03
9462
40815쿼리 정렬 질문 [3]
화생방
2015-06-03
7340
40814PK의 성능차이 문의드립니다. [1]
궁금
2015-06-02
8660
40813UPDATE 쿼리인데 속도 문제 [2]
최인수
2015-06-02
7848
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.029초, 이곳 서비스는
	PostgreSQL v16.4로 자료를 관리합니다