How to properly label branches of a tree in a depth first search

后端 未结 1 995
忘掉有多难
忘掉有多难 2021-02-06 07:35

I have a tree with a structure like this:

     __2__3__4
    /   \\__5__6
0__1___7/__8__9
   \\\\
    \\\\__10__11__12
     \\__  __  __
        13  14  15
         


        
1条回答
  •  时光说笑
    2021-02-06 07:52

    Okay, I'll try to refrain from tweaking this answer again. It's just been so fun learning about the sort order of VarBinary, finding the POWER function, CTEs beating on one another, ... .

    Are you looking for anything like:

    declare @Nodes as Table ( NodeId Int Identity(0,1), Name VarChar(10) )
    declare @Relations as Table ( ParentNodeId Int, ChildNodeId Int, SiblingOrder Int )
    insert into @Nodes ( Name ) values
    --  ( '0' ), ( '1' ), ( '2' ), ( '3' ), ( '4' ), ( '5' ), ( '6' ), ( '7' ), ( '8' ),
    --  ( '9' ), ( '10' ), ( '11' ), ( '12' ), ( '13' ), ( '14' ), ( '15' )
      ( 'zero' ), ( 'one' ), ( 'two' ), ( 'three' ), ( 'four' ), ( 'five' ), ( 'six' ), ( 'seven' ), ( 'eight' ),
      ( 'nine' ), ( 'ten' ), ( 'eleven' ), ( 'twelve' ), ( 'thirteen' ), ( 'fourteen' ), ( 'fifteen' )
    
    insert into @Relations ( ParentNodeId, ChildNodeId, SiblingOrder ) values
      ( 0, 1, 0 ),
      ( 1, 2, 0 ), ( 1, 7, 1 ), ( 1, 10, 2 ), ( 1, 13, 3 ),
      ( 2, 3, 0 ), ( 2, 5, 1 ),
      ( 3, 4, 0 ),
      ( 5, 6, 0 ),
      ( 7, 5, 0 ), ( 7, 8, 1 ),
      ( 8, 9, 0 ),
      ( 10, 11, 0 ),
      ( 11, 12, 0 ),
      ( 13, 14, 0 ),
      ( 14, 15, 0 )
    
    declare @MaxSiblings as BigInt = 100
    ; with
    DiGraph ( NodeId, Name, Depth, ParentNodeId, Path, ForkIndex, DepthFirstOrder )
    as (
      -- Start with the root node(s).
      select NodeId, Name, 0, Cast( NULL as Int ), Cast( Name as VarChar(1024) ),
        Cast( 0 as BigInt ), Cast( Right( '00' + Cast( 0 as VarChar(2) ), 2 ) as VarChar(128) )
        from @Nodes
        where not exists ( select 42 from @Relations where ChildNodeId = NodeId )
      union all
      -- Add children one generation at a time.
      select R.ChildNodeId, N.Name, DG.Depth + 1, R.ParentNodeId, Cast( DG.Path + ' > ' + N.Name as VarChar(1024) ),
        DG.ForkIndex + R.SiblingOrder * Power( @MaxSiblings, DG.Depth - 1 ),
        Cast( DG.DepthFirstOrder + Right( '00' + Cast( R.SiblingOrder as VarChar(2) ), 2 ) as VarChar(128) )
        from @Relations as R inner join
          DiGraph as DG on DG.NodeId = R.ParentNodeId inner join
          @Nodes as N on N.NodeId = R.ChildNodeId inner join
          @Nodes as Parent on Parent.NodeId = R.ParentNodeId
      ),
    
    DiGraphSorted ( NodeId, Name, Depth, ParentNodeId, Path, ForkIndex, DepthFirstOrder, RowNumber )
    as ( select *, Row_Number() over ( order by DepthFirstOrder ) as 'RowNumber' from DiGraph )
    
    select ParentNodeId, NodeId, Depth, Path,
      ( select Count(*) from DiGraphSorted as L
        left outer join DiGraphSorted as R on R.RowNumber = L.RowNumber - 1 where
        R.RowNumber < DG.RowNumber and L.ForkIndex <> R.ForkIndex ) as 'ForkNumber' -- , '', *
      from DiGraphSorted as DG
      order by RowNumber
    

    0 讨论(0)
提交回复
热议问题