Language/Javascript
[JS] 재귀 함수 / 스택과 큐 / 자바스크립트 메모리 / 배열
Jaka_Park
2024. 4. 16. 01:57
목차
1. 재귀 함수
2. 스택과 큐
3. 자바스크립트 메모리
3 - 1 원시타입
3 - 2 참조 타입
4. 배열
1. 재귀 함수
재귀함수는 함수의 내용에서 다시 자신을 호출해서 반복 작업을 하는 방식입니다. for 문으로도 반복문을 구현 가능한 로직들은 재귀 함수로 작성이 가능합니다. 재귀 함수를 사용하는 이유는 반복하는 내용의 기능을 여러개로 나누고 직관적으로 관리할 때 사용하는 프로그래밍 패턴 중 하나입니다.
재귀 함수를 작성할 때는 더이상 나눠야 할 필요가 없을 때 종료됩니다.
문제를 나눠서 기능을 작성하는 경우는 이 두가지 패턴을 찾아서 활용해야합니다.
재귀함수로 반복문을 사용한 예
function sum(n, result){
if (n === 5){
console.log(result);
}
sum(n + 1, result + n);
}
sum(1, 0);
// 출력값 : 10
재귀함수의 목적
장점으로 반복문을 많이 사용하는 경우보다 코드가 간결하고 직관적이다.
단점으로 스택에 함수 실행이 쌓여서 메모리 공간을 많이 차지하고 속도 성능이 저하된다.
재귀함수를 통한 피보나치 수열
function fibo(n){
if(n == 1 || n == 2) return;
return fibo(n - 1) + fibo(n - 2);
}
재귀 함수를 이용한 짝수 더하기
// 재귀함수로 짝수를 더하는 재귀적으로 돌리자
// 더하는 횟수는 인자값으로 전달 받아서
function sum(num, count){
if(count <= 0) return;
console.log(num);
sum(num + 2, count - 1);
}
sum(2, 5);
// 출력 : 2 4 6 8 10
2. 스택과 큐
스택
스택은 LIFO (Last In First Out) 후입선출 방식으로 데이터를 저장하는 자료구조입니다. 이는 마지막으로 삽입된 데이터가 먼저 삭제되는 구조를 의미합니다. 스택은 삽입(push)과 삭제(pop)의 두가지 기본 연산으로 구성되며 삽입은 스택의 가장 위쪽에 데이터를 추가하는 것이고, 삭제는 스택의 가장 위쪽 데이터를 제거하는 것이다. 재귀함수를 호출 할때 사용합니다.
큐
큐는 FIFO (First In First Out) 선입선출 방식으로 데이터를 저장하는 자료구조입니다. 이는 먼저 삽입된 데이터가 먼저 삭제되는 구조를 의미합니다. 큐 역시 스택과 마찬가지로 삽입(enmqueue)과 삭제(dequeue)의 두가지 기본 연산으로 구성됩니다. 큐는 탐색, 작업처리 대기열등에 사용되며, 컴퓨터 시스템의 프로세스 스케줄링에도 활용됩니다.
3. 자바스크립트 메모리
자바스크립트의 메모리 영역은 call stack과 heap이라는 영역이 있다.
call stack 메모리에 원시타입이 저장되고 heap 메모리에는 참조 타입이 저장됩니다.
원시 타입
- string, number, boolean, undefined 등 메모리에 값을 저장하고 변수가 직접 값을 가르키는 것
- 원시타입은 재할당 하게되면 새로운 메모리에 재할당한 값을 저장하고 가르키는 주가 바뀌는 것
let a = 1;
a = 2;
// 이렇게 1과 2는 둘다 값이 존재하면서 새로운 메모리에 값을 재할당하고
// a가 가르키는 주소가 변한 것(이후 1은 사용되지 않으니 제거된다.)
참조 타입
- Array. Object, function 등 외에는 참조타입 입니다.
- 원시타입과 다르게 참조타입은 변수의 크기가 동적으로 변합니다.
- 동적으로 데이터가 변하기 때문에 참조타입의 데이터는 heap메모리에 저장됩니다.
- 변수를 호출해 주소의 값을 호출하면 힙 메모리에 주소의 값을 호출하고 힙메모리의 주소에 있는 값을 호출하게 됩니다.
let arr = [];
let arr2 = arr;
// push 메서드는 배열에 값을 뒤로 추가한다.
arr.push(1);
console.log(arr2);
원시타입은 값을 가르키는 주소를 가지고 있다.`
참조타입은 힙 메모리 주소를 가르키는 주소를 가지고 있다.
4. 배열
배열은 참조형 데이터 타입
// 문법
let arr = [];
let arr2 = ["javascript", 2, 3, 4, true];
// 0 인덱스 개념으로
// 배열의 값을 호출할 때
arr[0] === "javascript";
// 자바스크립트의 배열은 데이터의 타입이 동적 타입이다. (어떤 타입이라도 쓸 수 있음)
// length는 배열의 길이를 나타낸다.
// arr.length 배열의 길이를 확인하는 키와 값
// 이중 배열
let b = [[],[],[]];
// 배열의 값을 추가
// 배열의 맨 마지막 데이터 뒤로 값이 추가된다.
arr.push(1);
// 해당 인덱스에 값을 할당하는 경우
arr[0] = 1;
arr[1] = 2;
// 실습 배열을 하나 만들고 반복문을 10번 돌려서 배열에 증가하는 index
// 배열의 메서드
// index : 0, 1, 2, 3, 4, 5
let arr = [1, 2, 3, "javascript", 4, 5];
// indexOf 배열안에 값을 찾고 그 값이 들어있는 index를 반환
// 해당 값이 있는 인덱스를 찾아서 반환
arr.indexOf("javascript");
function indexOf(arr, str){
// 배열의 길이만큼
for(let i = 0; i < arr.length; i++){
// i가 0일 때는
if(arr[i] == str)[{
return i;
// 자바스크립트 인덱스가 몇번인지 알려줄 수 있다.
}
}
}
// find
// 배열의 값을 처음부터 순서대로 순화하며 true의 값을 찾으면
// 반복을 멈추고 해당 값을 반환
// 함수에서 값을 반환
let result = arr.find(function(i){
return i === "javascript";
});
function find(arr, fn){
for(let i = 0; i < arr.length; i++){
function(arr[i]){
return i === "javascript";
// 1 false, 2 false, javascript true
}
}
if(fn(arr[i])){
return arr[i];
}
}
// findIndex
// 배열의 값을 처음부터 순서대로 순화하며 true 값을 찾으면
// 반복을 멈추고 해당 인덱스를 반환한다.
let result2 = arr.findIndex(function(i){
return i === "javascript";
});
// filter
// 검색기능 구현할 때
// 새로운 배열을 만든다.
let arr2 = ['사과', '사과', '포도'];
// 배열을 반환한다.
// true 값을 받아도 배열의 끝까지 순회
// true값이 나온 해당 데이터를 배열의 형태로 만들어서 최종적으로 반환
// ['사과', '사과']
let result3 = arr2.filter(function(i){
return i[0] === "사";
});
result3 = ['사과', '사과']; // 새로운 힙 메모리에 할당된 값
// map
// 배열의 값을 처음부터 순서대로 순회하면서
// 배열의 끝까지 반복한다. 배열을 반환한다. 반환된 값들을 가지고 배열을 생성.
let result4 = arr2.map(function(i){
return "javascript";
});
// forEach : 배열의 문자열 변환
let a = [];
arr2.forEach(function(i){
console.log(i);
a.push(i);
});
// join : 배열을 만들어서 값을 깊은 복사
arr.join("*"); // 빈문자열이면 구분점에 내용 추가x
// 문자열을 배열로 변경
// split : 매개변수로 전달한 내용이 문자열에서 배열로 나눠질 구분점
arr.splice("*")
// "사과*사과*포도" 문자열 -> ["사과", "사과", "포도"] 배열
// 배열을 깊은 복사 하는 경우
// 스프레드 연산자 용어
const arr = [1,2,3];
const arr2 = [...arr];
배열로 lotto 번호 6개 랜덤으로 뽑기
// 1. 로또는 겹치는 숫자가 나오면 안됨.
// 2. 숫자는 6개를 뽑아야 한다.
// 3. 나온 숫자들을 리스트 형태로 보여줘야함. (배열의 형태로 만들어줘야함)
// 로또 번호들이 들어갈 로또 박스
const lottoNum = [];
// 로또 구슬을 뽑아서 담아놓을 정답 배열
const result = [];
// 추첨 전에 세팅
// 초기화 단계
function lottoInit(){
for(let i = 1; i <= 45; i++){
lottomNum.push(i);
// lottoNum[i - 1] = i;
}
console.log("셋팅 끝남");
}
function play(){
for(let i = 0; i < 6; i++){
let randomIndex = parseInt(Math.random() * lottoNum.length);
let number = lottoNum[randomIndex];
// splice 원본 배열의 값을 제거하는데
// 첫번째 인자가 시작 인덱스부터
// 두번째 인자값은 갯수
lottoNum.splice(randomIndex, 1);
result.push(number);
}
}
// 함수를 한꺼번에 호출하기
function main() {
lottoInit();
play();
console.log("로또의 결과는?", result);
}
main();