본문 바로가기
[C Data structure] C 자료 구조

[C] 자료구조 - 배열 스택 (Array Stack)

by codeomni 2023. 11. 9.
반응형

 

이번 주제는 스택(Stack)입니다.

스택은 선입후출(First In Last Out)의 구조로 먼저 들어간 데이터보다 나중에 들어간 데이터가 먼저 나오는 자료구조입니다.

뒤로 가기와 앞으로 가기의 기능 구현 등을 포함한 우리가 사용하고 있는 여러 프로그램에서 볼 수 있습니다.

 

스택은 배열링크드 리스트로 구현 가능 합니다.

그 중에서 배열은 구현이 쉽다는 장점과 용량을 동적으로 할당할 수 없다는 단점을 가지고 있습니다.

 


배열 스택 구조체

이전에 구현했던 자료들처럼 스택을 구성하는 노드들을 만듭니다.

1
2
3
4
5
// AS 노드
typedef struct Node
{
    ElementType Data;
} Node;

배열 스택을 구성하는 노드 구조체입니다.

연결 리스트처럼 다음 노드의 위치를 저장할 필요가 없기 때문에, 다음 노드를 저장할 포인터가 필요 없이 데이터를 담을 멤버로 구성합니다.

 

1
2
3
4
5
6
7
// AS 구조체
typedef struct tagArrayStack
{
    int Capacity;
    int Top;
    Node* Nodes;
} ArrayStack;

생성한 배열 스택의 용량 Capacity, 현재 높이를 저장하고 있는 Top, 스택에 넣을 노드 배열로 구성되어 있습니다.

 


배열 스택 - 구현

배열 스택의 주요 연산은 초기화, 데이터 추가, 제거, 맨 위 데이터의 확인 등이 있습니다.

  • 스택 생성(Create)
  • 스택 제거(Destroy)
  • 스택 데이터 추가 (Push)
  • 스택 데이터 제거(Pop)
  • 스택 맨 위 데이터 반환(Top)
  • 스택 크기(GetSize)
  • 스택 비어 있는지 확인(IsEmpty)

 

1. 배열 스택 - 생성

배열 스택을 생성하고 초기화를 하는 연산입니다.

스택 구조체와 용량을 받아서 크기만큼 할당합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
// AS 생성
void AS_CreateStack(ArrayStack** Stack, int Capacity)
{
    // 스택을 자유 저장소에 할당
    (*Stack) = (ArrayStack*)malloc(sizeof(ArrayStack));
    
    // 스택 용량만큼 노드를 자유 저장소에 할당
    (*Stack)->Nodes = (Node*)malloc(sizeof(Node) *Capacity);
 
    // 스택 용량과 Top 초기화
    (*Stack)->Capacity = Capacity;
    (*Stack)->Top = 0;
}

malloc () 함수를 사용해서 배열 스택과 노드를 동적으로 할당합니다.

생성한 배열 스택은 현재 비어 있으므로 Top를 0으로 초기화 합니다.

 

2. 배열 스택 - 소멸

자유저장소에 동적으로 생성했던 배열 스택과 노드를 소멸시키는 연산입니다.

free() 함수를 사용해서 할당한 메모리를 해제합니다.

1
2
3
4
5
6
7
8
9
// AS 소멸
void AS_DestroyStack(ArrayStack* Stack)
{
    // 배열 스택 노드를 자유 저장소에서 해제
    free(Stack->Nodes);
 
    // 배열 스택을 자유 저장소에서 해제
    free(Stack);
}

메모리가 누수되지 않도록, 먼저 할당된 노드들을 free() 함수로 해제하고 배열 스택을 해제합니다.

 

3. 배열 스택 - 데이터 삽입(Push)

생성된 배열 스택에 데이터를 추가하는 Push 연산입니다.

해당 연산은 Data를 받아서 Top 위치에 넣어주는 연산입니다.

C언어에서 인덱스는 0부터 시작하기 때문에 스택을 초기화할 때 Top의 위치를 0으로 했습니다.

현재 인덱스에 Data를 넣어준 다음에 스택의 위치를 나타내주는 Top의 위치를 증가시킵니다.

1
2
3
4
5
6
7
8
// AS 데이터 삽입
void AS_Push(ArrayStack* Stack, ElementType Data)
{
    int Position = Stack->Top;
 
    Stack->Nodes[Position].Data = Data;
    Stack->Top++;
}

코드 구현에 따라서 -1로 초기화하고 스택의 위치를 증가시킨 다음에 Data를 넣주는 방식도 있습니다.

1
2
3
4
5
6
7
8
9
10
// AS Top을 -1로 초기화
void AS_CreateStack(ArrayStack** Stack, int Capacity)
{
    (*Stack)->Top = -1;
}
// AS 데이터 삽입
void AS_Push(ArrayStack* Stack, ElementType Data)
{
    Stack->Nodes[++Stack->Top].Data = Data;
}

 

4. 배열 스택 - 데이터 제거(Pop)

스택에서 넣었던 마지막 요소를 빼주는 연산입니다.

마지막 요소를 꺼내주는 연산으로 Top의 이전 요소에 접근합니다.

1
2
3
4
5
6
7
// AS 데이터 제거
ElementType AS_Pop(ArrayStack* Stack)
{
    int Position = --(Stack->Top);
 
    return Stack->Nodes[Position].Data;
}

배열 스택의 Top 위치를 1만큼 감소시키고, 해당 위치의 노드의 데이터에 접근합니다.

 

5. 배열 스택 - 맨 위 데이터 반환(Top)

배열 스택의 Top의 위치를 구하는 연산입니다.

Top으로 접근하면 간단하게 구할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
// AS 맨 위 데이터 반환
ElementType AS_Top(ArrayStack* Stack)
{
    int Position = Stack->Top - 1;
 
    if (AS_IsEmpty(Stack))
    {
        printf("Stack is Empty\n");
        exit(-1);
    }
    
    return Stack->Nodes[Position].Data;
}

 

6. 배열 스택 - 크기

배열 스택의 크기를 구하는 연산입니다.

우리가 스택의 구조체에 만들어줬던 Top와 스택의 크기는 동일하기 때문에 Top를 반환해줍니다.

1
2
3
4
5
// AS 크기 반환
int AS_GetSize(ArrayStack* Stack)
{
    return Stack->Top;
}

 

7. 배열 스택 - 비여있는지 여부

배열 스택이 비여있는지 확인하는 연산입니다.

현재 Top의 위치가  0일 경우 해당 배열 스택은 비여있기 때문에 확인해서 반환합니다.

1
2
3
4
5
// AS 비여있는지 여부
int AS_IsEmpty(ArrayStack* Stack)
{
    return (Stack->Top == 0);
}

 

댓글