220 likes | 672 Views
배울 내용 스택 선형 큐 원형 큐. 스택 (Stack) 순서 리스트의 특별한 경우로 한쪽 끝 (top) 으로만 삽입과 삭제가 이루어짐 후입 선출 (last-in-first-out: LIFO) 리스트 먼저 삽입된 원소가 나중에 삭제. top=-1 top=0 top=1 top=2 top=3 top=2. 초기상태 삽입 삽입 삽입 삽입 삭제. 시스템 스택
E N D
배울 내용 • 스택 • 선형 큐 • 원형 큐
스택(Stack) • 순서 리스트의 특별한 경우로 한쪽 끝(top)으로만 삽입과 삭제가 이루어짐 • 후입 선출(last-in-first-out: LIFO) 리스트 먼저 삽입된 원소가 나중에 삭제 top=-1 top=0 top=1 top=2 top=3 top=2 초기상태 삽입 삽입 삽입 삽입 삭제
시스템 스택 • 스택이 사용되어지는 한 예 • 프로그램에서 함수가 처리되는 순서 • 가장 나중에 호출된 함수가 가장 먼저 처리됨 • 프로그램에서 함수 호출을 처리하기 위한 데이터 구조 • 함수가 호출되면 함수에 대한 스택 프레임이 생성되어 시스템 스택의 탑(top)에 위치 • 스택 프레임에는 복귀 주소와 지역 변수등이 있음 • 항상 시스템 스택의 top에는 현재 수행되고 있는 함수의 스택 프레임이 위치하고 함수가 종료되면 시스템 스택에서 해당 스택 프레임이 삭제됨 • 시스템 스택이 공백이 되면 메인 프로그램의 모든 수행이 완료
함수 호출과 제어 이동 main() { f1() 호출 α : } f1() { f2() 호출 β : } f2() { } 함수 호출과 시스템 스택 f2호출 f2종료 f1호출 f1종료
스택의 추상 데이터 타입 structure Stack 데이터 : 0개 이상의 원소를 가진 유한 순서 리스트 연산들 : 모든 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 FALSE Stack Add(stack, item) ::= if (IsFull(stack)) stack_full else stack의 톱에item을 삽입하고 return Boolean IsEmpty(stack) ::= if (stack == CreateS(max_stack_size)) return TRUE else return FALSE Element Delete(stack) ::= if (IsEmpty(stack)) return else스택 톱의 item을 제거해서 반환 end Array
스택의 표현 • 최대 100개의 원소를 삽입할 수 있는 스택의 데이터 구조 #define MAX_STACK_SIZE 100 struct element { int key; /* 다른 필드 */ }; element stack[MAX_STACK_SIZE]; int top = -1;
스택 생성과 사용 • element stack[MAX_STACK_SIZE]; • int main() • { • element data; • int top = -1; • push( &top, 1); //원소 삽입 • push( &top, 2); • data = pop( &top) //원소 삭제 • return 0; • }
스택 연산들 • 원소 삽입 연산 삽입 전에 스택이 포화상태인지 검사 void push( int *top, int item ) { if( isFull(*top) ) printf( “Stack is full”); else stack[++(*top)].key = item ; } int isFull( int top) { if( top == (MAX_STACK_SIZE -1) ) return 1; else return 0; }
스택 연산들(계속) • 원소 삭제 연산 삭제 전에 스택이 비어있는지 검사 element pop ( int *top) { if( isEmpty(*top) ) { printf(“Stack Empty”); exit(-1); } else return stack[(*top)--]; } int isEmpty( int top) { if( top == -1 ) return 1; else return 0; }
큐(QUEUE) • 한쪽 끝(rear)에는 데이터가 삽입되고 반대쪽 끝(front)으로는 데이터 삭제가 일어나는 순서 리스트 • 선입선출(first-in-first-out:FIFO) 리스트 먼저 삽입된 원소가 먼저 삭제 <- front <- front <- front, rear 삽입 rear=2,front=0 삽입 rear=0,front=-1 삽입 rear=1,front=-1 삭제 rear=1,front=0 초기상태 rear=front=-1
큐의 추상 데이터 타입 Structure Queue 데이터 : 0개 이상의 원소를 가진 유한 순서 리스트 연산들 : 모든 queue∈Queue, item∈element, max_queue_size∈positive integer QueueCreateQ(max_queue_size) ::=최대 크기가 max_queue_size인 공백 큐를 생성 Boolean IsFullQ(queue, max_queue_size ) ::= if (queue의 원소수 == max_queue_size) return TRUE else return FALSE Queue AddQ(queue, item) ::= if (IsFull(queue)) queue_full else queue의 뒤에 item을 삽입하고 이 queue를 반환 Boolean IsEmptyQ(queue) ::= if (queue == CreateQ(max_queue_size)) return TRUE else return FALSE Element DeleteQ(queue) ::= if (IsEmpty(queue)) return else queue의 앞에 있는 item을 제거해서 반환 end Queue
큐의 표현 • 최대 100개의 원소를 삽입할 수 있는 큐의 데이터 구조 • #define MAX_QUEUE_SIZE 100 • struct element { • int key; • /* 다른 필드 */ • }; • element queue[MAX_QUEUE_SIZE]; • int rear = -1; • int front = -1;
큐의 연산들 • 원소 삽입 연산 삽입 전 큐가 포화상태인지 검사 void addq( int *rear, int item ) { if( isFull(*rear) ) printf( “Queue is full”); else queue[++(*rear)].key = item ; } int isFull( int rear) { if( rear == (MAX_QUEUE_SIZE -1) ) return 1; else return 0; }
큐의 연산들(계속) • 원소 삭제 연산 삭제 전 큐가 비워있는지 검사 element deleteq ( int *front, int rear ) { if( isEmpty(*front, rear) ) printf(“Queue is Empty”); else return queue[++(*front)]; } int isEmpty( int front, int rear) { if( front == rear ) return 1; else return 0; }
선형 큐의 문제점 • 삽입과 삭제를 반복하면서 rear의 값이 MAX_QUEUE_SIZE-1이 되어 포화 상태이지만 front의 값이 양의 값을 가질 때 큐는 실제로는 포화상태가 아님 rear = MAX_QUEUE_SIZE-1 front = rear-1 인 경우, 큐에 원소가 하나 밖에 없지만 큐는 포화상태로 인식 <- front
원형 큐(circular queue) • 배열을 모듈러 연산(mod, %)을 이용하여 원형으로 운영함으로 가상의 원형 큐를 생성 • 초기값 : rear = front = 0 • 공백 상태 : front == rear • 포화상태 : (rear+1)% MAX_QUEUE_SIZE == front • 원소 삽입할 위치 • ( rear +1 ) % MAX_QUEUE_SIZE • 원소 삭제할 위치 • ( front + 1 ) % MAX_QUEUE_SIZE
원형 큐의 삽입 삭제 연산 포화상태일 때 실제로는 한 곳이 비어 있음 EMPTY와 FULL을 구분하기 위해 인덱스 1부터 원소 삽입 초기상태
원형 큐의 연산 • 원소 삽입 연산 void addq( int front, int *rear, int item ) { *rear = (*rear+1) % MAX_QUEUE_SIZE; if( front == *rear ) printf( “Queue is full”); else queue[*rear].key = item ; }
원형 큐의 연산(계속) • 원소 삭제 연산 element deleteq ( int *front, int rear ) { if( *front == rear ) { printf(“Queue is Empty”); exit(-1); } *front = (*front+1)%MAX_QUEUE_SIZE; return queue[*front]; }
단원 정리 • 스택 • 스택의 표현 방법(top) • 스택 연산들(삽입,삭제, 포화상태, 공백상태) • 선형 큐 • 큐의 표현 방법(rear, front) • 큐의 연산들(삽입, 삭제, 포화상태, 공백상태) • 원형 큐 • 선형 큐의 문제점과 원형 큐의 필요성 • 원형 큐의 연산들(선형 큐와의 차이점)
학습 평가 • 컴퓨터 시스템에서 스택과 큐가 사용되어지는 작업의 예를 각각 들어보시오. • 대기시간(실수형)과 작업명(문자열)을 원소로 가지는 원형 큐를 구현해 보시오. 삽입, 삭제 연산 함수와 메인 함수를 작성하여 원형 큐가 수행되어지는 과정을 보이시오.