2012/01/18 00:16

스택 만들기 - 아이오2일차 ( 1단계 ~ 10단계 ) - C++

//#include <iostream>
// using namespace std;

--
 스택을 만들어 봅시다
 oop : 잘못쓰기 어렵게 만들어라 
--
// 버전10. 숙제 : 버전8의 스택을 내부자료구조를 싱글링크드리스트 방식의 template으로 설계해 보세요.

// 버전9. 잘만드는 사람이 stack을 만들어주면 좋지 않을까?? 이미 표준에 있다.
// STL(Standard Template Library)
// 결론 : STL의 다양한 클래스에는 제거와 리턴을 동시에 하는 함수는 거의 없다.
--
#include <iostream>
#include <stack>
using namespace std;

int main()
{
 stack<int> s;
 s.push( 10 );
 s.push( 20 );

 // 20, 10을 화면에 모두 출력해 보세요.
 cout << s.top() << endl;
 s.pop();
 cout << s.top() << endl;
}
--

// 버전8. 최적화 - 성능을 향상시켜보자.
--
template<typename T> struct Stack
{
private :
 T* buff;
 int index;
public :
 Stack( T sz = 100) {
  index = 0;
  buff = new T[ sz ];
 }
 ~Stack()    { delete[] buff;  }

 void Push(const T& a ) { buff[index++] = a; }

 // 제거와 리턴을 동시에 하면, 참조를 리턴할 수 없다. 결국 임시객체가 리턴되므로 성능이 저하된다. = java
 // T Pop()     { return buff[--index]; }

 //  제거와 리턴을 분리하자. = c++
 void Pop()    { --index; }   // 제거만..
 T& Top()    { return buff[index]; } // 리턴만.. 참조리턴이 가능해진다.
};

int main()
{
 Stack<int> s1(100);  // 클래스 템플릿은 반드시 타입을 지정해야 합니다.
 s1.Push( 10 );
 s1.Push( 20 );
 cout << s1.Top() << endl;
 s1.Pop();
 cout << s1.Top() << endl;
 // cout << s2.Pop() << endl;
}
--

// 버전7. 다양한 타입에 대해서 자동으로 Stack 구조체가 Code 생성되게 하자 - template 도입(코드생성기)
// 어디를 바꿔야 하는지 잘 생각하자,
--
template<typename T> struct Stack
{
private :
 T* buff;
 int index;
public :
 Stack( T sz = 100) {
  index = 0;
  buff = new T[ sz ];
 }
 ~Stack()   { delete[] buff;  }

 void Push( T a ) { buff[index++] = a; }
 T Pop()   { return buff[--index]; }
};

int main()
{
 Stack<int> s1(100);  // 클래스 템플릿은 반드시 타입을 지정해야 합니다.
 Stack<double> s2;
 s1.Push( 10 );
 cout << s1.Pop() << endl;
 // cout << s2.Pop() << endl;
}
--


// 버전6. 내부자료구조의 변경 - 동적메모리 할당./
--
struct Stack
{
private :
 int* buff;
 int index;
public :
 // 생성자 : 구조체(클래스)이름과 동일한 함수, 객체를 생성하면 자동으로 호출된다.
 Stack( int sz = 100) {
  index = 0;
  buff = new int[ sz ];
 }
 // 소멸자 : 객체가 파괴될 때, 자동으로 호출된다 => 여기서 객체가 사용한 자원을 해지한다.
 ~Stack()   { delete[] buff;  }

 void Push( int a ) { buff[index++] = a; } // 버전6의 문제점, 타입이 항상 int ???
 int Pop()   { return buff[--index]; }
};

int main()
{
 Stack s1(100);  // 주면 주는거고,
 Stack s2();   // 안주면 기본값으로 내가줄게.
 s1.Push( 10 );
 cout << s1.Pop() << endl;
 //cout << s2.Pop() << endl;
}
--

 

// 버전5. 객체의 초기화를 자동으로 되게 하자 => 생성자 도입
--
struct Stack
{
private :
 int buff[10];  // 맴버 data   // 버전5의 문제점, 항상10개???
 int index;
public :
 // 생성자 : 구조체(클래스)이름과 동일한 함수, 객체를 생성하면 자동으로 호출된다.
 Stack()    { index = 0;   }
 void Push( int a ) { buff[index++] = a; }
 int Pop()   { return buff[--index]; }
};

int main()
{
 Stack s1, s2;
 // s1.init();
 s1.Push( 10 );
 cout << s1.Pop() << endl;
}
--


// 버전4. 객체의 상태를 외부에 직접 노출하면 잘못된 사용으로 객체가 불안해 진다.
//    외부에 잘못된 사용으로 부터 객체를 보호해야 한다.
//    용어 : 정보은닉, 좁은의미의 캡슐화
--
struct Stack
{
private :
 int buff[10];  // 맴버 data
 int index;
public :
 void init()   { index = 0;   } // 맴버함수 : 맴버data에 직접 접근할 수 있다.
 void Push( int a ) { buff[index++] = a; }
 int Pop()   { return buff[--index]; }
};

int main()
{
 Stack s1, s2;
 s1.init();    // 버전4의 문제점. 항상 직접 초기화를 해주어야 하나???
 s1.Push( 10 );
 // s1.index = 100;  // error. private를 외부에서 직접 접근할 수 없다.
 cout<< s1.Pop() << endl;
}
--

// 버전3. 상태를 나타내는 date와 상태를 조작하는 함수를 묶자 = > 넓은 의미의 캡슐화
--
struct Stack
{
 int buff[10];  // 맴버 data
 int index;

 void init()   { index = 0;   } // 맴버함수 : 맴버data에 직접 접근할 수 있다.
 void Push( int a ) { buff[index++] = a; }
 int Pop()   { return buff[--index]; }
};

int main()
{
 Stack s1, s2;
 s1.init();
 s1.Push( 10 );
 s1.index = 100;  // 버전3의 문제점... 스택이 깨진다 : 함수만 쓰면 되는데, 가져다 쓸 수 없게끔 해야 한다.
 cout<< s1.Pop() << endl;
}
--


// 버전2. 스택이라는 타입을 먼저 설계하자 - c 구조체 사용( c로 만들수 있는 최대 )
--
struct Stack
{
 int buff[10];
 int index;
};

void init( Stack* this )  { this->index = 0; }     // 맴버함수호출의 원리..
void push( Stack* s, int a ) { s->buff[ s-> index++] = a;  }
int pop( Stack* s)    { return s->buff[--(s->index)]; }

int main()
{
 Stack s1, s2;  // stack 2개
 init(&s1);
 push(&s1, 10);
 cout << pop(&s1) << endl;
}
--


// 버전1. 전역변수 사용 - 문제점 : 스택이 2개 필요하면 ???
--
int buff[10];
int index = 0;

void push( int a )  { buff[index++] = a; }
int pop()    { return buff[--index]; }

int main()
{
 push(10);
 push(20);

 cout << pop() << endl;
}
--


1 2 3 4 5 6 7 8 9 10 다음