개요

스택 알고리즘 풀이 하는 김에 좀 더 공부해봤다.

 

10828번: 스택

첫째 줄에 주어지는 명령의 수 N (1 ≤ N ≤ 10,000)이 주어진다. 둘째 줄부터 N개의 줄에는 명령이 하나씩 주어진다. 주어지는 정수는 1보다 크거나 같고, 100,000보다 작거나 같다. 문제에 나와있지

www.acmicpc.net

 


개념

불연속적인 메모리로 Last in first out 을 가진다.

[Top of pointer을 가지고있음]

 


구현

array형식으로도 구현가능하고 linked list로도 구현 가능하여 각 장,단점을 생각해 보았다.


array로 구현시

 추가 메모리가 요구 되지 않는다.

 

● 먼저 array의 강력한 장점인 인덱스로 값을 찾는것이 stack에서는 그렇게 필요하지 않다고 느꼈다

어차피 맨 위의 데이터만 사용하려고 하는 것이기 때문이다.

 

● 크기에 대한 번거로운 과정이 있을 것이다(새로 할당받고 복사하고 원 메모리 반환)

그에 딸려오는 단편화 문제

 

Linked list로 구현시

● 임의의 위치에 데이터를 추가,삭제 하는 기능이 없기 때문에 이러한 장점을 살릴 수 없다.

 

 크기에 제약이 없다!

 

● 옆의 노드의 주소를 저장 할 공간이 추가 요구 됨

 

● 맨 위의 데이터만을 참고 한다는 스택의 특징이 랜덤 액세스가 불가능한 연결리스트의 단점을 커버 해줌


나는 무난한 배열로 구현을 해보겠다.


생성 & 소멸 & 멤버 변수

#include <iostream>
using namespace std;
#define INIT_STACK_SIZE 10

template<typename T>
class Stack
{
public:

	Stack()
	{
		data = new T[INIT_STACK_SIZE];
		capacity = INIT_STACK_SIZE;
		topIndex = -1;
	}
	~Stack()
	{
		delete[] data;
		data = nullptr;
	}
    
    
/************생략************/
                                        

private:
	//스택에 넣을 데이터를 담을 포인터 형
	T * data;
	//맨 위의 인덱스
	int topIndex;
	//스택의 총 메모리 양
	int capacity;
};

데이터 삽입 (Push)

	void Push(T input)
	{
		++topIndex;
		if (capacity <= topIndex)
		{
			T * temp = new T[capacity * 2];
			memcpy(temp, data, sizeof(int) * capacity);
			delete[] data;
			data = temp;
			capacity *= 2;
		}
		data[topIndex] = input;
	}

배열이기 때문에 크기에 대한 처리를 따로 해주었다.


데이터 삭제 (Pop)

	void Pop()
	{
		if (IsEmpty() == true) return;
		--topIndex;
	}

맨 위의 데이터 꺼내기 (Top)

	T Top()
	{
		if (IsEmpty() == true) return -1;
		return data[topIndex];
	}

여기서 예외설정을 안해서 알고리즘에서 틀렸었다 😂


결과

 


사용처

 

맨 위의 데이터를 다룬다는 것에 대하여 게임의 네비게이션에서 사용 할 수 있을거 같다.

 

이는 여태 시도하는 경로를 스택에 쌓아둠과 동시에 틀릴 경우 맨위부터 다시 돌아가 다른 경로를 탐색함에 있어서

LIFO인 스택과 같아 잘 맞는다.

[나중에 깊이 우선 탐색이라는 알고리즘이 이와 같다고한다?]

 

또한 상점에서 거래를 이전으로 돌리는 기능을 구현 할 수 있을 것 같다.(ctrl + z 처럼)

롤에서 상점에서 구매했던 것이나 팔았던 행위를 되돌릴 수 있는 것처럼!

 

또 다른 이용은 아직 데이터를 뒤집을때 편할듯 하다.

 

스택 프레임이란 개념도 있는데

함수가 호출될 때, 그 함수만의 스택 영역을 구분하기 위하여 생성되는 공간이라 한다.

그렇기에 함수 호출시에 생성되고 함수가 종료되면서 소멸한다.

이 공간에는 함수와 관계되는 지역 변수가 저장된다고 한다.

 

암튼 그렇다 ㅋㅋ

 

'코딩 테스트 > 자료구조' 카테고리의 다른 글

힙 [Heap]  (0) 2022.07.29
Linked List  (0) 2022.01.26
Vector  (0) 2022.01.25

특징

노드 컨테이너로 이루어져 있다

 

탐색의 경우 처음부터 끝까지 하나씩 탐색해야하기 때문에 O(n)

=>인덱스를 지원하기 하지 않기 때문에 랜덤한 접근이 불가능하다

 

데이터의 어느곳이든지 삽입 삭제가 빠르다 O(1)

=>순서 변경도 마찬가지

 

컨테이너의 크기가 고정이 아닌 동적으로 이루어진다

 

근데 이 또한 vector처럼 동적할당으로 이루어지는데

자주 크기가 조정 될 시에 메모리단편화라는 단점이 거론되지 않는가 궁금했다.

추측인데 vector는 데이터가 메모리에 연속적으로 있어야 하지만

List는 각 데이터 하나 하나가 꼭 붙어 있지 않아도 되기에 미리 나누어져있는 메모리를 할당받을 확률이 높다고 생각한다.

 

※캐시라인이라는 개념으로 vector와 비교되는데 나중에 다시 찾아보기


결론

 

연결 리스트도 vector와 마찬가지로 가변성이 가장 큰 특징이라 생각이 들어

vector와 차이를 많이 못느꼈었는데

 

어느곳에서나 데이터의 삽입 삭제에 빠르며 메모리의 크기 조정 또한 빠르다

"변화에 강함" 이게 핵심인거 같다.

 


사용처

 

[작성중]

그 아이템 뺑뺑이 돌아가는거

 

 

'코딩 테스트 > 자료구조' 카테고리의 다른 글

힙 [Heap]  (0) 2022.07.29
스택 [Stack]  (0) 2022.01.27
Vector  (0) 2022.01.25

특징

 

연속된 컨테이너를 가지고있다( = 메모리상 연속적으로 저장이 됨 )

 

탐색의 경우 처음부터 끝까지 하나씩 탐색해야하기 때문에 O(n)

 

인덱스를 지원하기때문에 랜덤한 접근은 빠르다(조회) O(1)

 

데이터의 끝부분에 삽입, 삭제는 빠르다. amortized O(1)

[ 삽입시 메모리를 다시 동적할당 받아올 경우 n개만큼 복사가 이루어지기때문에 이 상황에는 O(n) ]

하지만 중간에 삽입, 삭제시에는 그 뒤에 있는 모든 데이터를(n) 한칸씩 앞이나 뒤로 복사가 이루어져 느리다. O(n)

 

컨테이너의 크기가 고정이 아닌 동적으로 이루어진다

하지만 크기가 자주 변경된다면 불리한 자료구조이다.

=> 잦은 동적할당과 해제 => 메모리 단편화가 발생 할 소지가 많다.

 


결론

 

크기가 변할 가능성이 있으나 자주는 아닌 경우,

인덱스를 이용한 접근을 사용하는 경우,

처음부터 쭉 순회를 해야할 경우,

중간 삽입,삭제가 적을 경우

vector를 사용할것이다.

 


사용처

 

만약 내 게임에서 사용 한다면

 

게임 내의 모든 아이템 데이터를 담는 자료구조로 vector를 사용할거 같다.

아이템은 거의 꾸준히 업데이트 되기 때문에 가변적 특성을 띄고

꼭 순차하여 아이템 정보를 가져오는게 아닌

인덱스를 통해 원하는 아이템정보를 가져올 수 있기 때문이다.

 

플레이어의 분신같은 스킬을 사용할때

각 분신을 vector에 넣을거 같다.

이 스킬에 분신의 개수가 변경될 가능성이 있다고 생각하기 때문에 가변적 특성을 띄고

분신이 나타나고 사라지기 전까지 분신이 추가되는 중간 삽입,삭제가 없어 잘 맞는다고 생각했다.

 

한 맵에서 출현하는 몬스터들의 데이터를 저장할거 같다.

출현하는 몬스터의 수는 거의 고정적이지만 이벤트성이나 다른 몬스터의 추가로 수정 될 수 있다고 생각하였고

중간에 삽입 삭제할 경우가 없다고 생각이 들어 vector가 적당하다 생각했다.

 


추가

 

vector의 순회 속도

더보기

 

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=4roring&logNo=221337048963

이 글과 비슷하게 나도 데이터를 순회 하는데 있어서 밑의 5가지 방법을 테스트 해봤다

1. 함수 at 사용

2. operator [ ] 사용

3. 주소를 직접받아 연산해 순회

4. iterator 사용

5. 범위기반 for문 사용

 

20,000,000개의 데이터를 순회하면서 int형 변수 result에 계속 더하여 테스트했다.

(좌) Debug mode (우) Release mode

느낀 점

 

1.

이번에 찾아보면서 at과 [ ]를 비교하는 글이 많았었다.

at은 out of range 검사를 해주지만

[ ]은 검사를 하지 않기때문에 at보다 빠르다고 많이들 적혀있었는데

평균적으로 debug모드에서는 정말 차이가 없고 release모드에서만 차이가 확실히 났다.

 

2.

iterator를 사용한 경우 debug모드에서는 굉장히 느렸지만 release모드에서는 굉장히빠른 모습을 보였다

반전매력 ㄷㄷ

 

3.

다른 결과값이 나오기 전까지 vector를 순회할때는 range based for문을 사용해야겠다

 

4.

그래도 이 테스트는 절대적인 성능이 아니라 대략적으로 파악하기 위한거니

상황이 달라지면 결과도 바뀔수있기에 일반화하지 말자

 

코드 부분

설정 부분
테스트 부분

 

왜 Index로 인한 조회는 O(1)?

더보기

Index로 인한 조회는 빅오가 O(1)이 나오는데

나는 처음에 왜 상수시간복잡도가 나오지? 라고 생각이 들었다.

 

만약에 3번째 데이터를 찾는다 하면

0번 데이터를 찾고 카운트 0, 다음으로 넘어가

1번 데이터를 찾고 카운트 1, 다음으로 넘어가

2번 데이터를 찾고 카운트 2, 다음으로 넘어가

3번 데이터를 찾고 카운트 3.

 

이렇게 3번째 데이터를 찾아서 O(n)이 나오지 않을까? 라는 생각이 들어

Index의 조회가 어떻게 이루어지는지 궁금해서 찾아보았다.

 

바로 주소값을 계산해서 주소로 들어가 한번에 찾는건데

 

시작위치 + (인덱스 * 데이터 타입 크기) 로 계산이 되어 찾으려는 데이터를 한번에 O(1)로 찾아내는것이였다.

그래서 인덱스가 연속된 메모리의 컨테이너에서 가능한 이유였다~

ㅋㅋㅋㅋㅋ

 

https://dc7303.github.io/essay/2020/02/23/whyUseArrayInsteadOfList/

 

 

 

 

'코딩 테스트 > 자료구조' 카테고리의 다른 글

힙 [Heap]  (0) 2022.07.29
스택 [Stack]  (0) 2022.01.27
Linked List  (0) 2022.01.26

먼저 오차원인을 간단하게 말하면

 

컴퓨터는 2진수로 모든걸 다루기 때문에 소수도 2진수로 변경해서 값을 다루게되는데

이 변경하는 과정에서 오차값이 생긴다고 말할수있다.


이 변경하는 과정을 좀 더 설명하자면 

 

일단 컴퓨터가 실수를 다루는 방법은 대중적으로 2가지가 있다

  • 고정 소수점 방식
  • 부동 소수점 방식

고정 소수점 방식보다 더 정밀하게 표현하기 위해 부동 소수점 방식이 나왔다

 

주로 사용하는 실수 자료형에서 보면

 

float은 총32bit로 단정도라 하며

/ 1bit 부호비트 / 8bit 지수부 / 23bit 가수부 / 로 이루어져 있다

 

double은 총64bit

/ 1bit 부호비트 / 11bit 지수부 / 52bit 가수부 / 로 이루어져 있다


이 부동소수점 형태로 소수를 이진수로 변경하여 저장하는 과정은 크게 세가지다.

 

"11.6"을 단정도로 예시를 들면

 

1.일단 정수부와 소수부로 나누어 이진수로 변경

  정수부 소수부
10진수 11 0.6
2진수 1011 1001...
(무한소수로 반복됨)

여기서처럼 소수부가 이진수로 변환되면 무한소수가 될때가 있다.(모든 수가 그런건 아님)

끝없이 값을 저장할 수 는 없으므로 어딘가에서 끊어주고 그 뒤의 값을 버려야 하는데

이처럼 값을 버리는 과정에서 오차가 나게된다.

 

11.6 => 1011.1001....이다

 

2.정수부에 1만 남기도록 소수점을 이동하여 정규화하여 지수부와 가수부를 나눈다

여기서 소수점을 이동시키는게 정규화라 하였는데

이곳 뿐만아니라 여러곳에서 정규화를 한다는건 서로 비교할때 굉장히 편리하였는데 여기도 마찬가지고

추가로 조금더 비트를 절약하여 그만큼 정밀도가 향상되기 때문이다.

 

아무튼, 이동시키면 1.0111001.... 이며 소수점 뒤에있는 수가 가수부가 된다.

 

가수부는 단정도에서 11bit이므로 11bit만큼 채워주거나 잘라준다

1.01110011001 이된다.

(가수부는 "01110011001" 임)

 

그 후 소수점을 이동한 만큼 지수부가 결정된다.

이동한 거리는 3칸으로 지수는 3이다.

(만약 반대방향이였으면 -3)

 

지수부는 총 8bit로 3의 값을 가진다. 하지만 상대는 컴퓨터이므로 이진수화 해준다.

3은 이진수로 0000 0011이지만 놀랍게도 이 값에 bias값이라는걸 더하여 저장한다.

 

3.지수부에 bias값을 더함

지수가 음수일 경우도 있기 때문에 탄생한 하나의 음수 표현법이라 보면 된다.

[지수의 2진수 + bias값 = bias표현법]

 

2의 보수나 부호 비트처럼 음수를 표현하는 방법이 있는데

"왜 굳이 bias표현법을 사용하는가"라 한다면 사실 아직 잘 모르겠다.

여러 의견을 보았는데 확실 하지 않은거 같아 지금 상태에서는 이러한 표현법으로 저장한다 라고 알아둬야겠다.

 

bias값은 2^(n-1)-1 으로 계산한다.

[n은 지수부의 비트 수]

 

8bit의 bias표현 법에서 표현가능한 지수는 -127 ~ 128 이다

0000 0000 = 지수-127 + bias127

0000 0001 = 지수-126 + bias127

...

1000 0000 = 지수0 + bias127

1000 0001 = 지수1 + bias127

...

1111 1111 = 지수128 + bias127

 

그럼 위에서 나온 3의 이진수인 0000 0011과 단정도의 bias값인 0111 1111(127)을 더하면

1000 0010으로 지수부에 저장된다.

 

그럼 우리가 위에서 나온 3이 최종적으로 정리되는 형태는

 

0 / 1000 0010 / 01110011001 형태로 저장이 된다.

 

 


가장 설명이 좋았던 곳

https://blog.naver.com/kmc7468/220990920730

https://thrillfighter.tistory.com/349

'공통' 카테고리의 다른 글

Logical memory & physical memory  (0) 2021.06.05
  • 연산자 오버로딩

정의 되지않은 데이터끼리의 연산을 직접 정의하여 기호만으로도 그 정의대로 연산이 실행되게 할 수 있다

오버로딩은 다형성의 대표적인 예임

 

예를들어 Vector class가 있다고 생각하면 컴퓨터는 Vector + Vector이 어떻게 연산해야하는지 모른다

그래서 정의를 해주어 그대로 연산되게 하는것

 

 

연산자를 오버로딩 하려면 연산자 함수라는 특별한 함수를 사용한다

operator op ( argument-list )

 

이  op는 연산자 기호를 나타낸다 ( + , - , * , / , [ ])

 

이 연산자 함수는 함수표기와 연산자표기가 모두 가능하다

 

밑은 오버로딩 선언 및 정의이다

여기서 처음 알게된건 arg.x처럼 다른 객체의 private멤버 함수여도

같은 클래스로 생성되었다면 private에 선언된 데이터를 사용가능하다는 것이다

 

그리고 +연산자는 두개의 피연산자를 요구하는데, this 포인터를 통하여 암시적으로 하나가 전달된다.

다른하나는 매개변수로 명시적 전달이 된다.

 

연산자의 왼쪽에 있는 객체가 호출한 객체이고 오른쪽이 매개변수로 전달되는 객체이다

 

세개 이상의 객체의 연속된 연산도 가능하다

덧셈 연산자는 왼쪽에서 오른쪽으로 결합하는 연산자이기에 

a + b 가 실행되고  (a + b의결과) + c 가 실행된다

 

이러한 연산자 오버로딩은 편하지만 기호로만 어떤 기능인지 알수있기때문에

 

정의가 명확해야한다.

 

이건 설계시에도 마찬가지긴 하다


  • 연산자 오버로딩 제약

제한되는 상황이 있는데

 

최소 하나 이상의 피연산자가 사용자 정의 데이터형 이어야한다

[ float - float 같은 모두 표준 데이터형의 연산은 오버로딩 할 수 없다 ]

 

기호를 새로 만들 수 없다

[ operator *+-( ) 처럼ㅋㅋ ]

 

오버로딩 불가능한 기호들이다

 

  • 자료&정보

자료(Data): 단순한 사실이나 결과 값

[내가 지금 먹는 음료수의 칼로리, 내 핸드폰의 최대 데시벨]

 

정보(Information) : 자료를 가공하여 의사결정에 도움을 줄 수 있는 결과물

그렇다면 비교하면 정보가 될 수 있지 않을까?

[다이어트 중이라 제일 낮은 칼로리의 음료수를 먹을 거다, 3가지 음료수의 칼로리를 보고 가장 낮은 음료수를 파악,

여기서 "칼로리"들이 자료들이 되겠고 정보는 "3가지 음료수중에 결정한 음료수가 가장 낮은 칼로리를 가지고 있다"가 되겠다]


  • 데이터 베이스 정의

데이터 베이스에 관해 검색하면 4가지가 많이 나온다

 

통합된 데이터 : 자료의 중복을 배제한 데이터

[회원가입을 하였는데 내 정보가 한 번만 저장되지 않고 두 번 이상 저장되는 것처럼 중복을 배제한다]

저장된 데이터 : 컴퓨터 같은 저장 매체에 저장된 데이터

[종이나 책, 이러한 매체가 아닌 컴퓨터, 핸드폰처럼 저장장치에 저장을 한다]

운영 데이터 : 조직의 업무를 수행하는데 반드시 필요한 데이터

[음료수를 만드는 조직인데 뜬금없이 학생들의 키, 몸무게 이러한 데이터를 저장하지 않는다]

공용 데이터 : 여러 응용 시스템들이 같이 공용으로 사용하는 데이터

[은행에서 수납, 저축, 카드 등록 업무가 있다면 수납 데이터베이스, 저축 데이터베이스, 카드등록 데이터베이스

이렇게 나누지 않고 하나의 통합 데이터 베이스를 구축하여 세 업무 모두 사용할 수 있다는 뜻 같다]

 

근데 이게 정의라고 많이 나오는데 나는 어떠한 데이터가 들어가야 하는가 를 말하는 쪽에 더 가깝게 느껴졌다


  • 데이터 베이스 특징

실시간 접근성 : 말 그대로 질의에 대하여 실시간으로 처리가 가능하다

[내가 밥 먹을 때나 화장실에 있을 때나 원할 때 언제든지 질의하면 그에 맞는 데이터를 얻을 수 있다]

계속적인 변화 : 항상 최신 데이터를 유지한다

[내가 데이터를 얻으려고 요청했는데 1년 전 데이터나 1시간 전 데이터를 받지 않는다]

동시 공유 : 여러 사용자에게 동시에 공유된다

[동시에 나와 친구가 같은 데이터 건 다른 데이터건 데이터를 참조할 수 있다]

내용에 의한 참조 : 데이터를 찾을 때 어떠한 주소가 아닌 값 그 자체로 데이터를 찾을 수 있다

[0x010222처럼 주소로 데이터를 요청하는 게 아니라 "사과" , "160cm" 이러한 값들로 원하는 데이터를 요청할 수 있다]

 

 


이곳은 설명이 제일 깔끔하고 너무 설명이 잘 되어있었다

https://mangkyu.tistory.com/19

'컴퓨터 공학 > 데이터 베이스' 카테고리의 다른 글

스키마, 데이터 베이스 언어  (0) 2022.02.05
DataBase Management System  (0) 2022.01.27

하나의 StaticMeshComponent 를 가지고 StaticMesh만 변경해야하는 기능이였는데

 

블루프린트에서의 SetStaticMesh는 문제 없이 잘 돌아갔지만

 

C++에서의 SetStaticMesh는 메시는 잘 들어갔지만 머터리얼은 이전게 계속 유지되고있었다

[이 사실을 죤내 늦게 파악했다.. 담에는 더 자세히 파악해야겠다]

 

나중에 다른곳에서도 그런지 파악해봐야겠다

 

 

문제해결로 Material도 같이 변경해주었다

쥰내 이상한? 버그였다

 

내가 작성한 컴포넌트명이 ABC 라고 하면

ABC 프로퍼티를 읽으려던 중 None 에 접근했습니다.

(Accessed None trying to read property ABC)

라고 로그가 떴다.

 

내가 인스턴스화를 안했나? 싶었는데 잘 되어있었다;

만든 컴포넌트를 넣을 액터의 헤더
만든 컴포넌트를 넣을 액터의 CPP

 

검색 후 비슷한 증상을 겪은 사람이 있었나 보다

https://answers.unrealengine.com/questions/740355/c-uproperty-actor-component-variable-being-set-to.html?sort=oldest 

 

다들 원인은 UPROPERTY를 변경함에 있어서 생긴 문제로 파악하고 있다

 

해결방법은 죤내 어이가 없었는데

변수명을 바꾸면 된다

ㅋㅋㅋㅋㅋㅋ

(좌)header (우)cpp

테스트로 변수명뒤에 2를 붙였는데 잘됐다..

 

그 후로 다시 변수명을 되돌려도 잘되더라~~

 

이것때문에 얼마나 시간을 썼는지 ㅠ

+ Recent posts