순차 자료구조란?
데이터는 다양한 방식으로 저장될 수 있는데, 메모리에 저장된 물리적 위치가 연속적으로 저장된 경우를 순차 자료구조라고 합니다.
C에서는 배열을 통해서 순차 자료구조를 표현합니다. 그래서 메모리에 저장된 시작 위치를 알면 특정 자료의 위치를 쉽게 알 수 있다는 장점이 있습니다.
반면에 자료들이 연속적으로 저장되어있어, 특정 자료를 특정 위치에 삽입하거나, 삭제할 경우 특정위치 뒤에있는 자료들을 모두 한칸씩 뒤로 이동해서 자리를 비워주거나, 특정위치에 삭제할 자료 뒤에있는 자료들을 모두 한칸씩 앞 당겨야 한다는 번거로운 단점이 있습니다.
- 순차 자료구조의 사용 예시
순차 표현의 사용 예시로 첫번째는 테트리스의 블록 표현 방법이 예시가 있습니다.
테트리스 블록 한개를 예로들어서, 이 블록의 표현 방법은 배열을 사용하여, 표현할 수 있습니다.
int block[4][4]={
0,0,0,0,
0,0,1,1,
0,1,1,0,
0,0,0,0};
(엥 저게 무슨말이지?) 2차원 배열을 사용한 저것이 어떻게 테트리스 블록이냐?! 궁금해 하실 수도 있습니다.
#include <stdio.h>
int main(void) {
int block[4][4] = {0,0,0,0,0,0,1,1,0,1,1,0,0,0,0,0 };
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (block[i][j] == 0)
printf(" ");
else if (block[i][j] == 1)
printf("■");
}
printf("\n");
}
return 0;
}
배열에서 숫자 0은 공백으로, 숫자 1은 ■ 기호를 사용할 경우, 단순하지만 연산 처리과정이 엄~청빠른 컴퓨터는 단번에 우리가 쉽게 알아볼 수 있는 블록으로 출력해줍니다.. +_+
(저 블록에서 방향도 바꿔야 하지 않나?)..
우리는 3차원 배열을 사용해서 블록의 회전기능까지 갖고있는 배열을 만들 수 있습니다.
바로!!!! 'rotation' 유무에 따라 기본 도형인지, 회전한 도형인지를 구분짓는, 두가지의 방법이 추가적으로 저장되어야 할 때 순차 자료구조의 특성을 갖는 3차원 배열을 사용하면 쉽게 저장이 가능합니다.
#include <stdio.h>
int main(void) {
int block[][4][4] = {
0,0,0,0,0,0,1,1,0,1,1,0,0,0,0,0 //이전의 블록, 기본 형태의 블록
,0,0,0,0
,0,1,0,0 //회전한 블록
,0,1,1,0
,0,0,1,0
};
for (int z = 0; z < 2; z++) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (block[z][i][j] == 0)
printf(" ");
else if (block[z][i][j] == 1)
printf("■");
}
printf("\n");
}printf("\n\n");
}
return 0;
}
내가 만약 기본적인 형태를 갖는 블록을 출력하고 싶다? block[0][i][j]를 출력하면 되고,
회전된 블록을 출력하고 싶을 경우에는 block[1][i][j]를 출력하면 되는 것입니다.
이처럼 배열의 첫 번째 원소부터 마지막 원소까지 연이어 메모리에 저장된 것을 순차 자료구조라고 합니다.
위의 경우에서, 내가 특정한 index의 위치를 바꾸고 싶은 경우에는 쉽게 바꿀 수 있지만,
특정 index의 정보를 삭제하고 싶을 경우, 삭제할 뒤에있는 정보들의 index를 일일이 바꿔주지 않으면 저 도형은 우리가 알아볼 수 없는 도형이 되버립니다.
=> 원소 삽입 삭제가 비효율적이구나..?!를 알아 차릴 수 있습니다.
- 순차 자료구조의 사용 두번째 예시
예를들어 2020년 5월~8월, 2021년 5월~8월까지 휴대폰의 판매량을 순차적인 리스트로 표현한다면, 2차원 배열을 사용하면 쉽게 자료들을 나열할 수 있습니다.
연도 / 판매량 | 5월 | 6월 | 7월 | 8월 |
2020년 | 3515만대 | 3342만대 | 2951만대 | 4278만대 |
2021년 | 3215만대 | 3751만대 | 2845만대 | 4385만대 |
int salesRate[2][4]={
{3515,3342,2951,4278}, //2020년 휴대폰 판매량
{3215,3751,2845,4385} //2021년 휴대폰 판매량
};
2차원 배열로 판매량 list를 구현했지만, 실제로 메모리상에서는 배열의 index를 기준으로 하는 행 우선 순서에 따라 1차원 배열이 저장되는 물리적 순서로 저장이 됩니다.
#include <stdio.h>
int main(void) {
int n = 0; int* p = NULL;
int salesRate[2][4] = {{3515,3342,2951,4278},{3215,3751,2845,4385}};
p = &salesRate[0][0];
for (int i = 0; i < sizeof(salesRate) / sizeof(salesRate[0][0]); i++) {
printf("2차원 배열의 주소 : %u ,sale[%d][%d]=%d\n", p, i / 4, i % 4,*p);
p++;
}
return 0;
}
옆에 결과를 볼 수 있으면 알 수 있지만,
행 우선 순서에 따라 시작 배열의 주소 끝 두 자리수가 84에서, index가 1씩 늘어날 때마다 88, 92 ...+(int)자료형의 크기인 4씩 연속적으로 저장됩니니다.
2차원 배열에서 열을 기준으로 저장하는 방식인 열 우선 순서 방법도 있지만, 기본적인 프로그래밍에서는 컴파일러에 따라 결정되는데, C 컴파일러는 행 우선 순서 방법을 사용합니다.
- 순차 자료구조의 사용 세번째 예시
배열을 활용한 순차 list는 수학을 배울때 많이 쓰였던 다항식에서도 사용될 수 있습니다.
1차원 배열을 사용하여 2x^3+7x^2+0x^1+8x^0 이 다항식을 표현 할 때 최고차항의 계수를 차례대로 index 0부터 저장할 수 있습니다.
int MAX_INDEX=3;
float coef[MAX_INDEX]={2,7,0,8}
(계수는 표현을 했는데 차수(제곱,세제곱 등등)는 어떻게 표현하지? 2차원 배열을 써야하나?)라는 의문점이 문득 들 수 있습니다.
최고차항이 낮은 다항식의 경우, 위의 예제에서 차수는 계수를 저장한 index에서 가장 낮은 index=0이 최고차항인 x^세제곱이고, index1=x^제곱....을 표현한다! 라고 계수저장과 반대로 이해하시면 됩니다.
그렇다면 10x^1000차수 +10x^2+100 의 다항식같은 경우에는 비어있는 index값, 계수값을 전부 0으로 채워야 할까요?
결론은 No!!!! (손아픕니다..)
이런 경우는 희소 다항식이라고 표현하고, 2차원 배열을 이용합니다. 2차원 배열이다! [][] ==내가 원하는 두가지의 정보를 연속적으로 저장할 수 있다!!!!
2차원 배열을 사용해 한개의 행에 최고차항이 큰 순서부터 계수와 차수를 저장하면 희소 다항식을 쉽게 표현할 수 있습니다.
int poly[][]={ //<계수, 지수>
{10,1000} //첫번째 값은 계수, 두번째 값은 차수!
,{10,2},
{10,0}
};
# degree = 차수
#Coefficient 줄여서 coef=계수
#polynomial 줄여서 poly = 다항식
한방 정리
순차 자료구조 | 장점 | 단점 |
배열을 활용해 정보를 연이어 저장 할 수 있다. | 특정 원소를 삽입, 삭제 할 경우 추가적인 overhead가 발생한다. | |
물리적 주소(1차원 배열)의 순서로 간단하게 구성되어 있다. | ||
읽기, 쓰기, 순차 접근이 좋다. | 삽입, 삭제가 비효율적이다. |
긴 글 읽어 주셔서 감사합니다.
모두 화이팅!!
'ComputerScience > Algorithm concepts' 카테고리의 다른 글
[C언어/자료구조] Stack. 스택의 의미와 필수 함수, 응용 (0) | 2021.09.16 |
---|---|
[자료구조] 중위표기식과 후위표기식 간 변환방법 완벽하게 부수기 +_+ | stack의 응용 (2) | 2021.09.16 |
[C언어] 연결리스트(linkedList)와 원형 연결리스트! _C로배우는 쉬운 자료구조 (0) | 2021.09.09 |
[C언어]알고리즘 (Time Complexity)시간 복잡도와 빅오 표기법 (0) | 2021.08.24 |