메모리에서 휘발성 메모리와 비휘발성 메모리가 존재한다.

 

휘발성 메모리의 대표적인 사례는 RAM, ramdom access memory 가 있다.

비휘발성 메모리에는 대표적으로 컴퓨터의 하드 드라이브가 있다.

 

RAM 이라는 메모리를 사각형으로 된 박스 상자로 본다고 가정하면, 아래와 같이 무수히 많은 박스 영역으로 구성되어 있다고 생각할 수 있다.

출처 : https://www.youtube.com/watch?v=NFETSCJON2M&list=PL7jH19IHhOLMdHvl3KBfFI70r9P0lkJwL&index=2

그리고 하나의 박스 영역마다 메모리에서는 자신이 기억할 수 있도록 주소를 생성한다.

따라서 유저가 RAM을 활용해서 '6' 이라는 데이터를 호출하려고 할 때, 컴퓨터는 모든 상자를 다 확인해보는것이 아니라, '6'이라는 데이터가 담긴 주소값을 바로 입력받았다면, 그 즉시 '6'을 호출하는 것이다. 그래서 RAM은 빠르다.

 


Array 배열

 

배열은 위 그림에서 빨간 박스로 체크되어 있는 것 처럼, 특정 영역을 미리 컴퓨터에게 명령하여 공간을 할당하는 것을 의미한다. 그리고 우리는 미리 할당한 영역에 원하는 데이터를 추가할 수도, 삭제할 수도, 수정할 수도 있다.

 

1. Reading

출처 : https://www.youtube.com/watch?v=NFETSCJON2M&list=PL7jH19IHhOLMdHvl3KBfFI70r9P0lkJwL&index=2

만약 배열 안에 다음과 같은 데이터값을 넣어놨다면, 우리는 pizza라는 데이터를 호출해야할 문제를 맞닥드렸을 때

System.out.println(array[2]) 라는 명령어를 통해서 피자를 바로 호출 할 수 있을 것이다.

즉 시간복잡도의 의미적으로 본다면, 우리는 하나의 스텝만으로 피자를 출력할 수 있게 된다는 것이다.

따라서 배열을 사용한다면, Reading에서 매우 효율적인 선택이 될 것이다.

 

2. Searching

 

 

   하지만 Searching에서의 배열은 다르다. 

   아래의 그림에서 잘 설명되어 있듯, 메모리는 각 공간마다 임의의 주소값     만을 할당해서 기억한다.

   따라서 각 주소값마다 어떤 데이터가 있는지를 알지는 못하는 것이다.

   Reading과 같이, 우리가 이미 pizza 라는 데이터의 주소값을 아는 상태에     서는 호출이 매우 효율적이지만

   만약 데이터의 주소값을 모른다면?

 

  우리는 모든 주소값의 박스 상자를 열어보면서 내가 원하는 데이터값을      찾아야 할 것이다.

 

 

그리고 만일, pizza 라는 데이터를 찾기 위해 배열 안에서 검색을 했는데 원하는 값이 없다면? ...

 

이처럼 배열에서의 Searching은 다소 효율적이지 못한 결과를 만들어낼 수 있다.

 

 

 

 

3. Add, Delete

 

배열의 추가 역시 가장 효율적이다, 라는 표현과는 거리가 있다.

우선 배열에서의 데이터 추가에서 최상의 시나리오는 potato의 오른쪽, 즉 배열 index 5 에 새 값이 들어오는 것이다.

하지만 index 0, 1, 2 등에 새 데이터가 씌워져야 한다면?

그 경우, 위 사진에서 볼 수 있듯, 기존 데이터를 오른쪽으로 다 옮기는 스텝(시간복잡도)을 거친 후 새 데이터가 씌워질 것이다.

 

뿐만 아니라 만약 배열의 공간이 꽉 차 있는 상태에서 새 데이터를 추가하려고 한다면? 

우리는 새로운 배열을 만든 후 기존의 배열을 복사하여 붙여넣기 하는 스텝을 거쳐야 할 것이다.

 

삭제 역시 마찬가지이다. 배열의 제일 오른쪽에 위치한 데이터를 삭제한다면 추가적 스텝은 불필요하겠지만

만약 중간값, 혹은 맨 처음값을 삭제한다면?

우리는 기존 배열의 데이터들을 왼쪽으로 쉬프트 하는 스텝이 필요해질 것이다. 왜냐하면 배열의 중간값을 비울 수는 없기 때문이다.