728x90

선형 자료 구조(연결 리스트, 스택, 큐 등): 순차적으로 요소에 접근

트리 자료구조는 노드들을 방문하기 위해 다른 방식을 사용해야 함

 

트리 순회(Tree Traversal): 트리의 모든 노드들을 방문하는 과정 - 주로 세 가지가 있음: 전위 순회, 중위 순회, 후위 순회

 

전위 순회와 후위 순회 모두 Recursion을 통해 간단하게 구현 가능.

특히, 두 순회는 print 코드가 Recursion 코드의 이전에 있는지 / 이후에 있는지에 따라 나뉨.

 

1. 전위 순회(Preorder Traversal)

: Work at a node is performed before its children are processed

 

2. 후위 순회(Postorder Traversal)

: Work at a node is performed after its children are processed

 

 

https://yoongrammer.tistory.com/70

 

[자료구조] 트리 순회 (Tree Traversal)

목차 트리 순회 (Tree Traversal) 트리의 모든 노드들을 방문하는 과정을 트리 순회(TreeTraversal)라고 합니다. 선형 자료 구조(연결 리스트, 스택, 큐 등)는 순차적으로 요소에 접근하지만 트리 자료구

yoongrammer.tistory.com

 

728x90

728x90

macOS에서 memory leak 체크하려다
-valgrind는 너무 유용하고 간단한 툴이지만: 리눅스 환경에서만 실행된다는 소식...
-sanitizer는 과제 환경인 g++ 컴파일러가 아닌 clang 컴파일러에서만 실행된다는 소식...


그렇게 알게된 게 'leaks'
macOS에서 valgrind의 역할을 해주는 요긴한 친구다 ❤️
하지만 leaks를 실행하기 위한 코드를 컴파일코드의 '어디'에 넣어야 할지 몰랐고, 이를 이해하면 과제에서 주어진 makefile의 문법을 알아야 했다. 역시 프로그래밍은 성급히 하면 오히려 꼬이고 세 배의 시간이 소요된다는 것.. ㅎㅎ 처음부터 찬찬히 해보니 성공했다!


 

1. makefile 친숙해지기 (아래링크에서 완벽 정리)
https://hwan-shell.tistory.com/188

c++] make, makefile의 사용방법(기본적인 설명)

1. makefile 이란?? 요 세개의 파일이 있다고 가정해 봅시다. 우리는 아래와 같은 명령어를 통해 실행파일을 만들어낼 수 있습니다. $ g++ -c test1.cpp add.cpp -> test1.o, add.o 파일 생성(오브젝트 파일) $ g++

hwan-shell.tistory.com

나의 makefile

CC = g++-11 --std=c++17
RD = rm -f
DoublyLinkedList.o: DoublyLinkedList.h DoublyLinkedList.cpp
	$(CC) -c DoublyLinkedList.cpp

part1_main.o: part1_main.cpp DoublyLinkedList.h
	$(CC) -c part1_main.cpp

part1_main.out: DoublyLinkedList.o part1_main.o
	$(CC) DoublyLinkedList.o part1_main.o -o part1_main.out

part2_main.o: part2_main.cpp DoublyLinkedList.h
	$(CC) -c part2_main.cpp

part2_main.out: DoublyLinkedList.o part2_main.o
	$(CC) DoublyLinkedList.o part2_main.o -o part2_main.out

clean:
	$(RD) *.o

→ 근데 결론은,, Makefile을 수정하지 않아도 됐더라는 것..! ㅋㅋ
그래두 이제 Makefile 읽을 수 있음
 
1. 일단 첫 번째는 DoublyLinkedList.o를 만들기 위한 코드임.
2. 두 번째는 part1_main.o를 만들기 위한 코드임. 앞에 Make 쳐주면 됨.
 
하지만, 내가 실제로 커맨드로 입력하는 코드는 $make part1_main.out (과제 명세) 임.

3. '$make part1_main.out'는 part1_main.out를 만드는 makefile 문법이 반영된 커맨드임. 이걸 터미널에 입력하면, makefile의 세 번째 코드가 실행됨. 세 번째 코드의 오른쪽 부분을 살피면, "part1_main.out를 만들기 위해서는 DoublyLinkedList.o와 part1_main.o가 필요하다"는 것을 알 수 있음. 이를 위해, 아까 언급한 첫 번째 두 번째 코드가 실행되는 것임.

$(CC) DoublyLinkedList.o part1_main.o -o part1_main.out

- $(CC)에는 g++-11 --std=c++17가 입력됨.

- 첫 번째 두 번째 코드를 통해 생성된 DoublyLinkedList.o와 part1_main.o를 활용하여

- part1_main.out라는 이름의 executable file을 만들어라

 

2. brew install leaks

사랑스러운 leaks를 mac에 설치하는 커맨드임

 

3. 아래 영상을 따라함

https://www.youtube.com/watch?v=bhhDRm926qA

이 영상이 진짜 최고임...
 
+추가 →근데 이거 볼 것도 없음. 위 영상에서 다 설명해줌.
https://stackoverflow.com/questions/59122213/how-to-use-leaks-command-line-tool-to-find-memory-leaks

How to use leaks command-line tool to find memory leaks?

leaks command-line tool will report the address of the leaked memory the size of the leak (in bytes) the contents of the leaked buffer like the following: Process: checker [84357] Path: ...

stackoverflow.com

커맨드라인에 이하를 입력

export MallocStackLogging=1 

→ memory leak과 관련된 모든 log를 터미널창에 출력해주도록 설정하는 것(option)

 
make part1_main.out

executable file 생성

 
leaks --atExit -- ./part1_main.out

현재 디렉토리의 part1_main.out를 실행하는데, memory leaks을 detect하고 그 결과를 보고하라!
 

  • leaks -atExit : tells which leaks exist, but not where any leaked allocation came from
  • MallocStackLogging : creates logs that can tell me where the leaked allocations came from, but the logs are automatically deleted when the program exits, and leaks -atExit runs, obviously, at exit

실행 결과

2 7
1 1
R
L
P 2
L
L
P 3
V
1 2 1 3 
part2_main.out(10555) MallocStackLogging: stack logs deleted from /tmp/stack-logs.10555.1008e8000.part2_main.out.0iRX5O.index
Process 10555 is not debuggable. Due to security restrictions, leaks can only show or save contents of readonly memory of restricted processes.

Process:         part2_main.out [10555]
Path:            /Users/USER/*/part2_main.out
Load Address:    0x10082c000
Identifier:      part2_main.out
Version:         0
Code Type:       ARM64
Platform:        macOS
Parent Process:  leaks [10554]

Date/Time:       2023-10-23 14:19:02.367 +0900
Launch Time:     2023-10-23 14:18:53.129 +0900
OS Version:      macOS 13.1 (22C65)
Report Version:  7
Analysis Tool:   /usr/bin/leaks

Physical footprint:         3585K
Physical footprint (peak):  7601K
Idle exit: untracked
----

leaks Report Version: 4.0, multi-line stacks
Process 10555: 228 nodes malloced for 117 KB
Process 10555: 0 leaks for 0 total leaked bytes.

leaks(10554) MallocStackLogging: stack logs deleted from /tmp/stack-logs.10554.104b18000.leaks.MUDEON.index

0 leaks for 0 total leaked bytes. !!!!

나의 소중한 코드에세서는 다행히 leak이 detect되지 않음...🥰🥰🥰

728x90

728x90

0. 주의

- 단순 BST 문제와 & Optimal BST 문제는
- 다루는 자료구조 자체는 BST로 동일하지만, 주목하는 특징이 서로 다르다.
 
(1) BST의 경우 Search가 궁극 목적이다. 즉 Binary Tree 자료구조를 통해 우리가 아는 Binary Search(이진 탐색)을 해내는 게 핵심이다. (ex. 숫자 맞추기 게임에서 Up/Down를 알 수 있다고 하면, 일반적으로 가능한 범위를 반으로 잘라서 정중앙의 숫자를 말하는 것이 가장 효율적 - 점차 정답의 범위를 반씩 좁혀나감) 따라서 각 노드에 저장된 숫자(키/데이터)의 양적 비교가 중요하다.
 
(2) Optimal BST의 경우 
형태는 BST로 똑같다. 그러나 이 경우 노드에 저장된 숫자의 양적 비교가 중요하지 않다. 오히려, 각 노드에 저장된 데이터는 문자열과 같이 더 다양한 데이터가 들어갈 수 있고, 우리가 '양적 비교'의 대상으로 고려해야 할 수치는 데이터 자체의 값이 아니라 메타데이터, 즉 데이터의 '검색 빈도(확률)' 및 각 데이터의 검색을 위한 '함수 호출 횟수'이다. 이들을 계산하여 '평균 검색 시간'을 최소화하는 트리 구조로 업그레이드시키는 것이 핵심이다.
 
따라서 완성된 Optimal BST의 모습을 보면, 1번 이진트리와 같이 숫자가 정렬된 상태가 아니다. 오히려 노드 데이터 자체는 마구잡이로 unsorted되었을 가능성이 높다. 노드의 정렬 기준이, 메타데이터 연산 결과를 Minimize하는 것이어야 하기 때문이다.


1. BST (Binary Search Tree) 이진 탐색 트리 (이진 트리 중 하나)

 

 
BST: ordered set (순서 가능한 집합)에 속한 원소(key)로 이루어진 Binary Tree
* Binary Tree: 각 노드의 자식의 수가 최대 2개인 트리
- 이진 트리 (Binary Tree: 각 노드의 자식의 수가 최대 2개인 트리) 이다.
- 왼쪽 자식 노드의 값은 자신의 값보다 작아야 한다.
- 오른쪽 자식 노드의 값은 자신의 값보다 커야 한다.
- 서브트리도 BST이다.
- 값이 중복되는 노드는 없다.
 
BST는 그 나름대로 풀어야 할 문제들의 특징이 있다!
 
https://gsmesie692.tistory.com/m/115

이진 탐색 트리 (Binary Search Tree)

1. 이진 탐색 트리란? 누구나 한번쯤은 숫자 맞추기 게임을 해본 적이 있을 것이다. A가 숫자를 하나 생각하면 B는 그 숫자를 맞추는데, A는 B가 말한 숫자보다 자기가 생각한 숫자가 큰지 작은지 (

gsmesie692.tistory.com


2. Optimal Binary Search Tree 최적 이진 검색 트리

→ Dynamic Programming으로 최적화
 

Goal: 평균 검색 시간이 제일 낮은, 가장 효율적인 트리를 찾자

1) 전제: 각 검색어의 검색 빈도(확률)이 다를 수 있다
ex) Crystal = 0.1 / Daisy = 0.2 / Beatrice = 0.3 / John = 0.4
 
2) 평균 검색 시간: 각 검색어의 검색 빈도(확률) p와, 검색을 위한 함수 호출 횟수(시간 복잡도) c의 가중합

⭐️

- '평균'이라는 말에 마지막에 개수로 나눠야 하지 않는가 하고 생각할 수 있지만, 이미 '확률'을 곱하여 더하므로 그 자체로 평균이 됨
- 각 검색어의 검색 빈도는 상수임 (고정된 Input)
- 따라서 검색어들을 어떤 형태의 BST로 구성하느냐에 따라 c가 달라져서 전체 평균 검색 시간이 달라지는 것!
ex)

https://gsmesie692.tistory.com/m/116

왼쪽: (0.1*1) + (0.2*2) + (0.3*2) + (0.4*3) = 2.3
오른쪽: (0.1*4) + (0.2*3) + (0.3*2) + (0.4*1) = 2.0
 

Problem Solving - Algorithm

1. brute-force

: 모든 경우의 수는 2^(n-1) →exponential
 

2. Dynamic Programming

- Bottom up
- 시간 복잡도: n^3 (for문이 3겹)
- Optimal Substructure: 어떤 BST의 왼쪽, 오른쪽 서브트리가 각각 최적 BST여야, 해당 BST도 최적이다. 
- 메모를 위한 Table(Tabular) 2개 & for문만이 필요하다!!
 
노드(Key)가 1~n개 있다고 하자: K_1 ~ K_n
 

1) Table A:

 K_i부터 K_j까지 최적의 BST로 정렬되어있다고 한다면, optimal 평균 검색 시간A[i][j]에 메모
- 원소가 하나인 트리의 경우, 원소를 찾는데 비교를 딱 한 번 하므로 A[i][i] = p_i
 

https://hi-guten-tag.tistory.com/73

어떤 Optimal BST가 있고 그것의 root가 Key(Node)k라고 하자.
그러면 그것의 left subtree가 최적이고, right subtree 또한 최적이다.
(최적이 아니라면 그걸 cut 하고 더 최적인 subtree로 paste하면, 현재보다 더 좋은 bst가 된다. 그러나 이는 현재가 optimal bst라는 가정에 모순된다)
 
왼쪽 서브 트리의 최적 값은 A[1][k-1]로 메모되어 있음
오른쪽 서브트리의 최적 값은 A[k+1][n]로 메모되어 있음
- 이때 Key k를 트리의 root로 추가해서 전체 트리를 만든다면, 각 서브 트리에서의 비교 횟수는 기존의 비교 횟수에 추가로 한 번만 더 비교를 하면 됨(각 subtree의 노드마다, 검색을 위한 함수 호출 횟수가 1씩 늘어나기 때문임)
- root에 대한 평균 검색 횟수는: 1(depth) x p_root = p_k
→ 둘을 합친 전체 트리의 최적 값은 (A[1][k-1] + p_1 + ... p_k-1) + p_k + (A[k+1][n] + p_k+1 + ... + p_n)


2) Recurrence Relation

수많은 경우의 수 중 최적의 값은 반드시 존재한다(최솟값)

Recurrence Relation (재귀 관계식)
https://gsmesie692.tistory.com/m/116

→ 1부터 n까지가 아니라 i번째부터 j번째까지의 key로 일반화

Base Case
https://hi-guten-tag.tistory.com/73

이 식을 이용해서 2차원 table A를 채워나가서, A[1][n] 의 값을 얻으면 그것이 최적 BST의 평균 검색 시간(최적값)이 됨


3) Table R:

R[i][j]:  K_i부터 K_j까지 최적의 BST로 정렬되어을 때, optimal BST root의 인덱스 메모 (A 배열에 최적값을 넣는 순간의 k값)
 
- R의 필요성: A만으로 최적값은 구할 수 있지만 최적 BST의 모양을 알 수 없음
- root 인덱스가 저장되어 있으면, root 이후의 노드 인덱스는 어떻게 아는가? Recursion에 의해 채워진다. 즉, 루트가 된 노드가 k번 노드라고 치면 그 왼쪽 서브트리의 루트노드 (즉 k번 노드의 left child)는 R[1][k-1], 오른쪽 서브트리의 루트노드는 R[k+1][n] 이 된다. 이런 식으로 R 배열의 값들을 이용해 재귀함수를 호출해주면서 노드를 만들어나가면 최적 BST가 만들어진다.
 

https://gsmesie692.tistory.com/m/116

 


https://gsmesie692.tistory.com/m/116 
⭐️⭐️

최적 이진 탐색 트리 (Optimal Binary Search Tree)

이전 포스팅에서 설명했던 이진 탐색 트리 (BST) 의 활용 예를 보자. 설명할 때는 보통 이해하기 쉽게 노드에 들어있는 데이터를 숫자로 가정하지만, 실제로 쓰일 때는 문자열이라던가 더 다양한

gsmesie692.tistory.com

https://hi-guten-tag.tistory.com/73

[알고리즘] 동적 계획법 - 최적 이진 검색 트리 (Dynamic Programming - Optimal Binary Search Tree)

1. BST (Binary Search Tree)란? 아마 자료구조 시간에 다 배웠으실 텐데요. BST는 ordered set (순서 가능한 집합)에 속한 원소(key)로 이루어진 이진 트리이고, 다음의 조건을 만족합니다. 각각의 노드는 하

hi-guten-tag.tistory.com

 

728x90

728x90

C++에서 cin을 사용하여 입력을 받을 때, 기본적으로 공백 문자(스페이스, 탭, 개행)을 기준으로 데이터를 분리

→ 띄어쓰기(스페이스)는 cin에서 입력을 구분하는 구분자로 작용함

 

예시

#include <iostream>
using namespace std;

int main() {
    int a, b, c;
    cout << "정수 a, b, c를 입력하세요: ";
    cin >> a >> b >> c;

    cout << "입력된 값: a=" << a << ", b=" << b << ", c=" << c << endl;
    
    return 0;
}

 

"1 2 3"로 입력하면 cin은 이를 공백 문자를 기준으로 각 변수에 할당함


사례

#include <iostream>
using namespace std;

int main() {

    int N, M;
    cin >> N >> M;
    cout << "N: "<< N <<", M: " << M << endl;

    char a;
    cin>>a;
    if (a=='*'){
        int b;
        cin>>b;
        cout<<b<<endl;
    }

    return 0;
}

Output

728x90
728x90

https://math.stackexchange.com/questions/4748117/what-does-nonlinear-mapping-phix-mean-is-it-a-vector-or-matrix

 

What does nonlinear mapping $\Phi(x)$ mean? Is it a vector or matrix?

I'm reading a paper about image classification. According to the paper, it says For a given nonlinear mapping $\Phi (x)$, the input data space $\mathbb{R}^{n}$ can be mapped into the feature space ...

math.stackexchange.com

For a given nonlinear mapping Φ(𝑥), the input data space 𝑛 can be mapped into the Feature space

Φ : ℝ𝑛 ↦ Feature space
𝑥 ↦ Φ(𝑥)

 

The feature map is an arbitrary map into the feature space 𝐻.

For example, if 𝐻 is finite dimensional (say, of dimension 𝑚), you can pick an orthonormal basis for it,

and think of each component of Φ in that basis as a feature. This is what scalar features are. 


Inner product space

 


orthonormal basis 

In mathematics, particularly linear algebra, an orthonormal basis for an inner product space V with finite dimension is a basis for V whose vectors are orthonormal, that is, they are all unit vectors and orthogonal to each other.

 

For example, the standard basis(표준기저) for a Euclidean space R" is an orthonormal basis, where the relevant inner product is the dot product of vectors. The image(공역) of the standard basis under a rotation or reflection (or any orthogonal transformation) is also orthonormal(=standard basis를 가지고 rotation과 같은 orthogonal transformation을 하면 그 transformed vector들도 orthonormal이다), and every orthonormal basis for R" arises in this fashion.

 

*standard basis: 유클리드 공간에서 직교 좌표계의 축을 향하는 단위 벡터의 집합

Every vector a in three dimensions is a linear combination of the standard basis vectors i, j and k.

standard basis i, j, k or R3

 

* basis: 벡터 공간을 선형생성하는 선형독립인 벡터들이다. 달리 말해, 벡터 공간의 임의의 벡터에게 선형결합으로서 유일한 표현을 부여하는 벡터들


For a general inner product space V, an orthonormal basis can be used to define normalized orthogonal coordinates on V. Under these coordinates, the inner product becomes a dot product of vectors. (The inner product는 dot product의 일반화된 버전 to abstract vector spaces over a field of scalars, being either the field of real numbers or the field of complex numbers)

 

orthogonal (직교) orthonormal
Two vectors are said to be orthogonal if their dot product is zero
Orthogonal vectors are perpendicular to each other
1) not only orthogonal
2) also, unit length 

 

 

Reference

https://en.wikipedia.org/wiki/Standard_basis

https://ko.wikipedia.org/wiki/%EA%B8%B0%EC%A0%80_(%EC%84%A0%ED%98%95%EB%8C%80%EC%88%98%ED%95%99)

https://www.collimator.ai/reference-guides/what-is-orthogonal-vs-orthonormal

https://en.wikipedia.org/wiki/Inner_product_space

 

728x90

+ Recent posts