650 likes | 1.09k Views
자 료 구 조. 제 3 장 스택과 큐. 3.1 C++ 의 템플리트. 3.1 C++ 의 템플리트. ▶ 템플리트 함수 - 클래스와 함수의 재사용에 기여 (1) 템플리트 함수를 사용하지 않는 경우 ( 예 ) 정수 배열을 위한 선택 정렬 함수 sort( 프로그램 1.6) 부동 소수점 수의 배열을 정렬하려면 ? . 첫째 행에서 int *a 를 float *a 로 변경 . 둘째 행에서 정수를 부동 소수점 수로 변경 . 11 번째 행에서 int 를 float 로 변경
E N D
자 료 구 조 제 3 장 스택과 큐
3.1 C++의 템플리트 • ▶ 템플리트 함수 • - 클래스와 함수의 재사용에 기여 • (1) 템플리트 함수를 사용하지 않는 경우 • (예) 정수 배열을 위한 선택 정렬 함수 • sort(프로그램 1.6) • 부동 소수점 수의 배열을 정렬하려면? • . 첫째 행에서 int *a를 float *a로 변경 • . 둘째 행에서 정수를 부동 소수점 수로 변경 • . 11번째 행에서 int를 float로 변경 • (2) 템플리트 / 인수화타입(parameterized type)을 • 이용한 해결 • - 다음 템플리트 함수 sort는 int나 float의 배열을 • 모두 정렬
3.1 C++의 템플리트 • ------------------------------------------ • template <class KeyType> • void sort(KeyType *a, int n){ • // n개의 KeyType a[0]부터 a[n-1]까지 비감소순으로 정렬 • for( int i=0; i<n; i++) • { • int j = i; • // a[i]와 a[n-1] 사이에 가장 작은 KeyType을 찾는다 • for( int k = i+1; k<n; k++) • if( a[k] < a[j]) j = k; • // 교환 • KeyType temp = a[i]; a[i] = a[j]; a[j] = temp; • } • } • ------------------------------------------ • 프로그램 3.1: 템플리트를 이용한 선택 정렬 • - 템플리트 함수 sort 이용 예 • ------------------------------------------ • float farray[100]; • int intarray[250]; • ... • // 이 시점에서 배열들이 초기화된다고 가정한다 • sort(farray, 100); • sort(intarray, 250); • ------------------------------------------ • 프로그램 3.2: 템플리트 인스턴스화를 보여주는 코드의 일부
3.1 C++의 템플리트 • * 사용상의 주의 사항 : • . <, =, 및 복사 생성자 • . int와 float에 대해서는 자동적으로 정의 • . 사용자 정의 데이타 타입에 대해서는 별도로 정의 • 하여야 함 • (예) sort를 이용해 Rectangle 배열을 넓이 • 오름차순으로 정렬 • -> operator < 정의 필요 • -> 지정 연산자, 복사 생성자는 컴파일러의 묵시적 • 구현으로 충분
3.1 C++의 템플리트 • ▶ 템플리트 클래스 • - 클래스의 재사용에 기여 • (1) 컨테이너 클래스(container class) • - 여러 데이타 객체들을 저장하는 데이타 구조를 • 표현하는 클래스 • (예) 배열, 백(Bag) • - 객체들의 삽입과 삭제가 가능 • - 백(Bag) • . 동일한 원소가 여러 번 나타남 • . 원소 위치, 삭제 연산시 어떤 원소가 제거 • 되는지는 문제 안됨 • -> 삽입: 해당 원소를 배열의 첫번째 가용 • 위치에 저장 • -> 삭제: 배열 중앙 위치 원소 삭제. 그 오른쪽 • 모든 원소는 한 자리씩 왼쪽으로 이동.
3.1 C++의 템플리트 • (2) 템플리트 클래스를 사용하지 않은 Bag 클래스 정의 예 • ----------------------------------------- • class Bag { • public: • Bag (int MaxSize = DefaultSize); //생성자 • ~Bag(); // 파괴자 • void Add(int); // 정수 하나를 백에 삽입 • int *Delete(int&); //백에서 정수 하나를 삭제 • Boolean IsFull(); • // 백이 포화상태이면 TRUE, 그렇지 않으면 FALSE를 반환 • Boolean IsEmpty(); • // 백이 공백상태이면 TRUE, 그렇지 않으면 FALSE를 반환 • private: • void Full(); // 백이 포화상태일 때의 조치 • void Empty(); // 백이 공백상태일 때의 조치 • int *array; • int MaxSize; // 배열의 크기 • int top; // 배열에서 원소가 들어 있는 가장 높은 위치 • -----------------------------------------프로그램 3.3: 정수를 포함하는 클래스 Bag의 정의
- 클래스 Bag의 연산 구현 • --------------------------------------- • Bag::Bag (int MaxBagSize): MaxSize (MaxBagSize) • { array = new int[MaxSize]; top = -1; } • Bag::~Bag() { delete [] array; } • inline Boolean Bag::IsFull() • { if (top == MaxSize-1) return TRUE; • else return FALSE; } • inline Boolean Bag::IsEmpty() • { if (top == -1) return TRUE; • else return FALSE; } • inline void Bag::Full() • { cerr << "Data structure is full" << endl; } • inline void Bag::Empty() • { cerr << "Data structure is empty" << endl; } • void Bag::Add(int x) • { if( IsFull()) Full(); • else array[++top] = x; } • int* Bag::Delete(int& x) • { if( IsEmpty()) { Empty(); return 0; } • int deletePos = top/2; x = array[deletePos]; • for ( int index = deletePos; index<top; index++) • array[index] = array[index+1]; • //배열의 상반을 집약한다 • top--; return &x; • } • --------------------------------------- • 프로그램 3.4: Bag에 대한 연산들의 구현
3.1 C++의 템플리트 • (3) 템프리트 클래스를 이용한 Bag의 구현 • - 어떠한 데이타 타입의 객체들도 저장 • -----------------------------------------template <class Type> • class Bag • { • public: • Bag (int MaxSize = DefaultSize); //생성자 • ~Bag(); // 파괴자 • void Add(const Type&); // 원소 하나를 백에 삽입 • Type *Delete(Type&); //백에서 원소 하나를 삭제 • Boolean IsFull(); • // 백이 포화상태이면 TRUE, 그렇지 않으면 FALSE를 반환 • Boolean IsEmpty(); • // 백이 공백상태이면 TRUE, 그렇지 않으면 FALSE를 반환 • private: • void Full(); // 백이 포화상태일 때의 조치 • void Empty(); // 백이 공백상태일 때의 조치 • Type *array; • int MaxSize; // 배열의 크기 • int top; // 배열에서 원소가 들어 있는 가장 높은 위치 • } • ----------------------------------------- • 프로그램 3.5: 템플리트 클래스 Bag의 정의 • - 템플리트 클래스 Bag을 int와 Rectangle로 인스턴스화 • Bag<int> a; Bag<Rectangle> r;
-------------------------------------- • template <class Type> • Bag<Type>::Bag (int MaxBagSize): • MaxSize (MaxBagSize) { • array = new Type[MaxSize]; • top = -1; • } • template <class Type> • Bag<Type>::~Bag() { delete [] array; } • template <class Type> • void Bag<Type>::Add(const Type& x) { • if( IsFull()) Full(); • else array[++top] = x; • } • template <class Type> • Type* Bag<Type>::Delete(Type& x) { • if( IsEmpty()) { Empty(); return 0;} • int deletePos = top/2; • x = array[deletePos]; • for ( int index = deletePos; index<top; index++) • array[index] = array[index+1]; //배열의 상반을 • //집약한다 • top--; • return &x; • } • -------------------------------------- • 프로그램 3.6: Bag에 대한 연산들의 구현
3.2 스택 추상 데이타 타입 • - 순서 리스트의 특별한 경우 • 순서 리스트 : A = a0, a1, ... , an-1, n ≥ 0 • ▶ 스택(stack) • 톱(top)이라고 하는 한쪽 끝에서 모든 삽입(push)과 삭제(pop)가 일어나는 순서 리스트 . 스택 S=(a0,....,an-1) : a0는 bottom, an-1은 top의 원소 . ai는 원소 ai-1(0<i<n)의 위에 있음 - 후입선출(LIFO, Last-In-First-Out) 리스트 - 원소 A,B,C,D,E를 삽입하고 한 원소를 삭제하는 예
3.2 스택 추상 데이타 타입 • 그림 3.1: 스택에서의 삽입과 삭제
3.2 스택 추상 데이타 타입 • 예제 3.1 [시스템 스택]: • - 프로그램 실행시 함수 호출을 처리 - 함수 호출시 활성 레코드 (activation record) 또는 스택 프레임(stack frame) 구조 생성 . 이전의 스택 프레임에 대한 포인터 . 복귀 주소 . 지역 변수 . 매개 변수 - 함수가 자기자신을 호출하는 순환 호출도 마찬가지 로 처리 -> 순환 호출시마다 새로운 스택 프레임 생성 -> 최악의 경우 가용 메모리 전부 소모
3.2 스택 추상 데이타 타입 • - 주 함수가 함수 a1을 호출하는 예 그림 3.2: 함수 호출 후의 시스템 스택
- 스택 ADT • --------------------------------------- • template <class KeyType> • class Stack{ • // objects: 0개 이상의 원소를 가진 유한 순서 리스트 • public: • Stack (int MaxStackSize = DefaultSize); • // 최대 크기가 MaxStackSize인 공백 스택을 생성 • Boolean IsFull(); • // 스택 내에 있는 원소의 수가 스택의 최대크기와 같은 • // 경우 TRUE (1), 그렇지 않은 경우 FALSE (0)을 반환 • void Add(const KeyType& item); • // IsFull()이 TRUE이면 StackFull()을 호출하고, • // 그렇지 않으면 스택의 톱에 item을 삽입 • Boolean IsEmpty(); • // 스택 내에 있는 원소의 수가 0인 경우 TRUE (1), • // 그렇지 않은 경우 FALSE (0)을 반환 • KeyType* Delete(KeyType&); • // IsEmpty()가 TRUE이면 StackEmpty()을 호출하고 • // 0을 반환, • // FALSE 이면 스택의 톱 원소를 제거하고 그 포인터를 • 반환 • }; • ----------------------------------------- • ADT 3.1: 추상 데이타 타입 Stack
3.2 스택 추상 데이타 타입 - 스택 구현: 일차원 배열 stack[MaxSize] 사용 . i번째 원소는 stack[i-1]에 저장 . 변수 top은 스택의 최상위 원소를 가리킴 (초기 : top = -1) ---------------------------------------- Private: int top; KeyType *stack; int MaxSize; Template <class KeyType> Stack<KeyType>::Stack (int MaxStackSize): MaxSize (MaxStackSize) { stack = new KeyType[MaxSize]; top = -1; }
3.2 스택 추상 데이타 타입 - 멤버 함수 IsFull()과 IsEmpty() 구현 template <class KeyType> inline Boolean Stack<KeyType>::IsFull() { if (top == MaxSize-1) return TRUE; else return FALSE; } template <class KeyType> inline Boolean Stack<KeyType>::IsEmpty() { if (top == -1) return TRUE; else return FALSE; }
3.2 스택 추상 데이타 타입 - Add와 Delete 연산 구현 --------------------------------- template <class KeyType> void Stack<KeyType>::Add(const KeyType& x) // stack에 x를 삽입 { if (IsFull()) StackFull(); else stack[++top] = x; } ----------------------------------------프로그램 3.7: 스택에로의 삽입 ----------------------------------------template <class KeyType> KeyType* Stack<KeyType>::Delete(KeyType& x) // stack에서 톱 원소를 제거 { if (IsEmpty()) { StackEmpty(); return 0; } x = stack[top--]; return &x; } ----------------------------------------프로그램 3.8: 스택으로부터 삭제 *주의 : Delete의 반환값은 KeyType* 타입 -> 공백인 경우는 0을 반환
3.3 큐 추상 데이터 타입 ▶ 큐(queue) - 한쪽 끝(rear)에서 삽입이 일어나고 반대쪽 끝(front)에서 삭제가 일어나는 순서 리스트 . 큐 Q=(a0, a1, ... , an-1): a0는 앞(front) 원소 an-1은 뒤(rear) 원소 . ai는 ai-1(1≤i<n)의 뒤에 있다고 함 - 선입선출(FIFO, First-In-First-Out) 리스트
3.3 큐 추상 데이터 타입 - 원소 A,B,C,D,E를 삽입하고 한 원소를 삭제하는 예 그림 3.4: 큐에서의 삽입과 삭제
3.3 큐 추상 데이터 타입 - 큐 ADT ------------------------------------------ template <class KeyType> class Queue{ // objects: 0개 이상의 원소를 가진 유한 순서 리스트 public: Queue (int MaxQueueSize = DefaultSize); // 최대 크기가 MaxQueueSize인 공백 큐를 생성 Boolean IsFull(); // 큐 내에 있는 원소의 수가 큐의 최대크기와 같은경우 // TRUE (1), 그렇지 않은 경우 FALSE (0)을 반환 void Add(const KeyType& item); // IsFull()이 TRUE이면 QueueFull()을 호출, // 그렇지 않으면 큐의 뒤에 item을 삽입 Boolean IsEmpty(); // 큐 내에 있는 원소의 수가 0인 경우 TRUE (1), // 그렇지 않은 경우 FALSE (0)을 반환 KeyType* Delete(KeyType&); // IsEmpty()가 TRUE이면 QueueEmpty()를 호출하고 // 0을 반환, FALSE이면 큐의 앞 원소를 제거하고 // 그 포인터를 반환 }; ------------------------------------------ ADT 3.2: 추상 데이타 타입 Queue
3.3 큐 추상 데이터 타입 • - 큐의 구현: 1차원 배열 이용 • . 변수 front는 큐에서 첫 원소의 위치 • 보다 하나 작은 위치 • . 변수 rear는 큐에서 마지막 원소의 위치 • Private: • int front, rear; • KeyType *queue; • int MaxSize; • template <class KeyType> • Queue<KeyType>::Queue (int MaxQueueSize): • MaxSize (MaxQueueSize) • { • queue = new KeyType[MaxSize]; • front = rear = -1; • }
3.3 큐 추상 데이터 타입 - 멤버 함수 IsFull()과 IsEmpty() 구현 template <class KeyType> inline Boolean Queue<KeyType>::IsFull() { if (rear == MaxSize-1) return TRUE; else return FALSE; } template <class KeyType> inline Boolean Queue<KeyType>::IsEmpty() { if (front == rear) return TRUE; else return FALSE; } * 주의 : IsFull() 구현은 ADT 3.2 명세와 다름 - rear = MaxSize-1이고 front > -1이 될 수 있기 때문 -> 이 경우 큐 원소수가 MaxSize보다 작음
3.3 큐 추상 데이터 타입 - Add와 Delete 구현 -------------------------------------- template <class KeyType> void Queue<KeyType>::Add(const KeyType& x) // queue에 x를 삽입 { if (IsFull()) QueueFull(); else queue[++rear] = x; } -------------------------------------- 프로그램 3.9: 큐에 삽입 -------------------------------------- template <class KeyType> KeyType* Queue<KeyType>::Delete(KeyType& x) // 큐에서 앞 원소를 제거 { if (IsEmpty()) { QueueEmpty(); return 0;} x = queue[++front]; return &x; } --------------------------------------- 프로그램 3.10: 큐에서의 삭제
3.3 큐 추상 데이터 타입 • ▶ 큐의 순차적 표현의 문제점 예 • 예제 3.2 [작업 스케쥴링]: • - 운영체제의 작업 큐(job queue) : FCFS 스케쥴링 • 작업들이 큐에 들어가고 나옴에 따라 큐는 점차 • 오른쪽으로 이동 • -> 결국 rear 값이 MaxSize-1과 같아져서 큐가 • 포화 상태가 됨 • - QueueFull()의 업무 • . 전체 큐를 왼쪽으로 이동(shift) • -> 첫째 원소가 q[0]에 가도록 • . front를 -1로, rear 값도 조정 • . 이러한 배열 이동에 많은 시간 소요 • -> 최악의 경우: O(MaxSize)
3.3 큐 추상 데이터 타입 • 그림 3.5: 큐에서의 삽입과 삭제 • 큐 포화시마다 전체 큐를 왼쪽 이동시 • 최악의 경우 • . 큐에 n개의 원소 J1,...,Jn이 있음 • . 그 후 삽입과 삭제가 교대로 이루어짐 • . 새 원소 삽입시마다 n-1개의 원소 가진 큐 • 전체 왼쪽 이동
3.3 큐 추상 데이터 타입 그림 3.6: 큐의 예
3.3 큐 추상 데이터 타입 ▶ 순차적 큐의 문제 해결: 원형 큐 - 배열 queue[MaxSize]를 원형으로 취급 -> rear == MaxSize-1이면 q[0]가 빈 경우 q[0]에 삽입 - 최대 원소 수: MaxSize가 아니라 MaxSize-1 -> front == rear가 포화상태인지, 공백상태인지 구분하기 위함 - 초기: front == rear == 1 - 공백: front == rear
3.3 큐 추상 데이터 타입 - 네 원소 J1-J4 가진 원형 큐 그림 3.7: MaxSize = n 이고 네 개의 작업 J1, J2, J3, J4를 가진 원형 큐
3.3 큐 추상 데이터 타입 - 원형 큐에 대한 삽입 연산 . rear 증가(circular shift) if (rear == MaxSize-1) k = 0; else k = rear+1; ≡ (rear+1) % MaxSize . 포화 상태 검사(front == k), 포화 아니면 새원소 삽입 ------------------------------------ template <class KeyType> void Queue<KeyType>::Add(const KeyType& x) // 원형 큐에 x를 삽입 { int k = (rear+1) % MaxSize; if (front == k) QueueFull(); else queue[rear=k] = x; } ------------------------------------ 프로그램 3.11: 원형 큐에 삽입
3.3 큐 추상 데이터 타입 - 원형 큐에 대한 삭제 연산 . 먼저 empty 테스트 . front 이동: ++front %= MaxSize ------------------------------------ template <class KeyType> KeyType* Queue<KeyType>::Delete(KeyType& x) // 원형 큐에서 앞 원소를 제거 { if (front == rear) { QueueEmpty(); return 0; } x = queue[++front %= MaxSize]; return &x; } ------------------------------------ 프로그램 3.12: 원형 큐에서의 삭제
3.4 C++의 서브타입과 계승 - 계승(inheritance) : 추상 데이타 타입간의 서브타입(subtype) 관계를 표현 . IS-A(~의 하나이다) 관계 ex) . 의자: 가구의 서브타입(IS-A) . 사자: 포유류의 서브타입(IS-A) . 직사각형: 다각형의 서브타입(IS-A). - Bag과 Stack간의 관계 . 백(bag) : 단순히 원소들이 삽입과 삭제가 될 수 있는 자료구조 . 스택 : 원소들이 후입선출 순서에 따라 삭제되는 자료 구조(제한적) . Stack은 Bag의 하나(IS-A) 즉 Stack은 Bag의 서브타입
3.4 C++의 서브타입과 계승 - C++의 공용 계승(public inheritance) : IS-A 관계를 표현 class Stack : public Bag { } - 일반적인 추상 데이타 타입을 표현하는 클래스 : 기본 클래스(base class) - Bag - 추상 데이타 타입을 표현하는 클래스 : 파생 클래스(derived class) - Stack Note : Virtual 멤버 함수 선언 : 기본 클래스 구현 : 파생 클래스
3.4 C++의 서브타입과 계승 -----------------------------------------class Bag { Public: Bag (int MaxSize = DefaultSize); // 생성자 virtual ~Bag(); // 파괴자 virtual void Add(int); // 백에 원소를 삽입한다 virtual int *Delete(int&); // 백에서 원소를 삭제한다 virtual Boolean IsFull(); // 백이 포화상태이면 TRUE, // 그렇지 않으면 FALSE를 반환 virtual Boolean IsEmpty(); // 백이 공백상태이면 TRUE, // 그렇지 않으면 FALSE를 반환 Protected: virtual void Full(); // 백이 포화상태일 때의 조치 virtual void Empty();// 백이 공백상태일 때의 조치 int *array; int MaxSize; // 배열의 크기 int top; // 배열에서 원소가 있는 가장 높은 위치 }; class Stack: public Bag { Stack (int MaxSize = DefaultSize); // 생성자 ~Stack(); // 파괴자 int *Delete(int&); // 스택에서 원소를 삭제한다 }; -----------------------------------------프로그램 3.13: Bag과 Stack의 정의
3.4 C++의 서브타입과 계승 • 계승의 의미: • - 파생 클래스(Stack)가 기본 클래스(Bag)의 모든 • 비전용(공용, 보호) 멤버(데이타와 함수)들을 • 계승받음 • 계승된 멤버들은 기본 클래스에서 가졌던 것과 • 똑같은 접근 레벨을 파생클래스에서도 가짐 • - 계승 받은 멤버함수는 같은 프로토 타입 유지 • : 기본 클래스 인터페이스 재사용
3.4 C++의 서브타입과 계승 ---------------------------------------- Stack::Stack (int MaxStackSize): Bag(MaxStackSize) { } // Stack 생성자는 Bag 생성자를 호출한다. Stack::~Stack() { } // Stack이 파괴될 때 Bag 파괴자는 자동으로 호출된다. // 이것이 array가 제거되는 것을 보장한다. int *Stack::Delete(int& x) { if (IsEmpty()) Empty(); return 0; x = array[top--]; return &x; } ---------------------------------------- 프로그램 3.14: Stack 연산의 구현
계승 작동 예 : Bag b(3); //크기3의 배열을 생성하기위하여 Bag의 생성자를 이용 Stack s(3); //크기3의 배열을 생성하기위하여 Stack의 생성자를 이용 b.Add(1); b.Add(2); b.Add(3); // Bag::Add를 사용한다. // Bag::Add는 함수 Bag::IsFull과 Bag::Full을 호출 s.Add(1); s.Add(2); s.Add(3); // Stack::Add가 정의되지 않았으므로 Bag::Add를 사용 // Bag::Add는 Bag::IsFull과 Bag::Full을 호출 // 왜냐하면 이들은 Stack에서 재정의되지 않았기 때문 int x; b.Delete(x); // Bag::Delete를 사용 // 이것은 Bag::IsEmpty와 Bag::Empty를 호출 s.Delete(x); // Stack::Delete를 사용 // 이것은 Bag::IsEmpty와 Bag::Empty를 호출 // 왜냐하면, 이들이 Stack에서 재정의되지 않았기 때문
3.4 C++의 서브타입과 계승 - Queue ADT도 Bag의 서브타입 . 선입선출 순서로 원소가 삭제되는 자료 구조 . Queue도 Bag의 한 파생 클래스로 표현 가능
0 1 0 1 1 0 0 0 0 1 0 0 0 1 1 0 1 1 1 0 1 0 0 1 0 1 0 1 0 0 1 1 1 1 0 0 0 1 0 1 1 1 1 1 0 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0 1 1 1 1 0 1 1 1 1 0 1 0 1 0 1 1 1 1 1 1 1 0 0 1 0 1 1 0 1 0 0 0 1 0 1 1 1 1 1 0 1 1 1 0 0 1 0 1 1 1 1 1 1 1 0 1 0 1 1 0 1 0 1 1 0 0 1 1 0 1 0 1 0 0 1 1 1 1 0 1 1 0 0 1 0 0 1 1 1 1 1 1 1 1 1 1 0 1 0 1 1 0 0 1 0 1 1 1 1 1 0 1 1 1 1 0 0 0 1 1 3.5 미로 문제 미로는 1≤i≤m이고 1≤j≤p인 이차원 배열 maze[m][p]로 표현 1 : 통로가 막혀 있음 0 : 통과할 수 있음 입구 출구 그림 3.8: 예제 미로 maze[m+2][p+2] mark[m+2][p+2] : 시도한 위치 표시
3.5 미로 문제 현재의 위치 x : maze[i][j] 그림 3.9 : 가능한 이동
3.5 미로 문제 struct offsets { int a, b; }; enum directions {N, NE, E, SE, S, SW, W, NW}; offsets move[8]; 그림 3.10 : 이동 테이블 [i][j]에서 SW, 즉 [g][h]로 이동 → g = i + move[sw].a; h = j + move[sw].b;
3.5 미로 문제 stack은 미로 입구 좌표, 방향(dir)은 동(E)으로 초기화 while (stack이 공백이 아님) { (i, j, dir) = stack의 top에 있는 좌표와 방향; while (이동이 계속 가능) { (g, h) = 다음 이동 좌표; if ((g == m) && (h == p)) 경로 발견 성공; if (!maze[g][h] // 적법한 이동 && !mark[g][h]) // 전에 온 적이 없는 곳 { mark[g][h] = 1; dir = 다음에 시도할 방향; (i, j, dir)를 stack의 top에 삽입; i =g; j = h; dir = north; } } } cout << "No path found" << endl; -------------------------------------- 프로그램 3.15: 초기 미로 알고리즘
3.5 미로 문제 입구 출구
3.5 미로 문제 - path에서 배열 maze, mark, move는 전역적이라고 가정 - stack은 items의 스택으로 정의 struct items { int x, y, dir; };
------------------------------------------ void path(int m, int p) { // 경로가 있으면 출력한다. maze[0][i]= maze[m+1][i] = // maze[j][0] = maze[j][p+1] = 1, 0≤i≤p+1, 0≤j≤m+1. // (1, 1)에서 시작 mark[1][1]=1; stack<items> stack(m*p); items temp; temp.x = 1; temp.y = 1; temp.dir = E; stack.Add(temp); while (!stack.IsEmpty()) { // 스택이 공백이 아님 temp = *stack.Delete(temp); // 스택에서 삭제 while (d < 8) { // 앞으로 이동 int g = i + move[d].a; int h = j + move[d].b; if ((g == m) && (h == p)) { // 출구 도착,경로 출력 cout << stack; cout << i << " " << j << endl; // 경로상의 마지막 두 위치 cout << m << " " << p << endl; return; } if ((!maze[g][h]) && (!mark[g][h])) {//새로운 위치 mark[g][h] = 1; temp.x = i; temp.y = j; temp.dir = d+1; stack.Add(temp); // 스택에 삽입 i = g; j = h; d = N; // (g, h)로 이동 } else d++; // 다음 방향으로 시도 } } cout << "no path in maze" << endl; } ------------------------------------------ 프로그램 3.16: 미로 탐색 함수
3.5 미로 문제 - operator << ; stack 과 item에 대해 다중화 - friend로 선언되어 stack의 전용 데이타 멤버 접근 가능 -----------------------------------------template <class KeyType> ostream& operator<<(ostream& os, Stack<KeyType>& s) { os << "top = " << s.top << endl; for (int i = 0; i <= s.top; i++) os << i << ":" << s.stack[i] << endl; return os; } ostream& operator<<(ostream& os, items& item) { return os << item.x << "," << item.y << "," << item.dir; } ----------------------------------------- 프로그램 3.17: 연산자 <<의 다중화