C# 자료구조 배열(Array) 개념 배열의 차원, 정적배열과 동적배열, 원형배열

 

자료구조 배열(Array)

배열은 연속적인 메모리 상에 동일한 데이터 타입의 요소들을 순차적으로 일렬로 저장하는 자료구조입니다. 순차적으로 나열된 배열요소는 각 요소마다 Index를 붙이는데 배열을 A라고 했을 경우 첫 배열요소는 A[0], 두번째 배열요소는 A[1], ... 등 으로 배열 index를 붙입니다.

 

하나의 배열은 고정된 크기를 가지고 배열 index를 사용할 경우 배열요소를 바로 접근할 수 있습니다. 배열A가 100개 배열요소가 있는 가정하에 A[0], A[50], A[99] 등 접근하는 시간은 동일하고, 모두 해당 요소를 즉시 접근하여 배열요소 값을 읽거나 쓸 수 있습니다. 

 

배열은 프로그래밍 언어에서 사용하는 아주 기초적인 자료구조입니다.

C#의 배열은 배열 객체로서 메모리 상에 배열에 대한 정보를 가지고, System.Array class로부터 생성됩니다. System.Array 클래스의 속성과 메서드를 사용할 수 있는 객체 인스터스입니다.

 

배열의 차원(Dimension)

배열의 차원은 한 배열요소를 선택하기 위한 인덱스의 수입니다.

배열 A의 배열요소가 10개이고, 이를 메모리 상에 일렬로 저장하면 각 요소는 0부터 시작하는 배열 인덱스를 갖습니다. 배열 A의 첫번째 배열요소는 A[0]이고, 두번째 요소는 A[1]로 표현됩니다. 

 

1차원 배열은 한 줄로 연결된 배열을 말하고, 배열 요소를 서낵할 때는 1개의 인덱스만 필요합니다.

2차원 배열은 행(row)과 열(column)을 갖는 배열을 의미합니다. 3개의 행과 4개의 열을 갖는 2차원 배열이 있다면 배열 요소를 선택하기 위한 행과 열 2개의 Index가 필요합니다.

 

C#은 1차원 배열~32차원 배열까지 지원합니다!

 

가변 배열(Jagged Array)

가변 배열은 배열요소가 배열 타입인 경우를 말합니다. 배열요소는 서로 다른 차원과 크기를 갖는 배열일 수가 있는데요, C#에서는 다차원 배열일 경우 [,] 처럼 콤마로 차원을 분리하고, 가변 배열은 [][] 처럼 배열의 배열로서 사각괄호를 겹쳐서 표현합니다. 가변배열은 일반 다차원 배열했을 때 공간 낭비가 심해지는 경우와 또는 각 차원마다 다른 배열 크기를 가져야 하는 경우에 유용할 수 있습니다.

//Jagged Array (가변 배열)

int[][] A = nes int[3][];

 

//각 1차 배열요소당 서로 다른 크기의 배열 할당

A[0] = new int[2];

A[1] = new int[6]{1,2,3,4,5,6};

A[2] = new int[3]{9,8,7};

 

정적배열(Static Array)과 동적 배열(Dynamic Array)

배열은 일정한 크기의 연속된 배열요소들의 집합입니다. 배열 크기는 초기화 시 미리 지정되는데요, 정적 배열(Static Array)은 처음 지정한 고정 크기 그대로 계쏙 유지하는 배열입니다.

C#에서 기본적으로 사용하는 배열 문법 예를 들어 int[], string[,] 의 식으로 선언된 배열들은 모두 정적 배열에 해당합니다.

그러나 배열의 최대크기를 미리 알 수 없는 경우도 있고 배열 중간에 확장해야 하는 경우도 있습니다. 배열이 꽉 찼을 경우 배열을 확장하거나 반대로 배열이 너무 적은 요소를 가질 때 축소하는 기능을 가는 배열을 동적 배열이라고 합니다.

새로운 요소가 추가될 때마다 배열크기를 하나씩 늘려가는 것입니다. 새 배열요소를 추가할 때, 기존 배열의 크기보다 1개 더 큰 임시배열을 생성하고, 임시배열에 모든 요소를 복사한 다음 다시 임시배열을 기존배열에 할당하고 배열 마지막 요소에서 새 배열요소로 추가하는 것입니다.

public class DynamicArray

{

   private object[] arr= new object[0];

 

   public void Add(object elelment)

   {

      var temp = new object[arr.Length +1];

      for(int i=0; i< arr.Lenght; i++)

      {

         temp[i] = arr[i];

      }

       arr = temp;

       arr[arr.Length-1] = element;

   }

}

필요할 때마다 배열을 하나씩 동적으로 증가시키는 방식으로 꼭 필요한 공간만 사용한다는 장점이 있지만 매번 ㅐㅅ로운 배열공간을 생성하고 기존 배열요소들을 전부 복사해 넣어야 한다는 단점이 있습니다. 

 

4. 원형 배열(Circular Array)

원형배열은 고정된 크기의 배열을 마치 양 끝이 연결된 것처럼 사용할 수 있게 한 자료구조입니다. 원형 버퍼(Circular Buffer), 링 버퍼(Ring Buffer)라고 불립니다. 배열의 크기가 N 일때, 배열의 마지막 요소(N-1) 에 도착하면 다음 배열요소는 첫번째 요소(0) 으로 순환하는 구조입니다.

원형배열은 처음들어간 데이터가 먼저나오는 FIFO(First in first out) 구조로서 데이터 버퍼에 적합합니다. 비원형의 일반 배열은 마지막 들어간 데티어가 먼저나오는 LIFO(Last in first out) 구조의 버퍼로 적합합니다. 원형 배열은 FIFO 구조를 가진 큐(Queue)를 구현하거나 데이터 스트림 버퍼 를 구현할 때 사용되곤 합니다.

원형배열 자체는 고정된 크기를 갖는 일반 배열과 동일하지만 배열을 순환하는 구조로 만들어야 하기에 배열 index를 증가시킬 때에는 mod 연산자를 사용해서 마지막 배열의 다음 인덱스가 첫 배열 index로 돌아오게 합니다.

 

C#에서 mod 연산자는 %로 표시됩니다. 나머지를 구할 때 사용되는데 10%7 은 10을 7로 나눈 나머지 3 이 됩니다. 

index = (index + 1)% A.Length;

 

예를 들어보겠습니다.

배열에 a,b,c,d,e,f,g,h를 넣고 배열index를 순환하도록 조정하면 임의의 인덱스에서 시작하여 N개를 순차적으로 출력합니다.

char[] A = "abcdefgh".ToCharArray();

int startIndex = 2;

 

for(int i=0; i< A.Lenght; i++)

{

 int index = (startIndex +i) % A.Lenght;

 Console.Write(A[index]);

 

}

 

반응형