Presentation is loading. Please wait.

Presentation is loading. Please wait.

스택 스택 추상자료형 스택 스택의 구현 스택의 응용 한빛미디어(주).

Similar presentations


Presentation on theme: "스택 스택 추상자료형 스택 스택의 구현 스택의 응용 한빛미디어(주)."— Presentation transcript:

1 스택 스택 추상자료형 스택 스택의 구현 스택의 응용 한빛미디어(주)

2 자료구조 스택에 대해서 이해한다. 스택의 특징과 연산 방법을 알아본다. 순차 자료구조 방법을 이용한 스택과 연결 자료구조 방법을 이용한 스택을 구현해본다. 스택의 응용 방법을 알아본다.

3 스택(stack) 접시를 쌓듯이 자료를 차곡차곡 쌓아 올린 형태의 자료구조
스택에 저장된 원소는 top으로 정한 곳에서만 접근 가능 top의 위치에서만 원소를 삽입하므로 먼저 삽입한 원소는 밑에 쌓이고, 나중에 삽입한 원소는 위에 쌓인다. 마지막에 삽입(Last-In)한 원소는 맨 위에 쌓여 있다가 가장 먼저 삭제(First-Out)된다. ☞ 후입선출 구조 (LIFO, Last-In-First-Out) [그림 6-2] 스택의 구조

4 후입선출 구조의 예1 : 연탄 아궁이 연탄을 하나씩 쌓으면서 아궁이에 넣으므로 마지막에 넣은 3번 연탄이 가장 위에 쌓여 있다. 연탄을 아궁이에서 꺼낼 때에는 위에서부터 하나씩 꺼내야 하므로 마지막에 넣은 3번 연탄을 가장 먼저 꺼내게 된다. [그림 6-3] 스택 자료구조의 예_연탄아궁이

5 후입선출 구조의 예2 : 슈퍼맨의 옷 갈아입기 수퍼맨이 옷을 벗는 순서 슈퍼맨이 옷을 입는 순서
후입선출 구조의 예2 : 슈퍼맨의 옷 갈아입기 수퍼맨이 옷을 벗는 순서 ①장화 → ②망토 → ③빨간팬츠 → ④파란옷 슈퍼맨이 옷을 입는 순서 ④파란옷 → ③빨간팬츠 → ②망토 → ①장화 [그림 6-4] 스택 자료구조의 예_슈퍼맨 옷 입기

6 스택의 연산 스택에서의 삽입 연산 : push 스택에서의 삭제 연산 : pop
[그림 6-5] 만원 전철에서의 pop과 push

7 스택에서의 원소 삽입/삭제 과정 공백 스택에 원소 A, B, C를 순서대로 삽입하고 한번 삭제하는 연산과정 동안의 스택 변화
[그림 6-6] 스택의 자료 삽입ㆍ삭제 과정

8 스택에 대한 추상 자료형 ADT Stack 데이터 : 0개 이상의 원소를 가진 유한 순서 리스트 연산 :
    데이터 :  0개 이상의 원소를 가진 유한 순서 리스트     연산 :           Stack ∈ Stack; item ∈ Element;           createStack( ) ::= create an empty stack;                 // 공백 스택을 생성하는 연산           push(Stack, item) ::= insert item onto the top of Stack;                 // 스택의 top에 item(원소)을 삽입하는 연산           isEmpty(Stack) ::= if (Stack is empty) then  return  true                              else  return  false;                 // 스택이 공백인지 아닌지를 확인하는 연산           pop(Stack) ::= if (isEmpty(Stack)) then return error                          else { delete and return the top item of Stack };                 // 스택의 top에 있는 item(원소)을 스택에서 삭제하고 반환하는 연산           delete(Stack) ::= if (isEmpty(Stack)) then return error                             else delete the top item;                 // 스택의 top에 있는 item(원소)을 삭제하는 연산           peek(Stack) ::= if (isEmpty(Stack)) then return error                           else  return  (the top item of  the Stack);                 // 스택의 top에 있는 item(원소)을 반환하는 연산 End  Stack

9 스택의 push 알고리즘 top ← top+1; S(top) ← x; push(S, x) top ← top+1; // ①
스택 S에서 top이 마지막 자료를 가리키고 있으므로 그 위에 자료를 삽입하려면 먼저 top의 위치를 하나 증가 만약 이때 top의 위치가 스택의 크기(stack_SIZE)보다 크다면 오버플로우(overflow)상태가 되므로 삽입 연산을 수행하지 못하고 연산 종료 S(top) ← x; 오버플로우 상태가 아니라면 스택의 top이 가리키는 위치에 x 삽입 push(S, x) top ← top+1; // ① if (top > stack_SIZE) then overflow; else S(top) ← x; // ② end push( )

10 스택의 pop 알고리즘 return S(top); top ← top-1; pop(S)
if (top = 0) then error; else { return S(top); // ① top ← top-1; // ② } end pop( )

11 순차 자료구조를 이용한 스택의 구현 순차 자료구조인 1차원 배열을 이용하여 구현 스택의 크기 : 배열의 크기
스택에 저장된 원소의 순서 : 배열 원소의 인덱스 인덱스 0번 : 스택의 첫번째 원소 인덱스 n-1번 : 스택의 n번째 원소 변수 top : 스택에 저장된 마지막 원소에 대한 인덱스 저장 공백 상태 : top = -1 (초기값) 포화 상태 : top = n-1 [그림 6-7] 스택에 대한 1차원 배열 표현

12 크기가 5인 1차원 배열의 스택에서 연산 수행과정 [그림 6-8] 순차 자료구조를 사용한 스택에서의 연산 과정

13 순차 자료구조를 이용한 스택 프로그램 01 #include <stdio.h> 27 void del( )
02  #include <stdlib.h> 03  #define  STACK_SIZE 100 04  05  typedef int element; 06  element stack[STACK_SIZE]; 07  int top= -1; 08  09  void push(element item) 10  { 11      if(top >= STACK_SIZE -1) { 12          printf("\n\n Stack is FULL ! \n"); 13          return; 14      } 15      else stack[++top]=item; 16  } 17  18  element pop( ) 19  { 20      if(top==-1) { 21          printf("\n\n Stack is Empty!!\n"); 22          return 0; 23      } 24      else return stack[top--]; 25  } 26 27  void del( ) 28  { 29      if(top==-1) { 30          printf("\n\n Stack is Empty !\n"); 31          exit(1); 32      } 33      else top--; 34  } 35  36  element peek( ) 37  { 38      if(top==-1){ 39          printf("\n\n Stack is Empty !\n"); 40          exit(1); 41      } 42      else return stack[top]; 43  } 44  45  void printStack( ) 46  { 47      int i; 48      printf("\n STACK [ "); 49      for(i=0; i<=top; i++) 50          printf("%d ",stack[i]); 51      printf("] "); 52  } 53 

14 54  void main(void) 55  { 56      int item;    57      printStack( ); 58      push(1); 59      printStack( );    60      push(2); 61      printStack( );    62      push(3); 63      printStack( ); 64  65      item = peek( ); 66      printStack( ); 67      printf("peek top => %d", item); 68  69      del( ); 70      printStack( ); 71  72      item = pop( ); 73      printStack( ); 74      printf("\t pop top => %d", item); 75      76      item = pop( ); 77      printStack( ); 78      printf("\t pop top => %d", item); 79      80      pop( ); 81  82      getchar( ); 83  }

15 실행 결과 순차 자료구조로 구현한 스택의 장점 순차 자료구조로 구현한 스택의 단점
순차 자료구조인 1차원 배열을 사용하여 쉽게 구현 순차 자료구조로 구현한 스택의 단점 물리적으로 크기가 고정된 배열을 사용하므로 스택의 크기 변경 어려움 순차 자료구조의 단점을 그대로 가지고 있다.

16 연결 자료구조를 이용한 스택의 구현 단순 연결 리스트를 이용하여 구현 스택의 원소 : 단순 연결 리스트의 노드
스택 원소의 순서 : 노드의 링크 포인터로 연결 push : 리스트의 마지막에 노드 삽입 pop : 리스트의 마지막 노드 삭제 변수 top : 단순 연결 리스트의 마지막 노드를 가리키는 포인터 변수 초기 상태 : top = null [그림 6-9] 스택에 대한 단순 연결 리스트 표현

17 단순 연결 리스트의 스택에서 연산 수행과정 A, B, C를 순서대로 삽입하면서 스택을 생성한 후에 원소 하나를 삭제하는 과정
① 공백 스택 생성 : create(stack); ③ 원소 B 삽입 : push(stack, B); ⑤원소 삭제 : pop(stack); ② 원소 A 삽입 : push(stack, A); ④ 원소 C 삽입 : push(stack, C); [그림 6-9-1] 연결 자료구조를 사용한 스택에서의 연산 과정

18 단순 연결 리스트를 이용한 스택 프로그램 001 #include <stdio.h>
002  #include <stdlib.h> 003  #include <string.h> 004  005  typedef int element; 006  007  typedef struct stackNode {            008      element data; 009      struct stackNode *link; 010  }stackNode; 011  012  stackNode* top; 013  014  void push(element item) 015  {    016      stackNode* temp=(stackNode *)malloc(sizeof(stackNode)); 017      temp->data = item; 018      temp->link = top;    019      top = temp; 020  } 021  022  element pop( ) 023  { 024      element item; 025      stackNode* temp=top; 026  027      if(top == NULL) {      028          printf("\n\n Stack is empty !\n");     029          return 0; 030      } 031      else { 032          item = temp->data;    033          top = temp->link;     034          free(temp);                035          return item; 036      } 037  } 038  039  element peek( ) 040  {    041      element item; 042      if(top == NULL) {         043          printf("\n\n Stack is empty !\n");     044          return 0;     045      } 046      else { 047          item = top->data; 048          return item; 049      } 050  } 051 

19 052 void del( ) 053 { staackNode*temp; 055      if(top == NULL) {        056          printf("\n\n Stack is empty !\n");    057          058      } 059      else { 060          temp = top;    061          top = top->link;     062          free(temp); 063      } 064  } 065  066  void printStack( ) 067  { 068      stackNode* p=top; 069      printf("\n STACK [ "); 070      while(p){ 071          printf("%d ",p->data); 072          p = p->link; 073      } 074      printf("] "); 075  } 076  077  void main(void) 078  {         079      element item; 080      top = NULL;    081      printStack( ); 082      push(1);

20 실행 결과

21 역순 문자열 만들기 스택의 후입선출(LIFO) 성질을 이용 문자열을 순서대로 스택에 push 하기
[그림 6-10] 역순 문자열 만들기_① 순서대로 스택에 삽입하기

22 스택을 pop하여 문자열로 저장하기 [그림 6-11] 역순 문자열 만들기_② 스택에서 삭제하여 문자열 만들기

23 시스템 스택 프로그램에서의 호출과 복귀에 따른 수행 순서를 관리
가장 마지막에 호출된 함수가 가장 먼저 실행을 완료하고 복귀하는 후입선출 구조이므로, 후입선출 구조의 스택을 이용하여 수행순서 관리 함수 호출이 발생하면 호출한 함수 수행에 필요한 지역변수, 매개변수 및 수행 후 복귀할 주소 등의 정보를 스택 프레임(stack frame)에 저장하여 시스템 스택에 삽입 함수의 실행이 끝나면 시스템 스택의 top 원소(스택 프레임)를 삭제(pop)하면서 프레임에 저장되어있던 복귀주소를 확인하고 복귀 함수 호출과 복귀에 따라 이 과정을 반복하여 전체 프로그램 수행이 종료되면 시스템 스택은 공백 스택이 된다.

24 함수 호출과 복귀에 따른 전체 프로그램의 수행 순서
[그림 6-12] 함수 호출과 복귀에 따른 전체 프로그램 수행 순서

25 프로그램이 실행을 시작하여 main( ) 함수가 실행되면서 main( ) 함수에 관련된 정보를 스택 프레임에 저장하여 시스템 스택에 삽입
main( ) 함수 실행 중에 F_1( ) 함수 호출을 만나면 함수 호출과 복귀에 필요한 정보를 스택 프레임에 저장하여 시스템 스택에 삽입하고, 호출된 함수인 F_1( ) 함수로 이동 스택 프레임에는 호출된 함수의 수행이 끝나고 main( ) 함수로 복귀할 주소 a를 저장 [그림 6-13] main( ) 함수 실행 시작 [그림 6-14] F_1( ) 함수 호출

26 시스템 스택의 top에 있는 스택 프레임을 pop하여 정보를 확인하고, F_1( ) 함수의 b주소로 복귀
F_1( ) 함수 실행 중에 F_2( ) 함수 호출을 만나면 다시 함수 호출과 복귀에 필요한 정보를 스택 프레임에 저장하여 시스템 스택에 삽입. 호출된 함수인 F_2( ) 함수를 실행 스택 프레임에는 F_1( ) 함수로 복귀할 주소 b를 저장 호출된 함수 F_2( ) 함수를 실행 완료 시스템 스택의 top에 있는 스택 프레임을 pop하여 정보를 확인하고, F_1( ) 함수의 b주소로 복귀 [그림 6-15] F_2( ) 함수 호출 [그림 6-16] F_1( ) 함수로 복귀

27 복귀된 함수 F_1( ) 함수의 b주소 이후 부분을 실행
시스템 스택의 top에 있는 스택 프레임을 pop하여 정보를 확인하고 main( ) 함수의 a주소로 복귀 복귀된 main( ) 함수의 a주소 이후 부분에 대한 실행이 완료되면 시스템 스택의 top에 있는 스택 프레임을 pop하는데, 시스템 스택이 공백이 되었으므로 전체 프로그램 실행 종료 [그림 6-17] main( ) 함수로 복귀 [그림 6-18] main( ) 함수 실행 종료

28 수식의 괄호 검사 수식에 포함되어있는 괄호는 가장 마지막에 열린 괄호를 가장 먼저 닫아 주어야 하는 후입선출 구조로 구성되어있으므로, 후입선출 구조의 스택을 이용하여 괄호를 검사한다. 수식을 왼쪽에서 오른쪽으로 하나씩 읽으면서 괄호 검사 왼쪽 괄호를 만나면 스택에 push 오른쪽 괄호를 만나면 스택을 pop하여 마지막에 저장한 괄호와 같은 종류인지를 확인 같은 종류의 괄호가 아닌 경우 괄호의 짝이 잘못 사용된 수식! 수식에 대한 검사가 모두 끝났을 때 스택은 공백 스택 수식이 끝났어도 스택이 공백이 되지 않으면 괄호의 개수가 틀린 수식!

29 수식의 괄호 검사 알고리즘 testPair( ) exp ← Expression; Stack ← null;
while (true) do{ symbol ← getSymbol(exp);        case { symbol = "(" or "[" or "{" : push(Stack, symbol); symbol = ")" : open_pair ← pop(Stack); if (open_pair ≠ "(") then return false; symbol = "]" : if (open_pair ≠ "[") then return false; symbol = "}" : if (open_pair ≠ "{") then return false; symbol = null : if (isEmpty(Stack)) then return true; else return false; else : } }                                      end testPair( ) 

30 수식의 괄호 검사 예

31

32 [그림 6-19] 수식 처리에 따른 스택 사용 과정

33 수식의 괄호 검사 C 프로그램 001 #include <stdio.h>
002  #include <stdlib.h> 003  #include <string.h> 004  005  typedef char element; 006  007  typedef struct stackNode {            008      element data; 009      struct stackNode *link; 010  }stackNode; 011  012  stackNode* top; 013  014  void push(element item) 015  {    016      stackNode* temp=(stackNode *)malloc(sizeof(stackNode)); 017      temp->data = item; 018      temp->link = top;    019      top = temp; 020  } 021  022  element pop( ) 023  { 024      element item; 025      stackNode* temp=top; 026  027      if(top == NULL) {      028          printf("\n\n Stack is empty !\n");     029          return 0; 030      } 031      else { 032          item = temp->data;    033          top = temp->link;     034          free(temp);                035          return item; 036      } 037  } 038  039  element peek( ) 040  {    041      element item; 042      if(top == NULL) {         043          printf("\n\n Stack is empty !\n");  044          return 0;     045      } 046      else { 047          item = top->data; 048          return item; 049      } 050  } 051  052  void del( ) 053  {  054      stackNode* temp;

34 055      if(top == NULL) {        056          printf("\n\n Stack is empty !\n");    057          058      } 059      else { 060          temp = top;    061          top = top->link;     062          free(temp); 063      } 064  } 065  066  void printStack( ) 067  { 068      stackNode* p=top; 069      printf("\n STACK [ "); 070      while(p){ 071          printf("%d ",p->data); 072          p = p->link; 073      } 074      printf("] "); 075  } 076  077  int testPair(char *exp) 078  { 079      char symbol, open_pair; 080      int i, length=strlen(exp); 081      top=NULL; 082  083      for(i=0; i<length; i++){ 084          symbol = exp[i]; 085          switch(symbol){ 086          case '(' : 087          case '[' : 088          case '{' : 089              push(symbol);  break; 090          case ')' : 091          case ']' : 092          case '}' : 093              if(top==NULL) return 0; 094              else { 095                  open_pair = pop( ); 096                  if( (open_pair=='(' && symbol != ')') || 097                      (open_pair=='[' && symbol != ']') || 098                      (open_pair=='{' && symbol != '}')) 099                      return 0; 100                  else break; 101              }        102          } 103      } 104      if(top==NULL) return 1; 105      else return 0; 106  } 107

35 실행 결과 108 109  void main(void) 110  {     111      char* express = "{(A+B)-3}*5+[{cos(x+y)+7}-1]*4"; 112      printf("%s", express); 113      if(testPair(express) == 1) 114          printf("\n\n 수식의 괄호가 맞게 사용되었습니다!"); 115      else 116          printf("\n\n 수식의 괄호가 틀렸습니다!"); 117       118      getchar( ); 119  }

36 수식의 후위 표기법 변환 전위표기법(prefix notation) 중위표기법(infix notation)
연산자를 앞에 표기하고 그 뒤에 피연산자를 표기하는 방법 예) +AB 중위표기법(infix notation) 연산자를 피연산자의 가운데 표기하는 방법 예) A+B 후위표기법(postfix notation) 연산자를 피연산자 뒤에 표기하는 방법 예) AB+

37 중위표기식의 전위표기식 변환 방법 ① 수식의 각 연산자에 대해서 우선순위에 따라 괄호를 사용하여 다시 표현한다.
예) A*B-C/D 1단계: ( (A*B) - (C/D) ) 2단계:   ⇒ -(*(A B) /(C D)) 3단계   -*AB/CD ① 수식의 각 연산자에 대해서 우선순위에 따라 괄호를 사용하여 다시 표현한다. ② 각 연산자를 그에 대응하는 왼쪽괄호의 앞으로 이동시킨다. ③ 괄호를 제거한다.

38 중위표기식의 후위표기식 변환 방법 ① 수식의 각 연산자에 대해서 우선순위에 따라 괄호를 사용하여 다시 표현한다.
예) A*B-C/D  1단계: ( (A*B) - (C/D) )   2단계:   ⇒ ( (A B)* (C D)/ )-  3단계:  AB*CD/- ① 수식의 각 연산자에 대해서 우선순위에 따라 괄호를 사용하여 다시 표현한다. ② 각 연산자를 그에 대응하는 오른쪽괄호의 뒤로 이동시킨다. ③ 괄호를 제거한다.

39 스택을 사용하여 입력된 중위표기식을 후위표기식으로 변환
변환 방법 ⑴ 왼쪽괄호를 만나면 무시하고 다음 문자를 읽는다. ⑵ 피연산자를 만나면 출력한다. ⑶ 연산자를 만나면 스택에 push한다. ⑷ 오른쪽괄호를 만나면 스택을 pop하여 출력한다. ⑸ 수식이 끝나면, 스택이 공백이 될 때까지 pop하여 출력한다.

40 예) ((A*B)-(C/D)) [그림 6-20] 스택을 사용한 후위 표기식 변환 과정

41 후위표기법 변환 알고리즘 infix_to_postfix(exp) while (true) do {
symbol ← getSymbol(exp); case { symbol = operand : // 피연산자 처리 print(symbol); symbol = operator : // 연산자 처리 push(stack, symbol); symbol = ")" : // 오른쪽괄호 처리 print(pop(Stack)); symbol = null : // 수식의 끝 처리 while (top > -1) do else : } end infix_to_postfix( )

42 스택을 사용하여 후위표기식을 연산 연산 방법 ⑴ 피연산자를 만나면 스택에 push 한다.
수식이 끝나고 스택에 마지막으로 남아있는 원소는 전체 수식의 연산결과 값이 된다. ⑴ 피연산자를 만나면 스택에 push 한다. ⑵ 연산자를 만나면 필요한 만큼의 피연산자를 스택에서 pop하여 연산하고, 연산결과를 다시 스택에 push 한다. ⑶ 수식이 끝나면, 마지막으로 스택을 pop하여 출력한다.

43 후위표기식의 연산 알고리즘 evalPostfix(exp) while (true) do {
            symbol ← getSymbol(exp);             case {                 symbol = operand : // 피연산자 처리                         push(stack, symbol);                 symbol = operator : // 연산자 처리                         opr2 ← pop(stack));                         opr1 ← pop(stack));                         result ← opr1 op(symbol) opr2;                         // 스택에서 꺼낸 피연산자들을 연산자로 연산                         push(stack, result);                 symbol = null : // 후위수식의 끝                              print(pop(stack));                               }         } end evalPostfix( )

44 예) AB*CD/-

45 예) AB*CD/- [그림 6-21] 스택을 사용한 후위 표기식 연산 과정

46 후위표기식의 연산 C 프로그램 001 #include <stdio.h>
002  #include <stdlib.h> 003  #include <string.h> 004  005 typedef int element; 006  007  typedef struct stackNode {            008      element data; 009      struct stackNode *link; 010  }stackNode; 011  012  stackNode* top; 013  014  void push(element item) 015  {    016      stackNode* temp=(stackNode *)malloc(sizeof(stackNode)); 017      temp->data = item; 018      temp->link = top;    019      top = temp; 020  } 021  022  element pop( ) 023  { 024      element item; 025      stackNode* temp=top; 026  027      if(top == NULL) {      028          printf("\n\n Stack is empty !\n");     029          return 0; 030      } 031      else { 032          item = temp->data;    033          top = temp->link;     034          free(temp);                035          return item; 036      } 037  } 038  039  element peek( ) 040  {    041      element item; 042      if(top == NULL) {         043          printf("\n\n Stack is empty !\n");     044          return 0;     045      } 046      else { 047          item = top->data; 048          return item; 049      } 050  } 051  052  void del( ) 053  {  054      stackNode* temp;

47 055      if(top == NULL) {        056          printf("\n\n Stack is empty !\n");    057          058      } 059      else { 060          temp = top;    061          top = top->link;     062          free(temp); 063      } 064  } 065  066  void printStack( ) 067  { 068      stackNode* p=top; 069      printf("\n STACK [ "); 070      while(p){ 071          printf("%d ",p->data); 072          p = p->link; 073      } 074      printf("] "); 075  } 076  077  element evalPostfix(char *exp) 078  { 079      int opr1, opr2, value, i=0; 080      int length = strlen(exp); 081      char symbol; 082      top = NULL; 083  084      for(i=0; i<length; i++){ 085          symbol = exp[i]; 086          if(symbol != '+' && symbol != '-' && symbol != '*' && symbol != '/'){ 087              value = symbol - '0'; 088              push(value); 089          } 090          else{ 091              opr2 = pop( ); 092              opr1 = pop( ); 093              switch(symbol){ 094              case '+' : push(opr1 + opr2); break; 095              case '-' : push(opr1 - opr2); break; 096              case '*' : push(opr1 * opr2); break; 097              case '/' : push(opr1 / opr2); break; 098              } 099          } 100      } 101      return pop( ); 102  } 103  104  void main(void) 105  {         106      int result; 107      char* express = "35*62/-"; 108      printf("후위표기식 : %s", express); 109

48 실행 결과 110 result = evalPostfix(express);
111      printf("\n\n 연산결과 => %d", result); 112       113      getchar( ); 114  }

49


Download ppt "스택 스택 추상자료형 스택 스택의 구현 스택의 응용 한빛미디어(주)."

Similar presentations


Ads by Google