자료 구조
This presentation is the property of its rightful owner.
Sponsored Links
1 / 27

자료 구조 PowerPoint PPT Presentation


  • 104 Views
  • Uploaded on
  • Presentation posted in: General

자료 구조. 제 3 장 : 스택과 큐 이 형 원 강릉대학교 컴퓨터공학과. 학습 내용. 스택 ADT 큐 ADT 스택의 사용 예제 미로 문제 수식 계산 다중 스택과 큐. A. E D C B A. B A. C B A. D C B A. D C B A. top. top. top. top. top. top. 스택 (stack). 한쪽 끝 (top) 에서만 삽입 / 삭제가 되는 순서 리스트 Last-In-First-Out(LIFO)

Download Presentation

자료 구조

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


4788085

자료 구조

제 3 장 : 스택과 큐

이 형 원

강릉대학교 컴퓨터공학과


4788085

학습 내용

  • 스택 ADT

  • 큐 ADT

  • 스택의 사용 예제

    • 미로 문제

    • 수식 계산

  • 다중 스택과 큐


Stack

A

E

D

C

B

A

B

A

C

B

A

D

C

B

A

D

C

B

A

top

top

top

top

top

top

스택(stack)

  • 한쪽 끝(top)에서만 삽입/삭제가 되는 순서 리스트

  • Last-In-First-Out(LIFO)

  • 사용 예 : 시스템 스택


Adt structure stack

스택 ADT: structure Stack

objects: 0개 이상의 원소를 가진 유한 순서 리스트

functions:stack∈Stack, item∈element, max_stack_size∈양정수

Stack CreateS(max_stack_size) ::= 최대 크기 max_stack_size인 공백 스택 생성Boolean IsFull(stack, max_stack_size) ::= if (stack의 원소수 == max_stack_size) return TRUE else return FALSEStack Add(stack, item) ::= if (IsFull(stack)) stack_full else stack top에 item을 삽입하고 returnBoolean IsEmpty(stack) ::= if (stack == CreateS(max_stack_size)) return TRUE else return FALSEElement Delete(stack) ::= if (IsEmpty(stack)) return else stack top의 item을 제거해서 반환


4788085

스택의 구현

Stack CreateS(max_stack_size) ::= #define MAX_STACK_SIZE 100 /*최대스택크기*/ typedef struct { int key; /* 다른 필드 */ } element; element stack[MAX_STACK_SIZE]; int top = -1;Boolean IsEmpty(Stack) ::= top < 0;Boolean IsFull(Stack) ::= top >= MAX_STACK_SIZE-1;void add(int *top, element item) { element delete(int *top) { if (*top >= MAX_STACK _SIZE-1) { if (*top == -1) stack_full(); return stack_empty(); return; return stack[(*top)--];} } } stack[++*top] = item;}


Queue

A

B

A

C

B

A

D

C

B

A

D

C

B

rear

rear

rear

front

front

rear

front

front

rear

front

큐(queue)

  • 한쪽 끝(rear)에서 삽입, 반대쪽 끝(front)에서 삭제가 일어나는 순서 리스트

  • First-In-First-Out(FIFO)


Adt structure queue

큐 ADT: structure Queue

objects: 0개 이상의 원소를 가진 유한 순서 리스트

functions: queue∈Queue, item∈element, max_queue_size∈양 정수Queue CreateQ(max_queue_size) ::=최대 크기가 max_queue_size인 공백 큐를 생성Boolean IsFullQ(queue, max_queue_size ) ::= if (queue의 원소수 == max_queue_size) return TRUE else return FALSEQueue AddQ(queue,item) ::= if (IsFull(queue)) queue_full else queue 뒤에 item 삽입하고 반환Boolean IsEmptyQ(queue) ::= if (queue == CreateQ(max_queue_size)) return TRUE else return FALSEElement DeleteQ(queue) ::= if (IsEmpty(queue)) return else queue 앞에 있는 item을 제거해서 반환


4788085

큐의 구현: 순차 배열

Queue CreateQ(max_queue_size) ::= #define MAX_QUEUE_SIZE 100 /* 큐의 최대크기 */ typedef struct { int key; /* 다른 필드 */ } element; element queue[MAX_QUEUE_SIZE];int rear = -1; int front = -1;Boolean IsEmptyQ(queue) ::= front == rearBoolean IsFullQ(queue) ::= rear == MAX_QUEUE_SIZE-1void addq(int *rear, element item) { element deleteq(int *front, int rear) { if (*rear == MAX_QUEUE_SIZE-1) { if (*front == rear) queue_full(); return queue_empty(); return; return queue[++*front]; } } queue[++*rear] = item;}


4788085

큐의 구현: 순차 배열(계속)

  • 단점: rear = MAX_QUEUE_SIZE - 1이 되는 경우

    • 전체 큐를 왼쪽으로 이동, front=-1, rear 조정

      Q. 시간 복잡도 ?

    • 예제 [작업 스케쥴링] : O.S.에 의한 작업 큐의 생성

      front rearQ[0] Q[1] Q[2] Q[3]설 명

      -1 -1 공백큐

      -1 0 J1 Job 1의 삽입

      -1 1 J1 J2 Job 2의 삽입

      -1 2 J1 J2 J3 Job 3의 삽입

      0 2 J2 J3 Job 1의 삭제

      1 2 J3 Job 2의 삭제


4788085

큐의 구현: 원형 배열

  • 초기화: front = rear = 0

  • 공백 큐: front = rear

  • 포화 큐: 원소 수 = MAX_QUEUE_SIZE-1

    Q. Why ?


4788085

큐의 구현: 원형 배열(계속)

void addq(int *front, int *rear, element item) {*rear = (*rear+1) % MAX_QUEUE_SIZE; if (front == *rear) { queue_full(rear); /* rear를 리세트시키고 에러를 프린트 */ return; } queue[*rear] = item;}

void deleteq(int *front, int rear) { element item; /* queue의 front 원소를 삭제하여 그것을 item에 놓음 */ if (*front == rear) return queue_empty(); *front = (*front+1) % MAX_QUEUE_SIZE; return queue[*front];}


4788085

미로 문제 : 자료 구조

  • m x p 미로: 2차원 배열 maze[m+2][p+2]

    • maze[row][col] = 0(path) or 1(no path)

    • 가장 자리는 모두 1

    • 입구 maze[1][1], 출구 maze[m][p]

  • 이동 방향: 미리 정의된 이동 테이블 move[8]

    • 구조

      typedef struct { short int vert;short int horiz;

      } offsets;

      offsets move[8];


4788085

미로 문제 : 자료 구조(계속)

  • move[8]의 내용

    name dir move[dir].vert move[dir].horiz

    N 0 -1 0

    NE 1 -1 1

    E 2 0 1

    SE 3 1 1

    S 4 1 0

    SW5 1 -1

    W6 0 -1

    NW7 -1 -1

  • 현 위치 maze[row][col] 이동 위치 maze[next_row][next_col] next_row = row + move[dir].vert next_col = col + move[dir].horiz


4788085

미로 문제 : 자료 구조(계속)

  • 시도한 경로의 재시도 방지: mark[m+2][p+2]

    • mark[row][col] = 1 /* 한번 방문한 경우 (지나간 경로)*/

    • 경로의 탐색

      현위치 저장 후 방향 선택 : N에서 시계방향

      잘못된 경로의 선택 시는 backtracking후 다른 방향 시도

  • 시도한 경로의 유지: 스택 element stack[MAX_SIZE];

    #define MAX_SIZE 100 /* 스택의 최대 크기 */

    typedef struct { Q. 스택 크기의 최대값 ?

    short int row;

    short int col;

    short int dir;

    } element;


4788085

미로 문제 : 초기 미로 알고리즘

initiallize a stack to the maze's entrance coordinates and direction to north;while (stack is not empty) { /* 스택의 톱에 있는 위치로 이동*/ <rol, col, dir> = delete from top of stack; while (there are more moves from current position) { <next_row, next_col> = coordinate of next move; dir = direction of move; if ((next_row == EXIT_ROW) && (exit_col == EXIT_COL)) success; if (maze[next_row][next_col] == 0) && mark[next_row][next_col] == 0){ /* 가능하지만 아직 이동해보지 않은 이동 방향 */ mark[next_row][next_col] = 1; /* 현재의 위치와 방향을 저장 */ add <row, col, dir> to the top of the stack; row = next_row; col = next_col; dir = north; } }}printf("No path found");


4788085

미로 문제 : 미로 탐색 함수

void path(void) {int i, row, col, next_row, next_col, dir, found=FALSE;element position; mark[1][1]=1; top=0;stack[0].row=1; stack[0].col=1; stack[0].dir=1;while (top>-1 && !found) { position=delete(&top); row=position.row; col=position.col; dir=position.dir; while (dir<8 && !found) { next_row = row + move[dir].vert; /* dir 방향으로 이동 */ next_col = col + move[dir].horiz; if (next_row==EXIT_ROW && next_col==EXIT_COL) found = TRUE; else if (!maze[next_row][next_col] && !mark[next_row][next_col]) { mark[next_row][next_col]) = 1; position.row = row; position.col = col; position.dir = ++dir; add(&top, position); row = next.row; col = next.col; dir = 0; } else ++dir; }} ……

} Q. 복잡도 ?


4788085

수식의 계산

  • C의 연산자 우선 순위 계층

    토큰 우선순위 결합성

    --, ++ 16LR

    &, *, unary - + 15 RL

    *, /, %13LR

    +, -12L R

    >, >=, <, <= 10LR

    ==, !=9LR

    &&5L R

    ||4LR


4788085

수식의 계산(계속)

  • 수식의 표현

    중위 (infix) 표기 후위 (postfix) 표기 전위 (prefix) 표기

    a * b / c a b * c / / * a b c

    (1 + 2) * 7 1 2 + 7 * * + 1 2 7

  • 후위 표기식의 장점 : 컴파일러(기계)에게 편리

    • 괄호 및 연산자간의 우선 순위가 불필요

    • 한 번만 수식을 scan하면서 스택을 이용하여 쉽게 계산

       중위 표기식을 후위 표기식으로 변환 후 계산


4788085

후위 표기식의 계산

  • algorithm (예 : 3.14)

    L-->R로 scan피연산자 : 스택에 삽입연산자 : 필요한 피연산자 수만큼 스택에서 가져옴 연산 수행 후 결과를 스택에 저장식의 끝 : 스택의 top에서 해답을 가져옴


4788085

후위 표기식 처리 함수

typedef enum {lparen,rparen,plus,minus,times,divide,mod,eos,operand} precedence;int stack[MAX_STACK_SIZE]; /* 전역 배열 */char expr[MAX_EXPR_SIZE]; /* 입력 스트링 */int eval(void) { precedence token; char symbol; int op1,op2, top=-1, n=0; token = get_token(&symbol, &n); while (token != eos) { if (token == operand) add(&top, symbol-'0'); / *스택 삽입 */ else { op2 = delete(&top); op1 = delete(&top); switch(token) { case plus : add(&top, op1+op2); break; case minus : add(&top, op1-op2); break; …… case mod : add(&top, op1%op2); } } token = get_token(&symbol, &n); } return delete(&top); /* 결과를 반환 */}


4788085

후위 표기식 처리 함수(계속)

precedence get_token (char *symbol, int *n) {/* 다음 토큰을 취한다. symbol은 문자 표현이며, token은 그것의 열거된 값으로 표현되고, 명칭으로 반환된다. */*symbol = expr[(*n)++];switch (*symbol) { case '(' : return lparen; case ')' : return rparen; case '+' : return plus; case '-' : return minus; case '/' : return divide; case '*' : return times; case '%' : return mod; case ' ' : return eos; default : return operand; }

}


4788085

중위 표기 후위 표기

  • 수작업에 의한 중위->후위 변환

    ① 식을 괄호로 묶음

    ② 연산자를 오른쪽 괄호와 대치

    ③ 괄호 삭제

    • 예. 전위 표기 : a / b - c + d * e - a * c

      ((((a / b) - c) + (d * e)) - (a * c))

      ((((a b) / c) - (d e) *) + (a c) *) -

      후위 표기 : a b / c - d e * + a c * -

      ==> 컴퓨터 처리로는 비효율적 (∵ 2 pass가 필요 )

    • How to infix to postfix in one pass ?

      • 피연산자들의 순서: 중위/후위 동일 scan하면서 바로 출력 가능

      • 연산자 순서: 높은 우선 순위가 먼저 출력  스택을 이용


4788085

중위 표기 후위 표기(계속)

  • 중위  후위 변환의 핵심

    1. token = 피연산자: 출력

    2. token = ‘)’: (가 나올 때까지 스택의 연산자 출력

    3. 우선순위(top) ≥ 우선순위(token): 스택의 연산자 출력

    4. 우선순위(top) < 우선순위(token): 스택에 token 삽입

    주의. ‘)’: 스택에 넣지 않음 ‘(‘ : 스택 밖에서는 가장 높은 우선 순위

    but 스택 안에서는 가장 낮은 우선 순위Q. Why ?


4788085

중위 표기 후위 표기(계속)

  • 중위 표기식 a*(b+c)*d의 후위 표기식으로의 변환

    토큰 스택 Output

    [0] [1] [2]

    a a * * a( * ( a b * ( ab + * ( + abc * ( + abc ) * abc+ * * abc+*d * abc+*d eos abc+*d*


4788085

중위 표기 후위 표기(계속)

precedence stack[MAX_STACK_SIZE]; static int isp[] = {0, 19, 12, 12, 13, 13, 13, 0}; /* 연산자 ( ) + - * / % eos의 우선순위 값 */ static int icp[] = {20, 19, 12, 12, 13, 13, 13, 0}; void postfix(void) { char symbol; precedence token; int n = 0; int top = 0; stack[0] = eos; for (token==get_token(&symbol,&n); token!=eos; token==get_token(&symbol,&n)) { if (token == operand) printf("%c", symbol); else if (token == rparen) { while (stack[top] != lparen) print_token(delete(&top)); delete(&top); /* 좌괄호를 버린다 */ } else { /* symbol의 isptoken의 icp :symbol을 제거하고 출력 */ while (isp[stack[top]] >= icp[token]) print_token(delete(&top)); add(&top, token); } } while ((token=delete(&top)) != eos) print_token(token); printf(”\n");}


4788085

다중 스택

  • 2 스택 : 각 스택의 최하단 원소를 양끝으로

  • n (>2) 스택

    • 이용 가능한 기억장소를 n개의 세그먼트로 분할

      • 예상 크기를 아는 경우 : 크기에 따라 분할

      • 예상 크기를 모르는 경우 : 똑같이 분할

        • Memory[m]에서 n개 스택의 초기 구성

Top[0]

Top[1]

0 1 m/n 2 m/n m-1

….

….

….

Boundary[1]

Top[1]

Boundary[2]

Top[2]

Boundary[n]

Boundary[0]

Top[0]


4788085

다중 스택 함수

#define MEMORY_SIZE 100 /* memory 크기 */#define MAX_STACKS 10 /* 가능한 스택의 최대수 + 1 */element memory[MEMORY_SIZE];int top[MAX_STACKS];int boundary[MAX_STACKS];void create(int n) { /* n :사용자가 입력한 스택의 수 */ top[0] = boundary[0] = -1; for (i = 1; i < n; i++) top[i] = boundary[i] = (MEMORY_SIZE/n) * i; boundary[n] = MEMORY_SIZE -1;}void add(int i, element item) { /* item을 i번째 스택에 삽입 */ if (top[i] == boundary[i+1]) stack_full(i); Q. How to implement ? memory[++top[i]] = item;} element delete(int i) { /* i번째 스택에서 top 원소를 제거 */ if (top[i] == boundary[i]) return stack_empty(i); return memory[top[i]--];}


  • Login