Skip to content

Commit c7005b3

Browse files
committed
docs: 자료구조 3
- 배열, 포인터, 구조체, 재귀 호출의 네 가지 주요 주제에 초점을 맞추어 학습합니다.
1 parent 1d9c63c commit c7005b3

File tree

1 file changed

+177
-0
lines changed

1 file changed

+177
-0
lines changed

docs/자료구조/03.md

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
---
2+
sidebar_position: 3
3+
title: 프로그래밍 기법
4+
description: 배열, 포인터, 구조체, 재귀 호출의 네 가지 주요 주제에 초점을 맞추어 학습
5+
---
6+
7+
## 핵심 요약
8+
9+
- 배열 (Arrays): 동일한 자료형의 데이터 집합을 메모리의 연속된 공간에 저장하는 자료구조이다. 인덱스를 통해 각 요소에 빠르게 접근할 수 있으며, 1차원뿐만 아니라 다차원 형태로도 구성이 가능하다.
10+
- 포인터 (Pointers): 변수의 메모리 주소값을 직접 저장하고 다루는 변수이다. 메모리에 대한 직접적인 접근을 가능하게 하여 동적 메모리 할당, 배열 및 구조체의 효율적 관리 등 고급 프로그래밍 기법의 근간을 이룬다.
11+
- 구조체 (Structs): 서로 다른 자료형의 변수들을 하나의 논리적 단위로 묶어 새로운 자료형을 정의하는 기능이다. 배열과 달리 이질적인 데이터 그룹을 만들 수 있어, '레코드'와 같은 복잡한 데이터 형태를 표현하는 데 매우 유용하다.
12+
- 재귀호출 (Recursive Calls): 함수가 자기 자신을 다시 호출하는 프로그래밍 기법이다. 복잡한 문제를 동일한 구조를 가진 더 작은 문제들로 분할하여 해결하는 데 효과적이며, 특정 알고리즘을 간결하게 표현할 수 있게 한다.
13+
14+
---
15+
16+
## 배열 (Arrays): 심층 분석
17+
18+
배열은 동일한 자료형의 원소(element)들을 모아 메모리에 연속적으로 할당한 자료 그룹이다.<br/ >
19+
각 원소는 고유한 번호인 '인덱스(index)'를 통해 구별되며, C 언어에서 인덱스는 항상 0부터 시작한다.
20+
21+
### 1차원 배열
22+
23+
가장 기본적인 형태의 배열로, 데이터를 한 줄로 나열한 구조를 가진다.
24+
25+
- 선언 형식: 자료형 배열이름 [배열 요소의 개수];
26+
- 자료형: 배열에 저장될 모든 원소의 데이터 타입을 지정한다.
27+
- 배열이름: 변수 이름 규칙에 따라 정의한다.
28+
- 배열 요소의 개수: 대괄호([]) 안에 배열의 크기를 명시한다.
29+
- 메모리 할당: 배열 선언 시 할당되는 총 메모리 크기는 (자료형의 메모리 크기) × (배열 요소의 개수)로 결정된다.
30+
31+
| 배열 선언 예 | 의미 | 메모리 할당 크기 |
32+
| ------------- | ----------------------------------------------- | ---------------- |
33+
| char c[100]; | char형 원소 100개로 구성된 배열 c (c[0]~c[99]) | 1바이트 × 100 |
34+
| int i[100]; | int형 원소 100개로 구성된 배열 i (i[0]~i[99]) | 4바이트 × 100 |
35+
| short s[100]; | short형 원소 100개로 구성된 배열 s (s[0]~s[99]) | 2바이트 × 100 |
36+
| long l[100]; | long형 원소 100개로 구성된 배열 l (l[0]~l[99]) | 4바이트 × 100 |
37+
38+
- 초기화: 선언과 동시에 중괄호`{ }` 안에 초깃값 리스트를 지정하여 초기화할 수 있다.
39+
- 자료형 `배열이름[배열크기] = { 초깃값 리스트 };`
40+
- 초깃값의 개수가 배열 크기보다 작으면 나머지 원소들은 0으로 자동 초기화된다.
41+
- 초깃값의 개수가 배열 크기보다 많으면 컴파일 오류가 발생한다.
42+
- 문자 배열: 문자열(String)을 저장하기 위해 char형 배열을 사용한다. 문자열은 문자들의 연속적인 나열이며, 큰따옴표(" ")로 표현된다.
43+
- 초기화 방법: 문자열 리터럴`"String"`을 사용하거나, 개별 문자를 리스트`{'S', 't', 'r', 'i', 'n', 'g', '\0'}`로 지정할 수 있다.
44+
45+
### 다차원 배열
46+
47+
2차원 이상의 배열로, 행과 열 또는 면, 행, 열의 구조를 논리적으로 표현한다.
48+
49+
- 선언 형식:
50+
- 2차원: 자료형 `배열이름 [행 개수][열 개수];`
51+
- 3차원: 자료형 `배열이름 [면 개수][행 개수][열 개수];`
52+
- 구조:
53+
- 논리적 구조: 2차원은 표(table), 3차원은 입방체(cube) 형태로 인식된다.
54+
- 물리적 구조: 메모리에는 차원과 관계없이 모든 원소가 1차원적으로 연속되게 저장된다.
55+
- 초기화: 1차원 배열과 유사하게 초깃값 리스트를 사용한다. 차원별로 중첩된 중괄호를 사용하여 구조를 명확히 하거나, 모든 값을 나열하여 순서대로 초기화할 수 있다.
56+
57+
<br/>
58+
59+
---
60+
61+
<br/>
62+
63+
## 포인터 (Pointers): 심층 분석
64+
65+
포인터는 변수의 메모리 주소값을 값으로 가지는 특별한 변수이다.<br/ >
66+
포인터 변수가 특정 변수의 주소를 저장하는 것을 '해당 변수를 가리킨다(pointing)'고 표현하며,<br/ >
67+
이를 통해 메모리 영역에 직접 접근하고 제어할 수 있다.
68+
69+
### 선언 및 개념
70+
71+
- 정의: "변수의 메모리 주소값" 그 자체 또는 주소값을 저장하는 "포인터 변수"를 의미한다.
72+
- 선언 형식: 자료형 `*포인터이름;`
73+
- `*` 기호는 해당 변수가 포인터임을 나타낸다.
74+
- 자료형은 포인터 자체가 아닌, 포인터가 가리킬
75+
76+
### 주요 연산자
77+
78+
포인터는 두 가지 핵심 연산자를 통해 동작한다.
79+
80+
| 연산자 | 이름 | 설명 | 사용 예시 |
81+
| ------ | ----------- | ---------------------------------------------------------------------------------------- | ----------------------------------- |
82+
| `&` | 주소 연산자 | 변수 앞에 사용하여 해당 변수의 시작 메모리 주소를 반환한다. | `ptr = &i;` |
83+
| `*` | 참조 연산자 | 포인터 변수 앞에 사용하여, 해당 포인터가 가리키는 메모리 주소에 저장된 값을 읽거나 쓴다. | `*ptr = 20;` 또는<br/ > `j = *ptr;` |
84+
85+
### 포인터 초기화 방법
86+
87+
포인터 변수에 유효한 주소값을 할당하는 주요 방법은 다음과 같다.
88+
89+
1. 주소 연산자 `&` 사용: 기존 변수의 주소를 할당한다.
90+
2. 동적 메모리 할당: `malloc` 등의 함수를 통해 할당된 메모리의 시작 주소를 지정한다.
91+
3. 문자열 리터럴 할당: `char*` 포인터에 문자열의 시작 주소를 직접 지정한다.
92+
4. 배열 이름 사용: 배열의 이름은 그 자체로 배열의 시작 주소를 의미하므로 포인터에 할당할 수 있다.
93+
5. 배열 첫 번째 요소의 주소 사용: `&array[0]` 와 같이 배열의 첫 번째 요소의 주소를 명시적으로 지정한다.
94+
95+
### 고급 활용
96+
97+
- 포인터 배열 (Pointer Array): 포인터 변수들로 구성된 배열. `자료형 *포인터배열이름[배열크기];` 형태로 선언한다. 각 배열의 원소가 포인터이므로, 여러 개의 문자열이나 동적으로 할당된 메모리 블록들을 효율적으로 관리할 수 있다.
98+
- 포인터의 포인터 (Pointer to Pointer): 다른 포인터 변수의 주소를 저장하는 포인터로, 이중 포인터라고도 한다. `자료형 **포인터이름;` 형태로 선언한다. 포인터 배열을 함수 인자로 전달하거나, 함수 내에서 포인터 변수 자체의 값을 변경할 때 사용된다.
99+
100+
<br/>
101+
102+
---
103+
104+
<br/>
105+
106+
## 구조체 (Structs): 심층 분석
107+
108+
구조체는 하나 이상의 변수를 묶어 새로운 자료형으로 정의하는 기능이다. 배열과 달리, 서로 다른 자료형의 변수들을 멤버(항목)로 포함할 수 있다.
109+
110+
### 핵심 개념
111+
112+
- 정의: "서로 다른 자료형을 그룹으로 묶을 수 있"는 사용자 정의 자료형.
113+
- 배열과의 차이점: 배열은 동일 자료형(homogeneous)의 집합인 반면, 구조체는 다른 자료형(heterogeneous)의 집합을 만들 수 있다.
114+
- 활용: 이름, 입사 연도, 연봉 등 여러 필드(field)로 구성된 레코드(record)와 같은 복잡한 데이터를 표현하는 데 매우 유용하다.
115+
116+
### 선언 및 사용
117+
118+
구조체는 3단계의 과정을 거쳐 사용된다.
119+
120+
1. 구조체형 선언: struct 키워드를 사용하여 구조체의 이름과 내부 멤버 변수들을 정의한다.
121+
2. 구조체 변수 선언: 정의된 구조체형을 사용하여 변수를 선언한다.
122+
3. 구조체 변수 사용: 선언된 변수의 내부 멤버에 접근하여 데이터를 저장하거나 사용한다.
123+
124+
- 선언 형식:
125+
- 사용 형식: struct 구조체형이름 구조체변수이름;
126+
127+
### 데이터 항목 참조
128+
129+
구조체 변수의 멤버에 접근하기 위해 두 가지 연산자가 사용된다.
130+
131+
| 연산자 | 이름 | 설명 | 사용 예시 |
132+
| ------ | ------------- | ----------------------------------------------------------------------------------- | --------- |
133+
| . | 점 연산자 | 구조체 변수의 데이터 항목을 지정할 때 사용한다. (예: `Lee[i].name`) |
134+
| -> | 화살표 연산자 | 구조체를 가리키는 포인터를 통해 데이터 항목을 지정할 때 사용한다. (예: `ptr->name`) |
135+
136+
> 참고: 화살표 연산자 `p->member``(*p).member`와 완전히 동일한 표현이다.
137+
138+
### 구조체 연산
139+
140+
- 복사 연산: 같은 구조체형을 가진 변수들끼리는 대입 연산자(=)를 통해 모든 멤버의 내용을 한 번에 복사할 수 있다.
141+
- 주소 구하기 연산: 주소 연산자(&)를 사용하여 구조체 변수의 시작 주소를 얻을 수 있다.
142+
143+
<br/>
144+
145+
---
146+
147+
<br/>
148+
149+
## 재귀호출 (Recursive Calls): 심층 분석
150+
151+
재귀호출(순환호출)은 함수가 실행 도중에 자기 자신을 다시 호출하는 프로그래밍 기법이다.
152+
153+
### 핵심 개념
154+
155+
- 정의: "자기 자신을 호출하여 순환 수행되는 것".
156+
- 원리: 해결하려는 문제를 동일한 구조를 가진 더 작은 하위 문제로 분할하고, 가장 작은 단위의 문제(베이스 케이스)부터 해결해 나가는 방식이다.
157+
- 베이스 케이스 (Base Case): 재귀의 연쇄적인 호출을 멈추게 하는 조건이다. 이 조건이 없으면 함수는 무한히 자신을 호출하여 스택 오버플로 오류를 발생시킨다.
158+
159+
### 작동 원리: 팩토리얼 예제
160+
161+
팩토리얼 함수 `factorial(n)`은 재귀의 대표적인 예이다.
162+
163+
- 재귀적 정의: n > 0일 때, `factorial(n) = n \_ factorial(n - 1)`
164+
- 베이스 케이스: n = 0일 때, `factorial(0) = 1`
165+
166+
`factorial(3)`을 호출하면, 내부적으로 `factorial(2)`, `factorial(1)`, `factorial(0)`이 순차적으로 호출된다. `factorial(0)`이 베이스 케이스에 도달하여 1을 반환하면, 호출의 역순으로 결과값이 계산되어 최종적으로 `3 * 2 * 1 * 1 = 6`이 반환된다.
167+
168+
### 재귀의 종류
169+
170+
- 직접 재귀 (Direct Recursion): 함수가 자기 자신을 직접 호출하는 경우 (예: factorial 함수).
171+
- 간접 재귀 (Indirect Recursion): 함수 X가 함수 Y를 호출하고, 다시 함수 Y가 함수 X를 호출하는 것처럼 다른 함수를 통해 간접적으로 자기 자신이 호출되는 구조.
172+
173+
### 구현
174+
175+
재귀 알고리즘이 적합한 경우는 문제, 함수, 또는 데이터 구조 자체가 재귀적으로 정의될 때이다.<br/>
176+
재귀로 표현 가능한 대부분의 문제는 반복문(loop)을 이용해서도 구현할 수 있다.<br/>
177+
재귀는 코드를 간결하게 만들 수 있는 장점이 있지만, 함수 호출에 따른 오버헤드가 발생할 수 있다.

0 commit comments

Comments
 (0)