VB.NET 알고리즘 구현 - Stack, Queue Data Type

맨땅에 헤딩하면서 플그램을 배웠던 나로서는 좀 머리가 아팠던 부분이었다. 강의시간에는 졸았고 자격증시험에서는 외우기만 했으니 남는것은 없었다.다시 내공을 키우려고 맘먹고 구현해가면서 공부하던 시절 이 부분을 마치고 나서 무척이나 상쾌했던 기억이 있다.

 

 

재귀호출의 건셉 : 코딩라인수를 무척이나 줄여주는 재귀호출에는 무서운 함정이 있는데 잘못하면 무한히 반복되는 루틴이 되어버린다. Stack Overflow를 일으켜서 시스템을 바보로 만들어 버리곤한다. 재귀호출 알고리즘의 적용요건은 문제의 크기가 점점 감소해야 하고 종료조건이 있어야 한다.  간단한 예로 Factorial 의 경우 문제의 크기감소 : N! = N * (N-1)!  종료조건 : 0! = 1 이 있다.

 

예제소스를 실행해서 [VB알고리즘] - [알고리즘1] 메뉴클릭

"재귀호출" 창에서 해당 버튼클릭 (frmRecursion 폼 참조) 하면 내용 확인이 가능하다.

 

 

 

1.실습내용.

 

  1)최대공약수구하기

   재귀호출을 사용하여 최대공약수를 구하는 루틴을 구현한다.

   먼저 두수 u > v 인경우 u와 v의 최대공약수는 u와 u-v의 최대공약수라는 사실에 대해 이해해야한다.

 

  2)Fibonacci 수열

    

      예를들어 Fibonacci(5) = Fibonacci(4) + Fibonacci(3)

      img4.gif

 

 

  3)Tree그리기

     2Way 재귀호출로 Fixed 2진트리, RandomColed 2진트리 그리기

   img3.gif

    pGraphics.DrawLine() 함수를 사용 두점 사이에 선을 긋는다.

 

  

   img2.gif

왠삼각함수 ?  :   

(0, 0)를 기준으로 빗변의길이 r과 각도 Θ를 이용해서 다음점인 (x,y)를 구하기 위해서 sin, cos 함수를 사용한다.

혼돈을 피하기 위해 '빗변'의 길이과 '각도'에 유념하자.

 

 

img1.gif

clsAlg1.DrawFixTree(130, 200, 12, 40, 0.0, myGraphics)

시작점 (X0, Y0) =  (픽처박스의 폭 /2 , 픽처박스의 높이) = (130 픽셀, 200픽셀)

빗변 L0는 40 (0.8%로 감소), 비틀림각 trun0 = 0 (0.5씩증감)

결과적으로 처음으로 비틀리는 (X2, Y2) = (130 - 40 * System.Math.Cos(0.5), 160 - 40 * System.Math.Cos(0.5)) 가 된다.

 

 

 

 

2.최대공약수 구하기

  

  Public Function get_gcd_recur(ByVal u As Integer, ByVal v As Integer) As Integer

        If v = 0 Then

            Return u

        Else

            Return get_gcd_recur(v, u Mod v)

        End If

  End Function

 

 

3.Fibonacci 수열

   'Interger형과 Short형 함수 중복정의 해서 호출시 명시적인 형변환 필요

   'Short 형은 -32,768부터 32,767까지의 부호 있는 16비트(2바이트) 정수를 저장  [VB6에서의 Integer 형(%)]

   'n=23까지 가능

 

    '함수호출

     Dim Sortresult As Short = clsAlg1.Fibonacci(CType(txtFop1.Text, Short))

     lblFresult.Text = Format(Sortresult, "#,###")

 

    Public Function Fibonacci(ByVal n As Short) As Short

        'Short 형은 -32,768부터 32,767까지의 부호 있는 16비트(2바이트) 정수를 저장  [VB6에서의 Integer 형(%)]

        Try

            If n = 1 Or n = 2 Then

                Return 1

            Else

                Return Fibonacci(n - 1) + Fibonacci(n - 2)

            End If

        Catch exp As System.OverflowException

            MessageBox.Show("오버플로 Short 범위 Number : " & n, exp.Source, MessageBoxButtons.OK, MessageBoxIcon.Error)

            Return 0

        Catch exp As System.Exception

            MessageBox.Show(exp.Message, exp.Source, MessageBoxButtons.OK, MessageBoxIcon.Error)

            Return 0

        End Try

    End Function

 

 

 

4.FixedTree그리기

  

   If optFixed.Checked = True Then     '고정Tree

         '시작x좌표, 시작y좌표, 하위가지수Level, 가지길이,꺽임각, 그릴타겟(픽처박스의 Graphics개체를 넘김)

         clsAlg1.DrawFixTree(130, 200, 12, 40, 0.0, myGraphics)

   Else                                'RandomTree

         clsAlg1.DrawRndTree(130, 200, 10, 40, 0.0, myGraphics)

   End If

 

   '반환값이 없는 Sub 프로시저로 선언해 보자.

    Public Sub DrawFixTree(ByVal x As Integer, ByVal y As Integer, ByVal nOrder As Integer, _

                           ByVal nLength As Integer, ByVal dAngle As Double, ByVal pGraphics As Graphics)

        Try

            Dim dx As Integer = Convert.ToInt32(nLength * System.Math.Sin(dAngle))

            Dim dy As Integer = Convert.ToInt32(nLength * System.Math.Cos(dAngle))

            '파라미터로 넘어온 (x, y) 에서 다음좌표로 선을그림   130, 200   130, 200-40

            pGraphics.DrawLine(Pens.Blue, x, y, x - dx, y - dy)

 

            '다음에서 nOrder = 2 값을 변경해 보면서 트리레벨 및 오류가 발생 시 처리를 확인해 보자

            'If nOrder = 2 Then Throw New ApplicationException("오류 만들어보기")

 

            If nOrder > 0 Then    '재귀호출의 종료조건

                '2Way 재귀호출 (즉2진트리) 길이는 0.8로 감소, 0.5배수로 비틀기

                DrawFixTree(x - dx, y - dy, nOrder - 1, Convert.ToInt32(nLength * 0.8), dAngle + 0.5, pGraphics)

                DrawFixTree(x - dx, y - dy, nOrder - 1, Convert.ToInt32(nLength * 0.8), dAngle - 0.5, pGraphics)

            End If

        Catch exp As System.ApplicationException

            Debug.Print("오류발생 : Level -" & nOrder & " 길이 -" & nLength & " 각도  : " & dAngle)

            Exit Sub

        Catch exp As System.Exception

            MessageBox.Show(exp.Message, exp.Source, MessageBoxButtons.OK, MessageBoxIcon.Error)

            Exit Sub

        End Try

    End Sub

 

 

^^ RandomTree는 소스에서 확인하시기 바랍니당.

오늘 실습해볼 내용은 노멀트리의 Level Order운행과 Pre Order운행을 Stack과 Queue를 이용해서 구현해 보는 내용입니다.

제목은 Stack, Queue Data Type 이라고 했지만 구현부분은 List만 계속하니까 지루해서 제외했습니다.  대신 책등에서 마르고 닳도록 나오는 이넘들의 특성에 대해서 몇줄 적고 실제사용은 System.Collections.Stack 과 System.Collections.Queue 를 사용 했습니다.

 

먼저함 돌려보시려면 [VB알고리즘]-[자료구조] 메뉴를 클릭하시고 다음과 같은 화면이 나오면

"폴더선택" -> "일반트리" 버튼클릭 -> "LevelOrder (Queue)" 버튼을 클릭해 보시면 됩니다.

 

 

@보통 반말로 글을 쓰는데 자신에게 말하는거지 글을 보시는 분들에게 말하는 것은 아니니 오해 없으시기 바랍니다.

 

 

 

1.Stack, Queue Data Type

 

Stack이란?

  입구와 출구가 하나이고 한번에 한 아이템만 입출가능한 자료구조

  배열이나 연결리스트로 손쉽게 구현가능

  LIFO (Last In First Out) : 최종 입력된 자료가 가장먼저 인출됨

  Push : 스택에 데이타를 추가함

  Pop : 스택에서 가장 최근에 추가된 데이타를 인출

  Peek : 스택에서 최상단 데이타를 인출하지 않고 조회

  Top : 스택의 최상단 아이템 또는 아이템의 인덱스

 

 

 

Queue란?

경축! 아무것도 안하여 에스천사게임즈가 새로운 모습으로 재오픈 하였습니다.
어린이용이며, 설치가 필요없는 브라우저 게임입니다.
https://s1004games.com

  입구와 출구가 따로 있고 한번에 한 아이템만 입출가능한 자료구조

  FIFO (First In First Out) : 최초로 입력한 자료가 가정먼저 인출됨

  Put : 큐에 데이타를 추가함

  Get : 큐에서 가장 먼저 추가된 데이타를 인출

  Front : 큐에서 가장먼저 추가된 선두 아이템 또는 아이템의 인덱스

  Rear : 큐에서 가장나중에 추가된 꼬리 아이템 또는 인덱스

  Peek : 큐에서 최선두 데이타를 인출하지 않고 조회

 

 

 

 

2.주제

  

Queue 기반 : Level-order 노멀트리운행 구현 : 위에서 아래로 좌에서 우로 트리운행 (직관적)

Stack 기반 : Pre-order 노멀트리 운행 / 포스트오더 노드삭제

 

2.1. 큐를 활용한 Normal트리의 LevelOrder 트리운행

    Private Sub btnLevel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLevel.Click

        lvwTree.Items.Clear()

 

        Dim sysQueue As New System.Collections.Queue

        Dim order As Integer

        Dim tmpNode As NormalNode

 

        'LevelOrderTraverse 시작

        sysQueue.Enqueue(CType(tvwTree.Nodes(0), NormalNode))

        Do While sysQueue.Count > 0

            tmpNode = sysQueue.Dequeue                                                         '큐에서 자료인출

            order = order + 1

            tmpNode.NodeNum = order

            AddToListView(tmpNode.Text, tmpNode.NodeNum, tmpNode.Level)    ' 리스트뷰에 노드명, 운행순서, 레벨표시

            For i As Integer = 0 To tmpNode.Nodes.Count - 1                                ' 자식노드중 좌측에서 좌측노드 순으로 큐에 삽입

                sysQueue.Enqueue(tmpNode.Nodes(i))

            Next

        Loop

    End Sub

 

2.2.  스택을 사용한 Normal트리의 PreOrder 트리운행 (처음 노멀트리를 그린 순서와 동일)

    Private Sub btnStackPre_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStackPre.Click

        lvwTree.Items.Clear()

 

        Dim sysStack As New System.Collections.Stack

        Dim order As Integer

        Dim tmpNode As NormalNode

 

        'PreOrderTraverse 시작

        sysStack.Push(CType(tvwTree.Nodes(0), NormalNode))

        Do While sysStack.Count > 0                                                                 ' 스택내에 자료가 있는동안

            tmpNode = sysStack.Pop

            order = order + 1

            tmpNode.NodeNum = order

            AddToListView(tmpNode.Text, tmpNode.NodeNum, tmpNode.Level)     ' 리스트뷰에 노드명, 운행순서, 레벨표시

            For i As Integer = tmpNode.Nodes.Count - 1 To 0 Step -1                     ' 자식노드중 우측에서 좌측으로 푸시

                sysStack.Push(tmpNode.Nodes(i))

            Next

        Loop

    End Sub

 

2.3. Post Order 방식으로 운행 하면서 노드삭제

    Private Sub btnNRemoveAll_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNRemoveAll.Click

        lvwTree.Items.Clear()

 

        Dim sysStack As New System.Collections.Stack

        Dim order As Integer

        Dim tmpNode As NormalNode

 

        'PreOrderTraverse 시작

        sysStack.Push(CType(tvwTree.Nodes(0), NormalNode))

        Do While sysStack.Count > 0

            tmpNode = sysStack.Peek                                                                     ' 스택에서 인출하지 않고 조회

            If tmpNode.Nodes.Count = 0 Then

                tmpNode = sysStack.Pop                                                                  '  자식노드가 없으면 인출

                order = order + 1

                tmpNode.NodeNum = order

                AddToListView(tmpNode.Text, tmpNode.NodeNum, tmpNode.Level)     ' 리스트뷰에 노드명, 운행순서, 레벨표시

                tmpNode.Remove()                                                                          ' 노드삭제

            Else

                For i As Integer = tmpNode.Nodes.Count - 1 To 0 Step -1                     ' 자식노드중 우측에서 좌측으로 푸시

                    sysStack.Push(tmpNode.Nodes(i))

                Next

            End If

        Loop

    End Sub

 

 

2.3. Normal 트리 그리기 선택한 폴더를 기준으로 PreOrder방식으로 100여 개의 디랙토리 표시

    Private Sub btnNormal_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNormal.Click

        If txtSelectDir.Text = "" Then Exit Sub

        Dim strSelectedDirectory As String = txtSelectDir.Text

        tvwTree.Nodes.Clear()

        tvwTree.NodeCnt = 0

        lvwTree.Items.Clear()

        Try

            Dim dnSelectedDirectory As NormalNode = New NormalNode(1)

            ' 선택한 디랙토리명을 루트로 한다.

            dnSelectedDirectory.Text = strSelectedDirectory

            ' 트리뷰에 재정의된 TreeNode개체 추가

            tvwTree.Nodes.Add(dnSelectedDirectory)

            tvwTree.NodeCnt = 1                   ' 루트노드를 추가했으므로 카운트 증가

            dnSelectedDirectory.Text = dnSelectedDirectory.NodeNum & " " & dnSelectedDirectory.Text

            dnSelectedDirectory.ContextMenuStrip = ContextMenuStrip1

            ' 하위트리를 추가시키고, 하위노드수를 계산함

            SetSubNormalNode(strSelectedDirectory, dnSelectedDirectory)

 

            chkBin.CheckState = CheckState.Unchecked   ' 미채크상태로 : 채크박스의 TreeState = True  

            setMenu()                                  ' 팝업메뉴와 다른버튼제어

            dnSelectedDirectory.Expand()

        Catch exc As Exception

        End Try

    End Sub

 

    ' 하위 디랙토리 노드를 표시한다.

    Public Function SetSubNormalNode(ByVal strDirPath As String, ByRef mNode As NormalNode) As Boolean

        ' 현재 검색하고 있는 폴더를 상태바에 표시한다.

        sbrScan.Text = "Scanning : " + strDirPath

        Try

            ' 전달받은 문자열(폴더명)의 하위폴더를 문자열 배열에 세팅함

            Dim astrSubDirectories As String() = Directory.GetDirectories(strDirPath)

            Dim strSubDirectory As String

            For Each strSubDirectory In astrSubDirectories

                Dim dnSubNode As NormalNode = New NormalNode(tvwTree.NodeCnt + 1)

                ' \를 사용 풀패스에서 폴더명만 남김

                dnSubNode.Text = strSubDirectory.Remove(0, strSubDirectory.LastIndexOf("\") + 1)

                dnSubNode.Text = dnSubNode.NodeNum.ToString & "  " & dnSubNode.Text

                dnSubNode.ContextMenuStrip = ContextMenuStrip1

                mNode.Nodes.Add(dnSubNode)

                tvwTree.NodeCnt = tvwTree.NodeCnt + 1

                If tvwTree.NodeCnt > 100 Then GoTo end_rtn

                ' 재귀호출로 하위폴더를 검색하여 하위노드를 추가한다.

                SetSubNormalNode(strSubDirectory, dnSubNode)

            Next

        Catch exc As Exception

            Return False

        End Try

end_rtn:

        sbrScan.Text = "Node Count > 100"

        Return True

    End Function

 

 

vbalgorithms_20061206-etruelove.zip

[출처] https://m.blog.naver.com/PostView.nhn?blogId=etruelove&logNo=140034468438&proxyReferer=http%3A%2F%2Fwww.google.co.kr%2Furl%3Fsa%3Dt%26rct%3Dj%26q%3D%26esrc%3Ds%26source%3Dweb%26cd%3D1%26ved%3D0ahUKEwiZ67SWhMbZAhXHnpQKHZ7uD_kQFggmMAA%26url%3Dhttp%253A%252F%252Fm.blog.naver.com%252Fetruelove%252F140034468438%26usg%3DAOvVaw3LtVTOoXmteT-5hk99ux5I

 

[출처] http://www.devpia.com/Maeul/Contents/Detail.aspx?BoardID=45&MAEULNO=18&no=253&page=2#

 

본 웹사이트는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
번호 제목 글쓴이 날짜 조회 수
1195 [ 一日30分 인생승리의 학습법] VBA Web Scraping: How Can VBA Be Used To Scrape Website Data? file 졸리운_곰 2024.04.13 3
1194 [ 一日30分 인생승리의 학습법] 윈도우 실행파일 구조(PE파일) file 졸리운_곰 2024.03.31 3
1193 [ 一日30分 인생승리의 학습법] [Analysis] PE(Portable Executable) 파일 포맷 공부 file 졸리운_곰 2024.03.31 3
1192 [ 一日30分 인생승리의 학습법] 성공하는 메타버스의 3가지 조건 file 졸리운_곰 2024.03.30 7
1191 [ 一日30分 인생승리의 학습법] REST, REST API, RESTful 과 HATEOAS file 졸리운_곰 2024.03.10 9
1190 [ 一日30分 인생승리의 학습법] 렌더링 삼형제 CSR, SSR, SSG 이해하기 file 졸리운_곰 2024.03.10 2
1189 [ 一日30分 인생승리의 학습법] 엑셀 VBA에서 셀레니움 사용을 위한 Selenium Basic 설치 file 졸리운_곰 2024.02.23 11
1188 [ 一日30分 인생승리의 학습법]500 Lines or Less Blockcode: A Visual Programming Toolkit : 500줄 이하의 블록코드: 시각적 프로그래밍 툴킷 졸리운_곰 2024.02.12 4
1187 [ 一日30分 인생승리의 학습법] 구글 클라이언트(앱) 아이디를 발급받으려면 어떻게 해야 하나요? 졸리운_곰 2024.01.28 3
1186 [ 一日30分 인생승리의 학습법] 빅뱅 프로젝트를 성공적으로 오픈하기 위한 팁 졸리운_곰 2023.12.27 16
1185 [ 一日30分 인생승리의 학습법]“빅뱅 전환보다 단계적 전환 방식이 이상적 애자일팀과 협업 쉽게 체질 개선을” file 졸리운_곰 2023.12.27 12
1184 [ 一日30分 인생승리의 학습법] Big-bang / phased 접근 file 졸리운_곰 2023.12.27 3
1183 [ 一日30分 인생승리의 학습법] CodeDragon 메뉴 데이터 전환의 개념 이해 - 데이터 전환의 개념, 데이터 전환방식, 데이터 전환방식 및 장단점 비교, 데이터전환 이후 검토해야 할 사항 졸리운_곰 2023.12.27 5
1182 [ 一日30分 인생승리의 학습법] 블록체인과 IPFS를 이용한 안전한 데이터 공유 플랫폼 - 분쟁 해결 시스템 file 졸리운_곰 2023.12.27 6
1181 [ 一日30分 인생승리의 학습법] 블록체인과 IPFS를 이용한 안전한 데이터 공유 플랫폼 - 개념과 리뷰 시스템 file 졸리운_곰 2023.12.27 4
1180 [ 一日30分 인생승리의 학습법] 소켓 CLOSE_WAIT 발생 현상 및 처리 방안 file 졸리운_곰 2023.12.03 7
1179 [ 一日30分 인생승리의 학습법] robots 설정하기 졸리운_곰 2023.12.03 3
1178 [ 一日30分 인생승리의 학습법] A Tutorial and Elementary Trajectory Model for the Differential Steering System of Robot Wheel Actuators : 로봇 휠 액츄에이터의 차동 조향 시스템에 대한 튜토리얼 및 기본 궤적 모델 file 졸리운_곰 2023.11.29 6
1177 [ 一日30分 인생승리의 학습법] Streamline Your MLOps Journey with CodeProject.AI Server : CodeProject.AI 서버로 MLOps 여정을 간소화하세요 file 졸리운_곰 2023.11.25 2
1176 [ 一日30分 인생승리의 학습법] Comparing Self-Hosted AI Servers: A Guide for Developers / : 자체 호스팅 AI 서버 비교: 개발자를 위한 가이드 file 졸리운_곰 2023.11.25 10
대표 김성준 주소 : 경기 용인 분당수지 U타워 등록번호 : 142-07-27414
통신판매업 신고 : 제2012-용인수지-0185호 출판업 신고 : 수지구청 제 123호 개인정보보호최고책임자 : 김성준 sjkim70@stechstar.com
대표전화 : 010-4589-2193 [fax] 02-6280-1294 COPYRIGHT(C) stechstar.com ALL RIGHTS RESERVED