본문 바로가기

학습공간/C, 자료구조와 알고리즘

[4장] 스택

반응형

스택에 대한 문제풀이 내용이다.
스택(Stack)이란?

 - 한마디로 표현하면 선입후출, FILO(First In, Last Out) 형태의 자료구조이다.

 - 주로 컴파일러에서 괄호검사를 시행할 때, '{' 중괄호는 '}' 중괄호, '('소괄호는 ')' 소괄호로 닫혀야 한다. (Syntex Check)

 - 여러 줄의 구문들이 섞여 있을 때 쌍쌍의 짝이 맞아 떨어져서 최종적으로 스택이 공백이 되어있어야 정상일 것이다.

예제를 통해 괄호검사 프로그램정적 배열로도 구현해보고, 포인터 변수를 활용한 동적 배열로도 구현해 볼 것이다.

스택을 구현하기에 앞서 사용할 배열 리스트를 학습해보자.

 

정적 배열 리스트

#include <stdio.h>
#include <stdlib.h>
#define MAX_LIST_SIZE 100
typedef int element;
typedef struct
{
 int list[MAX_LIST_SIZE];
 int length;
}ArrayListType;
void error(char *message);
void init(ArrayListType *L);
int is_empty(ArrayListType *L);
int is_full(ArrayListType *L);
void add_list(ArrayListType *L, int position, element item);
element Delete(ArrayListType *L, int position);
void display(ArrayListType *L);
void add_last(ArrayListType *list, int item);
void add_last(ArrayListType *list, int item);
void add_first(ArrayListType *list, int item);
void clear(ArrayListType *list);
void replace(ArrayListType *list, int pos, int item);
int is_in_list(ArrayListType *list, int item);
int get_entry(ArrayListType *list, int pos);
int get_length(ArrayListType *list);
void add(ArrayListType *list, int pos, int item);
int main(void)
{
 ArrayListType *plist;
 int i;
 int temp;
 int temp2;
 
 printf("plist 생성\n");
 plist = (ArrayListType *)malloc(sizeof(ArrayListType));
 
 
 init(plist);
 for(i=10;i<=30;i+=10){
  add_last(plist , i);
 }
 
 display(plist);
 
 printf("\n첫번째위치에 100 삽입\n");
 add_first(plist, 100);
 display(plist);
 
 printf("\n마지막위치에 200 삽입\n");
 add_last(plist, 200);
 display(plist);
 
 printf("\n두번째 요소[1] 50으로 치환\n");
 replace(plist, 1, 50);
 display(plist);
 
 printf("\n세번째 요소[2]에 300 삽입\n");
 add(plist, 2, 300);
 display(plist);
 
 printf("\n요소가 몇번 인덱스에 있는지? (item): ");
 scanf("%d", &temp);
 temp2 = is_in_list(plist, temp);
 if(temp2 != 0)
  printf("%d번 인덱스에 있음\n", temp2);
 else
  printf("%d는 리스트에 없음\n");
 
 printf("\n몇번째 요소? : ");
 scanf("%d", &temp);
 printf("list[%d] -> %d\n", temp, get_entry(plist, temp));
 
 printf("\n현재 리스트의 길이 : %d\n", get_length(plist));
 
 free(plist);
 
 
}
void add_last(ArrayListType *list, int item){
 if(!is_full(list)){
  list->list[list->length] = item;
  list->length++;
 }
 else
  printf("리스트 오버플로우!\n");
}
void add_first(ArrayListType *list, int item){
 int i;
 if(!is_full(list)){
  for(i=list->length;i>0;i--){
   list->list[i] = list->list[i-1];
   
  }
  list->list[0] = item;
  list->length++;
 }
 else
  printf("리스트 오버플로우!\n");
}
void clear(ArrayListType *list){
 int i;
 for(i=0;ilength;i++){
  list->list[i] = 0;
 }
 list->length = 0;
 
}
void replace(ArrayListType *list, int pos, int item){
 
 if(pos >= list->length){
  printf("pos 위치지정 오류 \n");
  exit(0);
  
 }
 
 list->list[pos] = item;
 
}
int is_in_list(ArrayListType *list, int item){
 
 int i;
 for(i=0;ilength;i++){
  if(list->list[i] == item)
   return i;
 }
 
 return 0;
 
}
int get_entry(ArrayListType *list, int pos){
 if(pos >= list->length){
  printf("pos 위치지정 오류 \n");
  return -1;
  
 }
 
 return list->list[pos];
 
}
int get_length(ArrayListType *list){
 
 return list->length;
 
}
void error(char *message){
 fprintf(stderr,"%s\n", message);
 exit(1);
}
void add(ArrayListType *list, int pos, int item){
 int i;
 if(!is_full(list)){
  for(i=list->length;i>pos;i--){
   list->list[i] = list->list[i-1];
   
  }
  list->list[pos] = item;
  list->length++;
 }
 else
  printf("리스트 오버플로우!\n");
 
}
void init(ArrayListType *L)
{
 L->length = 0;
}
int is_empty(ArrayListType *L)
{
 return L -> length == 0;
}
int is_full(ArrayListType *L)
{
 return L -> length == MAX_LIST_SIZE;
}
void add_list(ArrayListType *L, int position, element item)
{
 if(!is_full(L))
 {
  int i;
  for( i = 0 ; i < L->length ; i++ )
   if( L->list[i] >= item )
    break;
   position = i;
   for(i=(L->length-1); i>=position; i--)
   {
    L->list[i+1] = L->list[i];
   }
   L->list[position] = item;
   L->length++;
 }
}
element Delete(ArrayListType *L, int position)
{
 int i;
 element item;
 
 if((position <0) ||( position >=L->length))
 {
  error("위치오류");
 }
 item = L -> list[position];
 for(i = position; i<(L->length-1); i++)
 {
  L->list[i] = L->list[i+1];
 }
 L-> length--;
 return item;
}
void display(ArrayListType *L)
{
 int i;
 for(i = 0; i< L->length; i++)
  printf("%d ",L->list[i]);
 
 printf("\n");
}

 

Case 1: 괄호검사 프로그램(정적 배열 스택)

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

#define MAX_STACK_SIZE 100

#define TRUE 1

#define FALSE 0

 

typedef char element;

 

typedef struct{

        element stack[MAX_STACK_SIZE];

        int top;

}StackType;

 

void init(StackType *s){

        s->top = -1;

}

 

int is_empty(StackType *s){

         return (s->top == -1);

}

 

int is_full(StackType *s){

        return (s->top == (MAX_STACK_SIZE-1));

}

 

void push(StackType *s, element item){

        if(is_full(s)){

                fprintf(stderr, "스택 포화 에러\n");

                return;

        }

        

        else s->stack[++(s->top)] = item;

}

 

void display(StackType *s){

        int i;

        for(i=0;i<=s->top;i++){

                printf("%c ", s->stack[i]);

                

        }

        printf("\n");           

}

 

element pop(StackType *s){

        if(is_empty(s)){

                fprintf(stderr, "스택 공백 에러 \n");

                exit(1);

        }

        else return s->stack[(s->top)--];

}

 

element peek(StackType *s){

        if(is_empty(s)){

                fprintf(stderr,"스택 공백 에러\n");

                exit(1);

        }

        else return s->stack[s->top];

}

 

int check_matching(char *in){

        StackType s;

        char ch, open_ch;

        

        int i, n = strlen(in);

        init(&s);

        

        for(i=0;i<n;i++){

                ch = in[i];

                switch(ch){

                case '(': case '[': case '{':

                        push(&s, ch);

                        printf("현재 스택의 상태 : ");

                        display(&s);

                        system("pause");

                        break;

                        

                case ')': case ']': case '}':

                        if(is_empty(&s)) return FALSE;

                        else{

                                open_ch = pop(&s);

                                printf("현재 스택의 상태 : ");

                                display(&s);

                                system("pause");

                                

                                if( (open_ch == '(' && ch != ')') ||

                                        (open_ch == '(' && ch != ')') ||

                                        (open_ch == '(' && ch != ')')) {

                                        return FALSE;

                                }                       

                                break;

                        }

                }

        }

        if(!is_empty(&s)) return FALSE;

        return TRUE;

}

 

int main(){

        char operation[100];

        printf("수식을 입력하세요 > "); /* ex) {A[(i+1)]=0;} */

        scanf("%s", operation);

        

        if(check_matching(operation) == TRUE)

                printf("괄호검사 성공\n");

        else

                printf("괄호검사 실패\n");  

}

int 타입의 top 변수에 스택의 인덱스를 관리하면서 배열 최대값에 도달하지 않도록 관리하고 있다.

아래 똑같은 코드에서 해당 구조체의 주소를 관리하는 top 포인터 변수를 사용하여 스택 포화 문제점을 해결해보자.

 

Case 2: 괄호검사 프로그램(동적 배열 스택)

#include <stdio.h>

#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#define TRUE 1
#define FALSE 0
typedef struct StackNode{
 int item;
 struct StackNode *link;
}StackNode;
typedef struct{
 StackNode *top;
}LinkedStackType;
void init(LinkedStackType *s)
{
 s->top = NULL;
}
int is_empty(LinkedStackType *s)
{
 return (s->top == NULL);
}
int pop(LinkedStackType *s)
{
 if(is_empty(s)){
  fprintf(stderr, "stack is empty!\n");
  exit(1);
 }
 else{
  StackNode *temp=s->top;
  int item = temp->item;
  s->top = s->top->link;
  free(temp);
  return item;
 }
 
}
void push(LinkedStackType *s, int item)
{
 StackNode *temp=(StackNode *)malloc(sizeof(StackNode));
 if(temp == NULL){
  fprintf(stderr,"메모리할당에러\n");
  return;
 }
 else{
  temp->item = item;
  temp->link = s->top;
  s->top = temp;
 }
}
int check_matching(char *in){
 LinkedStackType s;
 char ch, open_ch;
 int i,n = strlen(in);
 init(&s);
 
 for(i=0;i<n;i++){
  ch = in[i];
  switch(ch){
  case '(': case '[' : case'{':
   push(&s,ch);
   break;
  case ')': case ']': case'}':
   if(is_empty(&s)) return FALSE;
   else{
    open_ch = pop(&s);
    if((open_ch == '(' && ch != ')') ||
     (open_ch == '[' && ch!= ']') ||
     (open_ch == '{' && ch!= '}'))
     return FALSE;
    break;
   }
  }
 }
 if(!is_empty(&s)) return FALSE;
 return TRUE;   
}
void main(){
 if(check_matching("{A[(i+1)]=0;}") == TRUE)
  printf("괄호검사성공\n");
 else
  printf("괄호검사실패\n");
}

 

심화과정 Linked Stack(연결 리스트를 활용한 스택)

#include <stdio.h>

#include <stdlib.h>

typedef int element;

typedef struct StackNode{

        element data;

        struct StackNode *link;

} StackNode;

typedef struct StackType{

        StackNode *top;

} QueueType;

void error(char *message){

        fprintf(stderr,"%s\n",message);

        exit(1);

}

void init(StackType *s){

        s->top = NULL;

}

int is_empty(StackType *s){

        return (s->top == NULL);

}

int is_full(StackType *s){

        return 0;

}

void push(StackType *s, element item){

        StackNode *Newnode = (StackNode *)malloc(sizeof(StackNode));

        if(Newnode == NULL)

                error("메모리를 할당할 수 없습니다");

        else{

                Newnode->data = item;

                Newnode->link = s->top;

                s->top = Newnode;

        }

}

element pop(StackType *s){

        if(is_empty(s))

                error("스택이 비어 있습니다");

        else{

                StackNode *Newnode = s->top;

                element item = Newnode->data;

                s->top = s->top->link;

                free(Newnode);

                return item;

        }

}

element peek(StackType *s){

        if(is_empty(s))

                error("스택이 비어 있습니다");

        else{

                return s->top->data;

        }

}

 

void display(StackType *s){

        StackNode *temp = s->top;

        while(temp != NULL){

                printf("%d-> ",temp->data);

                temp = temp->link;

        }

        printf("\n");

}

 

element get_count(StackType *s){

        int count=0;

        StackNode *temp = s->top;

        while(temp != NULL){

                count++;

                temp = temp->link;

        }

        printf("현재 스택의 item의 개수 : %d개\n", count);

        return count;

}

void main(){

        StackType s;

 

        init(&s);

        push(&s, 1);

        push(&s, 2);

        push(&s, 3);

        push(&s, 4);

        pop(&s);

        display(&s);

        get_count(&s);

}

반응형

'학습공간 > C, 자료구조와 알고리즘' 카테고리의 다른 글

[6장] 연결 리스트 I  (0) 2019.11.23
[5장] 큐  (0) 2019.11.22
[3장] 배열, 구조체, 포인터  (0) 2019.11.21
[2장] 순환  (0) 2019.11.21
[1장] 자료구조와 알고리즘  (3) 2019.11.21