Skip to content

Commit

Permalink
Merge pull request #4 from deunlee/Study
Browse files Browse the repository at this point in the history
Apply template to Stack and add Graph interface
  • Loading branch information
deunlee committed Jun 2, 2020
2 parents 97f8ad5 + 385acc0 commit afc5b4c
Show file tree
Hide file tree
Showing 17 changed files with 623 additions and 162 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,7 @@
*.out
*.app

.vs
# IDE
x64
.vs
.vscode
6 changes: 3 additions & 3 deletions Graph/AdjacencyList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Deun {
AdjacencyList::AdjacencyList(int vSize) {
if (vSize <= 0) {
this->vSize = 0;
throw AdjacencyListError::MEMORY_ALLOCATION_FAILED;
throw GraphError::MEMORY_ALLOCATION_FAILED;
}

this->vSize = vSize;
Expand All @@ -16,7 +16,7 @@ namespace Deun {

if (!list) {
this->vSize = 0;
throw AdjacencyListError::MEMORY_ALLOCATION_FAILED;
throw GraphError::MEMORY_ALLOCATION_FAILED;
}

for (int i = 0; i < vSize; i++) {
Expand All @@ -33,7 +33,7 @@ namespace Deun {
if (vCount < vSize) {
return vCount++;
}
throw AdjacencyListError::TOO_MANY_VERTICES;
throw GraphError::TOO_MANY_VERTICES;
}

bool AdjacencyList::insertEdge(int from, int to, bool undirected) {
Expand Down
14 changes: 4 additions & 10 deletions Graph/AdjacencyList.h
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
#ifndef __DEUN_GRAPH_ADJ_LIST_H__
#define __DEUN_GRAPH_ADJ_LIST_H__

#include <iostream>
#include <new>
#include "Graph.h"

namespace Deun {
enum class AdjacencyListError {
MEMORY_ALLOCATION_FAILED = 1000,
TOO_MANY_VERTICES,
};

typedef struct AdjacencyListNode {
int vertex;
struct AdjacencyListNode* next;
Expand All @@ -18,7 +12,7 @@ namespace Deun {
/**
* 인접 리스트 그래프 (연결 리스트 기반)
*/
class AdjacencyList {
class AdjacencyList : public Graph {
protected:
int vSize; // 정점의 최대 개수 (메모리 할당량)
int vCount; // 정점의 개수
Expand All @@ -29,7 +23,7 @@ namespace Deun {
* 인접 리스트 생성자
*
* @param {int} vSize: 정점의 최대 개수
* @throw {AdjacencyListError} 메모리 할당 오류
* @throw {GraphError} 메모리 할당 오류
*/
AdjacencyList(int vSize = 1000);

Expand All @@ -42,7 +36,7 @@ namespace Deun {
* 정점을 삽입하고 삽입된 정점의 인덱스를 반환합니다.
*
* @return {int} 삽입된 정점의 인덱스(0-based)
* @throw {AdjacencyListError} 정점 개수 초과 오류
* @throw {GraphError} 정점 개수 초과 오류
*/
int insertVertex();

Expand Down
10 changes: 5 additions & 5 deletions Graph/AdjacencyMatrix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ namespace Deun {
AdjacencyMatrix::AdjacencyMatrix(int vSize) {
if (vSize <= 0) {
this->vSize = 0;
throw AdjacencyMatrixError::MEMORY_ALLOCATION_FAILED;
throw GraphError::MEMORY_ALLOCATION_FAILED;
}

this->vSize = vSize;
vCount = 0;
matrix = new (std::nothrow) char[vSize * vSize];
matrix = new (std::nothrow) bool[vSize * vSize];

if (!matrix) {
this->vSize = 0;
throw AdjacencyMatrixError::MEMORY_ALLOCATION_FAILED;
throw GraphError::MEMORY_ALLOCATION_FAILED;
}

clear();
Expand All @@ -27,7 +27,7 @@ namespace Deun {
}

inline bool AdjacencyMatrix::getRaw(int from, int to) {
return (bool)matrix[from * vSize + to];
return matrix[from * vSize + to];
}

inline void AdjacencyMatrix::setRaw(int from, int to, bool value) {
Expand All @@ -38,7 +38,7 @@ namespace Deun {
if (vCount < vSize) {
return vCount++;
}
throw AdjacencyMatrixError::TOO_MANY_VERTICES;
throw GraphError::TOO_MANY_VERTICES;
}

bool AdjacencyMatrix::insertEdge(int from, int to, bool undirected) {
Expand Down
16 changes: 5 additions & 11 deletions Graph/AdjacencyMatrix.h
Original file line number Diff line number Diff line change
@@ -1,23 +1,17 @@
#ifndef __DEUN_GRAPH_ADJ_MATRIX_H__
#define __DEUN_GRAPH_ADJ_MATRIX_H__

#include <iostream>
#include <new>
#include "Graph.h"

namespace Deun {
enum class AdjacencyMatrixError {
MEMORY_ALLOCATION_FAILED = 1000,
TOO_MANY_VERTICES,
};

/**
* 인접 행렬 그래프 (배열 기반)
*/
class AdjacencyMatrix {
class AdjacencyMatrix : public Graph {
protected:
int vSize; // 정점의 최대 개수 (메모리 할당량)
int vCount; // 정점의 개수
char* matrix; // 인접 행렬
bool *matrix; // 인접 행렬

inline bool getRaw(int from, int to);
inline void setRaw(int from, int to, bool value);
Expand All @@ -27,7 +21,7 @@ namespace Deun {
* 인접 행렬 생성자
*
* @param {int} vSize: 정점의 최대 개수
* @throw {AdjacencyMatrixError} 메모리 할당 오류
* @throw {GraphError} 메모리 할당 오류
*/
AdjacencyMatrix(int vSize = 1000);

Expand All @@ -40,7 +34,7 @@ namespace Deun {
* 정점을 삽입하고 삽입된 정점의 인덱스를 반환합니다.
*
* @return {int} 삽입된 정점의 인덱스(0-based)
* @throw {AdjacencyMatrixError} 정점 개수 초과 오류
* @throw {GraphError} 정점 개수 초과 오류
*/
int insertVertex();

Expand Down
34 changes: 34 additions & 0 deletions Graph/Graph.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,40 @@
#ifndef __DEUN_GRAPH_H__
#define __DEUN_GRAPH_H__

#include <iostream>
#include <new>

namespace Deun {
/**
* 그래프 인터페이스
*/
class Graph {
private:
void __dfs(int vertex, bool* visited);

protected:
int vSize; // 정점 개수 (메모리 할당량)

public:
virtual int insertVertex() = 0;
virtual bool insertEdge(int from, int to, bool undirected = false) = 0;

virtual bool hasVertex(int v) = 0;
virtual bool hasEdge(int from, int to) = 0;

virtual void clear() = 0;
virtual void print() = 0;

bool dfs(int vertex);
};

/**
* 그래프 오류
*/
enum class GraphError {
MEMORY_ALLOCATION_FAILED = 1000,
TOO_MANY_VERTICES,
};
}

#endif
80 changes: 80 additions & 0 deletions Stack/ArrayStack.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#ifndef __DEUN_ARRAY_STACK_H__
#define __DEUN_ARRAY_STACK_H__

#include "Stack.hpp"

namespace Deun {
/**
* 스택 클래스 (배열 기반)
*/
template <typename T>
class ArrayStack : public Stack<T> {
private:
int size; // 스택의 최대 크기 (메모리 할당량)
T* array; // 데이터 저장을 위한 배열
// top은 Stack 인터페이스의 count 변수를 사용함.
// count라고 명명한 이유는 LinkedListStack에서도 사용하기 위해서임.

public:
/**
* 스택 생성자
* @param size 스택의 최대 크기
* @throw StackError (크기 오류 또는 메모리 할당 실패)
*/
ArrayStack(int size = 1000);

/**
* 스택 소멸자
*/
~ArrayStack();

/**
* 스택의 최대 크기를 반환합니다.
*/
int getSize();

/**
* 현재 스택에 들어있는 원소의 개수를 반환합니다.
*/
int getCount();

/**
* 스택이 비어있는지의 여부를 반환합니다.
*/
bool isEmpty();

/**
* 스택이 가득 차있는지의 여부를 반환합니다.
*/
bool isFull();

/**
* 스택에 원소를 삽입하고 성공 여부를 반환합니다.
* @param element 원소
*/
bool push(const T& element);

/**
* 스택의 마지막 원소를 삭제하고 성공 여부를 반환합니다.
*/
bool pop();

/**
* 스택의 마지막 원소를 반환합니다.
* @throw StackError (스택이 빈 경우)
*/
T& peek();

/**
* 스택을 출력합니다.
*/
void print();

/**
* 스택을 초기화합니다. (모든 원소가 삭제됩니다.)
*/
void clear();
};
}

#endif
103 changes: 103 additions & 0 deletions Stack/ArrayStack.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#ifndef __DEUN_ARRAY_STACK_HPP__
#define __DEUN_ARRAY_STACK_HPP__

#include "ArrayStack.h"

namespace Deun {
template <typename T>
ArrayStack<T>::ArrayStack(int size) : Stack(0), size(size) {
if (size <= 0) {
throw StackError::SIZE_IS_TOO_SMALL;
}
array = static_cast<T*>(operator new(sizeof(T) * size, std::nothrow));
// new는 메모리 할당 후 생성자를 호출하지만, operator new는 메모리만 할당한다.
// (C의 malloc()와 동일하게 생성자를 호출하지 않는다.)
// new를 사용하는 경우 기본 생성자가 없는 클래스는 컴파일 오류가 발생한다.
if (!array) {
throw StackError::MEMORY_ALLOCATION_FAILED;
}
}

template <typename T>
ArrayStack<T>::~ArrayStack() {
clear(); // 명시적 소멸자 호출
operator delete(array); // 모든 메모리를 반환한다.
}

template <typename T>
int ArrayStack<T>::getSize() {
return size;
}

template <typename T>
int ArrayStack<T>::getCount() {
return count;
}

template <typename T>
bool ArrayStack<T>::isEmpty() {
return (count == 0); // count는 top 용도로 쓰인다.
}

template <typename T>
bool ArrayStack<T>::isFull() {
return (count == size);
}

template <typename T>
bool ArrayStack<T>::push(const T& element) {
if (isFull()) {
return false;
}
new(&array[count++]) T(element); // placement new
// 스택 생성자에서 미리 할당해 놓은 메모리에 T의 복사 생성자로 생성한다.
// placement new는 new와 다르게 메모리를 할당하지 않고 기존 메모리에 생성한다.
// 깊은 복사가 필요한 클래스를 사용할 경우 직접 복사 생성자를 구현해야 한다.
return true;
}

template <typename T>
bool ArrayStack<T>::pop() {
if (isEmpty()) {
return false;
}
array[--count].~T(); // 명시적 소멸자 호출
return true;
}

template <typename T>
T& ArrayStack<T>::peek() {
if (isEmpty()) {
throw StackError::ELEMENT_NOT_FOUND;
}
return array[count - 1];
}

template <typename T>
void ArrayStack<T>::print() {
using namespace std;
cout << "ArrayStack(size=" << size << ", count=" << count << ")" << endl;
if (!count) {
cout << "(empty)" << endl;
return;
}
cout << "(top) ";
for (int i = count - 1; i >= 0; i--) {
cout << array[i];
if (i) {
cout << " / ";
}
}
cout << endl;
}

template <typename T>
void ArrayStack<T>::clear() {
for (int i = count - 1; i >= 0; i--) { // top 부터 삭제
array[i].~T(); // 명시적 소멸자 호출
}
count = 0;
}
}

#endif
Loading

0 comments on commit afc5b4c

Please sign in to comment.