λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
βœ’οΈ Data Structures & Algorithms

[Data Structures & Algorithms] μŠ€νƒ(Stack)의 이해와 μ‘μš©

by A Lim Han 2023. 6. 11.

🧿 μŠ€νƒ(Stack) μ΄λž€?

μŠ€νƒ(Stack)μ΄λž€ ν•œμͺ½ λμ—μ„œλ§Œ 데이터λ₯Ό μ‚½μž…ν•˜κ³  μ‚­μ œν•  수 μžˆλŠ” μ„ ν˜• 자료ꡬ쑰λ₯Ό μ˜λ―Έν•˜λ©°, λ§ˆμ§€λ§‰μœΌλ‘œ μ‚½μž…λœ μ›μ†Œκ°€ κ°€μž₯ λ¨Όμ € μ‚­μ œλ˜λŠ” "ν›„μž…μ„ μΆœ(LIFO, Last-In-First-Out)"의 νŠΉμ§•μ„ 가진닀.

μŠ€νƒ(Stack) μžλ£Œκ΅¬μ‘°λŠ” 데이터λ₯Ό μ €μž₯ν•˜κ³  κ΄€λ¦¬ν•˜λŠ”λ° μ‚¬μš©λ˜λ©° 주둜 ν•¨μˆ˜ 호좜, μž¬κ·€ μ•Œκ³ λ¦¬μ¦˜, λ’€λ‘œκ°€κΈ° κΈ°λŠ₯ λ“±μ—μ„œ ν™œμš©λœλ‹€.

 


 

πŸ’™ μŠ€νƒ(Stack)μ—μ„œμ˜ μ—°μ‚° μ•Œκ³ λ¦¬μ¦˜

μ‚­μ œ μ—°μ‚° μ‚½μž… μ—°μ‚°
pop push

 

β‘  μŠ€νƒμ˜ push() μ•Œκ³ λ¦¬μ¦˜

push(S,x)
    
    top <- top + 1; //λ§ˆμ§€λ§‰ 자료 top μœ„μ— 자료λ₯Ό μ‚½μž…ν•˜κΈ° μœ„ν•΄ top의 μœ„μΉ˜λ₯Ό 1μ¦κ°€μ‹œν‚΄
    
    //top의 μœ„μΉ˜ν‚€ μŠ€νƒ 크기보닀 크닀면 μ˜€λ²„ν”Œλ‘œμš° λ°œμƒ
    if (top > stack_SIZE) then overflow;
    else //μ˜€λ²„ν”Œλ‘œμš° μƒνƒœκ°€ μ•„λ‹Œ 경우 μ•„λž˜ μ½”λ“œ μ‹€ν–‰
    {
        S(top) <- x; //μŠ€νƒμ˜ top이 κ°€λ¦¬ν‚€λŠ” μœ„μΉ˜μ— x μ‚½μž…
    }

end push()

 

 

β‘‘ μŠ€νƒμ˜ pop() μ•Œκ³ λ¦¬μ¦˜

pop(S)

    if (top == 0)
    {
        overflow;
    }
    else //μŠ€νƒμ΄ 곡백 μƒνƒœκ°€ 아닐 경우 μ‚­μ œ μ—°μ‚° μˆ˜ν–‰
    {
        return S(top); //top 에 μžˆλŠ” μ›μ†Œ μ‚­μ œ ν›„ λ°˜ν™˜
        top <- top -1; //μŠ€νƒμ˜ μ›μ†Œ 1κ°œκ°€ μ‚­μ œλ˜μ—ˆμœΌλ‹ˆ top μœ„μΉ˜λ₯Ό 1 κ°μ†Œμ‹œν‚΄
    }
    
end pop()

 


 

πŸ’™ μŠ€νƒ(Stack)의 좔상 μžλ£Œν˜•

ADT Stack

    createStack(S) ::= create an empty Stack S; //곡백 μŠ€νƒ S 생성
    
    //μŠ€νƒμ˜ 곡백 μ—¬λΆ€ 확인
    isEmpty(S) ::= if (S is empty) then return true
                   else return false;
                   
//μŠ€νƒμ˜ top에 item(μ›μ†Œ) μ‚½μž…
push(S, item) ::= insert item onto the top of Stack S;

 //μŠ€νƒμ˜ top에 μžˆλŠ” μ›μ†Œ λ°˜ν™˜
pop(S) ::= if (isEmpty(S)) then return error
           else return the top item of the Stack S;
           
End Stack

 


 

πŸ’™ 순차 μžλ£Œκ΅¬μ‘°μ™€ μŠ€νƒ(Stack)의 κ΅¬ν˜„

: μŠ€νƒμ€ 순차 자료ꡬ쑰인 1차원 배열을 μ΄μš©ν•˜μ—¬ κ΅¬ν˜„ν•  수 μžˆλ‹€.

 

  • μŠ€νƒμ˜ 크기  ==  λ°°μ—΄μ˜ 크기
  • μŠ€νƒ μ›μ†Œμ˜ μˆœμ„œ  ==  λ°°μ—΄ μ›μ†Œμ˜ 인덱슀
  • λ³€μˆ˜ top  ==  μŠ€νƒμ— μ €μž₯된 λ§ˆμ§€λ§‰ μ›μ†Œμ— λŒ€ν•œ 인덱슀

 

인덱슀 0 μŠ€νƒμ˜ 첫 번째 μ›μ†Œ
인덱슀 n-1 μŠ€νƒμ˜ n 번째 μ›μ†Œ
곡백 μƒνƒœ top = - 1
포화 μƒνƒœ top = n - 1

 

β€» 순차 자료ꡬ쑰둜 κ΅¬ν˜„ν•œ μŠ€νƒμ˜ μž₯단점

μž₯점  :  순차 자료ꡬ쑰인 1차원 배열을 μ‚¬μš©ν•˜μ—¬ μ‰½κ²Œ κ΅¬ν˜„μ΄ κ°€λŠ₯함

단점  :  물리적으둜 크기가 κ³ μ •λ˜μ–΄ μŠ€νƒ 크기λ₯Ό λ³€κ²½ν•˜κΈ° 어렀움

 


 

πŸ’™ μ—°κ²° μžλ£Œκ΅¬μ‘°μ™€ μŠ€νƒ(Stack)의 κ΅¬ν˜„

 

  • μŠ€νƒμ˜ μ›μ†Œ  ==  λ‹¨μˆœ μ—°κ²° 리슀트의 λ…Έλ“œ
  • μŠ€νƒ μ›μ†Œμ˜ μˆœμ„œ  ==  λ…Έλ“œμ˜ 링크 ν¬μΈν„°λ‘œ μ—°κ²°
  • λ³€μˆ˜ top  ==  λ‹¨μˆœ μ—°κ²° 리슀트이 λ§ˆμ§€λ§‰ λ…Έλ“œλ₯Ό κ°€λ¦¬ν‚€λŠ” 포인터 λ³€μˆ˜
  • 초기의 top μƒνƒœ  ==  null

 


 

πŸ’™ μŠ€νƒ(Stack)의 μ‘μš©_1) μ‹œμŠ€ν…œ μŠ€νƒ (System Stack)

: ν”„λ‘œκ·Έλž¨μ—μ„œμ˜ 호좜 및 볡귀에 λ”°λ₯Έ μˆ˜ν–‰ μˆœμ„œ 관리

β‘  ν•¨μˆ˜ 호좜 λ°œμƒ μ‹œ ν•¨μˆ˜ μˆ˜ν–‰μ— ν•„μš”ν•œ 정보λ₯Ό μŠ€νƒ ν”„λ ˆμž„μ— μ €μž₯
β‘‘ μŠ€νƒ ν”„λ ˆμž„μ— μ €μž₯ν•œ 값을 μ‹œμŠ€ν…œ μŠ€νƒμ— μ‚½μž…
β‘’ ν•¨μˆ˜μ˜ 싀행이 λλ‚˜λ©΄ μ‹œμŠ€ν…œ μŠ€νƒμ˜ top μ›μ†Œλ₯Ό μ‚­μ œ
β‘£ ν”„λ ˆμž„μ— μ €μž₯λ˜μ—ˆλŠ” 볡귀 μ£Όμ†Œ 확인 ν›„ 볡귀

 

-->  μœ„ 과정을 λ°˜λ³΅ν•˜μ—¬ 전체 ν”„λ‘œκ·Έλž¨ μˆ˜ν–‰μ΄ μ’…λ£Œλ˜λ©΄ μ‹œμŠ€ν…œ μŠ€νƒμ€ 곡백 μƒνƒœκ°€ λœλ‹€.

 


 

πŸ’™ μŠ€νƒ(Stack)의 μ‘μš©_2) μˆ˜μ‹μ˜ κ΄„ν˜Έ 검사

: μˆ˜μ‹μ— ν¬ν•¨λœ κ΄„ν˜Έλ“€μ˜ 경우 κ°€μž₯ λ§ˆμ§€λ§‰μ— μ—΄λ¦° κ΄„ν˜Έλ₯Ό κ°€μž₯ λ¨Όμ € λ‹«μ•„μ£Όμ–΄μ•Ό 함

-->  ν›„μž… μ„ μΆœ ꡬ쑰인 Stack을 μ΄μš©ν•˜μ—¬ κ΄„ν˜Έ 검사 κ°€λŠ₯

 

β€» μˆ˜μ‹μ„ μ™Όμͺ½μ—μ„œ 였λ₯Έμͺ½μœΌλ‘œ 읽어가며 검사 진행


β‘ 
μ™Όμͺ½ κ΄„ν˜Έλ₯Ό λ§Œλ‚˜λ©΄ Stack에 push

β‘‘ 였λ₯Έμͺ½ κ΄„ν˜Έλ₯Ό λ§Œλ‚˜λ©΄ μŠ€νƒμ„ pop ν•˜μ—¬ λ§ˆμ§€λ§‰μ— μ €μž₯된 κ΄„ν˜Έμ™€ 같은 μ’…λ₯˜μΈμ§€ μ—¬λΆ€ 확인
-->  같은 μ’…λ₯˜κ°€ μ•„λ‹ˆλΌλ©΄ μˆ˜μ‹μ— 였λ₯˜κ°€ μžˆλŠ” 것

β‘’ 검사 μ™„λ£Œ ν›„ μŠ€νƒμ˜ μƒνƒœλŠ” 곡백
-->  곡백 μƒνƒœκ°€ μ•„λ‹Œ 경우 였λ₯˜κ°€ μžˆλŠ” μˆ˜μ‹

 

testPair()
    exp <- Expression;
    Stack <- null;
    
    while (true) do
    {
        symbol <- getSymbol(exp);
        
        case
        {
            symbol = "(" or "[" of "{" :
                        push(Stack, symbol);
            symbol = ")" :
                        open_pair != "(") then return false;
            symbol = "]" :
                        open_pair <- pop(Stack);
                        if (open_pair != "[") then return false;
            symbol = "}" :
                        open_pair <- pop(Stack);
                        if (open_pair != "{") then return false;
            symbol = null :
                        if (isEmpty(Stack)) then return true;
                        else return false;
            else :
        }
    }
end testPair()

 


 

πŸ’™ μŠ€νƒ(Stack)의 μ‘μš©_3) μˆ˜μ‹μ˜ ν‘œκΈ°λ²• λ³€ν™˜

μˆ˜μ‹ ν‘œκΈ°λ²•
μ „μœ„ ν‘œκΈ°λ²• (Prefix Notation) μ€‘μœ„ ν‘œκΈ°λ²• (Infix Notation) ν›„μœ„ ν‘œκΈ°λ²• (Postfix Notation)
μ—°μ‚°μžλ₯Ό ν”Όμ—°μ‚°μž μ•žμ— ν‘œκΈ° μ—°μ‚°μžλ₯Ό ν”Όμ—°μ‚°μž κ°€μš΄λ°μ— ν‘œκΈ° μ—°μ‚°μžλ₯Ό ν”Όμ—°μ‚°μž 뒀에 ν‘œκΈ°
+ A B A + B A B +

 

A) μ€‘μœ„ ν‘œκΈ°μ‹  -->  μ „μœ„ν‘œκΈ°μ‹

β‘  μˆ˜μ‹μ˜ 각 μ—°μ‚°μžμ— λŒ€ν•΄ μš°μ„ μˆœμœ„λ₯Ό λ°˜μ˜ν•˜μ—¬ κ΄„ν˜Έλ₯Ό μ‚¬μš©ν•˜μ—¬ ν‘œν˜„
A * B + C / D  -->  ( (A * B) + (C / D) )

β‘‘ 각 μ—°μ‚°μžλ₯Ό 그에 λŒ€μ‘ν•˜λŠ” 쒌츑 κ΄„ν˜Έ μ•žμœΌλ‘œ 이동
( ( A * B ) + ( C / D ) )  -->  + ( * ( A B ) / ( C D ) )

β‘’ 2번 κ²°κ³Όμ—μ„œ κ΄„ν˜Έλ§Œ 제거
+ * A B / C D

 

 

B) μ€‘μœ„ ν‘œκΈ°μ‹  -->  ν›„μœ„ν‘œκΈ°μ‹

β‘  μˆ˜μ‹μ˜ 각 μ—°μ‚°μžμ— λŒ€ν•΄ μš°μ„ μˆœμœ„λ₯Ό λ°˜μ˜ν•˜μ—¬ κ΄„ν˜Έλ₯Ό μ‚¬μš©ν•˜μ—¬ ν‘œν˜„
A * B + C / D  -->  ( ( A * B ) + ( C / D ) )

β‘‘ 각 μ—°μ‚°μžλ₯Ό 그에 λŒ€μ‘ν•˜λŠ” 우츑 κ΄„ν˜Έμ˜ λ’€λ‘œ 이동
( ( A * B ) + ( C / D ) )  -->  ( ( A B ) * ( C D ) / ) +

β‘’ 2번 κ²°κ³Όμ—μ„œ κ΄„ν˜Έλ§Œ 제거
A B * C D / +

 

β€» 컴퓨터 λ‚΄λΆ€μ—μ„œμ˜ ν‘œκΈ°λ²• λ³€ν™˜

β‘  μ™Όμͺ½ κ΄„ν˜Έλ₯Ό λ§Œλ‚˜λ©΄ λ¬΄μ‹œν•˜κ³  λ‹€μŒ 문자 μ½μ–΄λ“€μž„
β‘‘ ν”Όμ—°μ‚°μžλ₯Ό λ§Œλ‚˜λ©΄ 좜λ ₯
β‘’ μ—°μ‚°μžλ₯Ό λ§Œλ‚˜λ©΄ μŠ€νƒμ— μ‚½μž…
β‘£ 우츑 κ΄„ν˜Έλ₯Ό λ§Œλ‚˜λ©΄ μŠ€νƒμ„ popν•˜μ—¬ 좜λ ₯
β‘€ μˆ˜μ‹μ΄ λλ‚˜λ©΄ μŠ€νƒμ΄ 곡백이 될 λ•ŒκΉŒμ§€ pop ν•˜μ—¬ 좜λ ₯

 

infix_to_postfix(exp)

    while (true) do
    {
        symbol <- getSymbol(exp);
        
        case
        {
            symbol = operand : //ν”Όμ—°μ‚°μž λ§Œλ‚˜λ©΄ 좜λ ₯
                        print(symbol);
            symbol = operator : //μ—°μ‚°μž λ§Œλ‚˜λ©΄ μŠ€νƒμ— push
                        push(stack, symbol);
            symbol = ")" : //우츑 κ΄„ν˜Έ λ§Œλ‚˜λ©΄ μŠ€νƒμ„ popν•˜μ—¬ 좜λ ₯
                        print(pop(stack));
            symbol = null : //μˆ˜μ‹μ˜ 끝 처리
                        while (top > - 1) do //μŠ€νƒμ΄ 곡백 μƒνƒœκ°€ 될 λ•ŒκΉŒμ§€ popν•˜μ—¬ 좜λ ₯
                        {
                            print(pop(stack));
                        }
        else :
        }
    }
    
end infix_to_postfix()

 

 

C) ν›„μœ„ ν‘œκΈ°λ²• μˆ˜μ‹ μ—°μ‚°

β‘  ν”Όμ—°μ‚°μž λ§Œλ‚˜λ©΄ μŠ€νƒμ— push
β‘‘ μ—°μ‚°μžλ₯Ό λ§Œλ‚˜λ©΄ ν•„μš”ν•œ 만큼의 ν”Όμ—°μ‚°μžλ₯Ό μŠ€νƒμ—μ„œ popν•˜μ—¬ μ—°μ‚°
β‘’ μ—°μ‚° κ²°κ³Όλ₯Ό λ‹€μ‹œ μŠ€νƒμ— push
β‘£ μˆ˜μ‹μ΄ λλ‚˜λ©΄ μŠ€νƒμ„ popν•˜μ—¬ 좜λ ₯

 

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));
        else :
        }
    }
    
end evalPostfix()