Eat Study Love

먹고 공부하고 사랑하라

Coding_Practice

C++ Container, Custom Map Practice

eatplaylove 2024. 7. 29. 12:58

CFDS1_HW2-2.pdf
0.18MB
hw2_1_release-2.zip
0.00MB
hw2_2_release.zip
0.00MB

 

답안?을 좀 보긴 했지만 그래도 차분히 코드를 짜봤다.

 

해당과제는 C++의 기본적인 OOP 특성은 물론, Container의 특징까지 잘 파악해볼 수 있는 과제이다.

 

일단 첫 번째 hw2-1의 경우 나의 코드는 아래와 같소

 

1. Container 과제

//Container.hpp
#include <iostream>
#include <string.h>

using namespace std;

// Implement definition of all classes and the member functions in this file.

class Container{
public:
    float size;
    float capa;
    string* code;
    string str;
    Container(float s):size(s),code(nullptr){}

    float get_size(){return size;}
    void virtual set_capacity() =0;
    float get_capacity(){return capa;}
    void set_container_code(){
        if(capa<100) str+="1";
        else if(100<=capa && capa<200) str+="2";
        else str+="3";
        code = new string(str);
    }
    string* get_container_code(){
        return code;
    }
    virtual ~Container(){delete code;}
};

class Box: public Container{
public:
    Box(float s):Container(s){}
    void set_capacity() override {capa = size*1;}
};

class PaperBox: public Box{
public:
    PaperBox(float s):Box(s){str="PaB";}
    void set_capacity() override {capa = size*1.3;}
};

class PlasticBox: public Box{
public:
   PlasticBox(float s):Box(s){str="PIB";} 
    void set_capacity() override {capa = size*1.1;}
};

class Bag: public Container{
public:
    Bag(float s):Container(s){str="B";}
    void set_capacity() override {capa = size*3;}
};

class Carrier: public Container{
public:
    Box* arr[2] = {nullptr,nullptr};
    Carrier(float s):Container(s){
        str="C";
        // arr[0]=nullptr;
        // arr[1]=nullptr;
    }
    void set_capacity() override {capa = size*5;}
    void add_aux(Box* aux){
        if(!arr[0]){
            arr[0] = aux;
            capa += (aux->capa)*1.1;
        }else if (!arr[1])
        {   arr[1] = aux;
            capa += (aux->capa)*1.1;}
        else return;
    }
    Box* get_aux(int n){
        if(n!=1 && n!=2)return nullptr;
        return arr[n-1];}

    ~Carrier(){
        delete arr[0];
        delete arr[1];

    }

};

//test용 main.cpp
#include "container.hpp"
#include <type_traits>

void Episode1(){
    cout << "Episode 1:" << endl;
    float alloc_weight = 0;

    Carrier* carrier1 = new Carrier(100);
    carrier1->set_capacity();

    float carrier_size = carrier1->get_size();
    
    Bag* bag1 = new Bag(50);
    bag1->set_capacity();

    PaperBox* pap_box1 = new PaperBox(10);
    pap_box1->set_capacity();
    PaperBox* pap_box2 = new PaperBox(10);
    pap_box2->set_capacity();

    PlasticBox* plas_box1 = new PlasticBox(10);
    plas_box1->set_capacity();
    PlasticBox* plas_box2 = new PlasticBox(10);
    plas_box2->set_capacity();

    // PlasticBox* plas_box3 = new PlasticBox(10);
    // plas_box3->set_capacity();


    carrier1->add_aux(plas_box1);
    carrier1->add_aux(plas_box2);
    // carrier1->add_aux(plas_box3);

    Box* aux_box = carrier1->get_aux(1);
    
    alloc_weight+=carrier1->get_capacity();
    alloc_weight+=bag1->get_capacity();
    alloc_weight+=pap_box1->get_capacity();
    alloc_weight+=pap_box2->get_capacity();

    carrier1->set_container_code();
    bag1->set_container_code();
    pap_box1->set_container_code();
    pap_box1->set_container_code();

    string* code = carrier1->get_container_code();

    cout << "Total capacity:" << alloc_weight << endl;
    cout << "aux_box:" << aux_box->get_capacity() << endl;

    delete carrier1;
}

void Episode2(){
    cout << "Episode 2:" << endl;
    float alloc_weight = 0;

    Carrier* carrier1 = new Carrier(150);
    carrier1->set_capacity();

    float carrier_size = carrier1->get_size();

    Bag* bag1 = new Bag(30);
    bag1->set_capacity();

    PaperBox* pap_box1 = new PaperBox(20);
    pap_box1->set_capacity();
    PaperBox* pap_box2 = new PaperBox(20);
    pap_box2->set_capacity();
    PlasticBox* plas_box1 = new PlasticBox(10);
    plas_box1->set_capacity();

    carrier1->add_aux(plas_box1);
    
    alloc_weight+=carrier1->get_capacity();
    alloc_weight+=bag1->get_capacity();
    alloc_weight+=pap_box1->get_capacity();
    alloc_weight+=pap_box2->get_capacity();

    carrier1->set_container_code();
    bag1->set_container_code();
    pap_box1->set_container_code();
    pap_box1->set_container_code();

    string* code = carrier1->get_container_code();

    cout << "Total capacity:" << alloc_weight << endl;
    delete carrier1;
}

int main(void){
    Episode1();
    cout << endl;
    Episode2();
}

 

과제에서 살짝 주의해야할 점은,

Class 상속관계에서 Construct call은 base -> derived 순으로 call 되지만

Destruct call은 derived -> base 순으로 call 된다.

 

그래서 통상, Base에 있는 destruct function의 경우는 virtual ~Base() {} 요렇게 virtual로 만들어 주는 것이 메모리 누수를 막을 수 있는 방법이다.

 

 

 

2. Custom Map 과제

 

일단 HW2 C번까지 완료..

#include <iostream>
#include <string>
#include <functional>
#include <stack>
using namespace std;

template <typename K, typename V> //Fill in the empty templates and implement the definition of the class and each member functions
class TreeNode {
public://getter / setter?
    TreeNode(K k, V v):key(k),value(v),left(nullptr),right(nullptr){}
    // ~TreeNode(){
    //     delete left;
    //     delete right;
    // } //Destruct를 해야하나 여부
    // getter , setter가 뭔지 몰랐다.
    K& getK(){return key;}
    void setK(K a){key = a;}
    V& getV(){return value;}
    void setV(V b){value = b;}

    TreeNode*& getL(){return left;}
    TreeNode*& getR(){return right;}
    void setR(TreeNode* r){right = r;}
    void setL(TreeNode* l){left = l;}

private:
    K key;
    V value;
    TreeNode* left;
    TreeNode* right;

};

template <typename K, typename V, typename Compare = std::less<K>> //Fill in the empty templates and implement the definition of the class and each member functions
class CustomMap {
public:
    TreeNode<K,V>* root;
    Compare comp;
    CustomMap():root(nullptr),comp(Compare()){}
    ~CustomMap(){
        stack<TreeNode<K,V>*> s;
        s.push(root);
        while(!s.empty()){
            TreeNode<K,V>* curr = s.top();
            s.pop();
            if(curr->getL()){
                s.push(curr->getL());
            }
            if(curr->getR()){
                s.push(curr->getR());
            }
            delete curr;
            }
        }

    TreeNode<K,V>* get_root(){return root;}
    Compare get_compare(){return comp;}
    void insert(K key, V value){
        TreeNode<K,V>* newNode = new TreeNode<K,V>(key,value);
        if(!root){
            root = newNode;
            return;
        }else{
            TreeNode<K,V>* temp = root;

            while(temp){
                if(comp(temp->getK(),key)){
                    if(!temp->getR()){
                        temp->setR(newNode);
                        return;
                        }
                    temp = temp->getR();
                }else if(comp(key,temp->getK())){
                    if(!temp->getL()){
                        temp->setL(newNode);
                        return;}
                    temp = temp->getL();}
                else{
                    delete newNode;
                    return;
                    }
                }
            }
        }
    void print_map(){//ascending order of keys->DFS inorder?
        print_map_help(root);
    }
    void print_map_help(TreeNode<K,V>* root){
        if(!root) return;
        print_map_help(root->getL());
        cout << root->getK()<<":"<<root->getV()<<endl;
        print_map_help(root->getR());
    };

    void deleteKey(K key){
            TreeNode<K,V>* temp = root;
            TreeNode<K,V>* parent = nullptr;
            TreeNode<K,V>* curr = nullptr;

            while(temp){
                if(comp(temp->getK(),key)){
                    parent = temp;
                    temp = temp->getR();
                }else if(comp(key,temp->getK())){
                    parent = temp;
                    temp = temp->getL();}
                else{//find it
                    // with 0 or 1 child
                    if(!temp->getL()){
                        if(parent){
                        if(comp(parent->getK(),temp->getK())){
                            parent->setR(temp->getR());
                        }else parent->setL(temp->getR());
                        temp->setR(nullptr);}
                    else root = temp->getR();

                    delete temp;
                    return;
                    }

                    if(!temp->getR()){
                        if(parent){
                        if(comp(parent->getK(),temp->getK())){
                            parent->setR(temp->getL());
                        }else parent->setL(temp->getL());
                        temp->setL(nullptr);}
                        else root = temp->getL();

                        delete temp;
                        return;
                    }
                    // with 2 children
                    curr = temp->getL();
                    TreeNode<K, V>* successorParent = temp;
                    while(curr->getR()){
                        successorParent = curr;
                        curr = curr->getR();
                    }
                    temp->setV(curr->getV());
                    temp->setK(curr->getK());
                    if(successorParent==temp){
                        successorParent->setL(nullptr);
                    }else{
                        successorParent->setR(curr->getL());
                    }
                    delete curr;
                    return;
                }
            
            }
    }
    V get_value(K key){
        if(!root) return V();
        TreeNode<K, V>* temp = root;
        while(temp){
            if(comp(temp->getK(),key)){
                temp = temp->getR();
            }
            else if(comp(key,temp->getK())){
                temp = temp->getL();
            }
            //find it
            else return temp->getV();
        }
        return V();
    }
    V& operator[](const K& key){
        TreeNode<K, V>* temp = root;
        while(temp){
            if(comp(temp->getK(),key)){
                temp = temp->getR();
            }
            else if(comp(key,temp->getK())){
                temp = temp->getL();
            }
            //find it
            else return temp->getV();
        }
        //찾으려는 key가 DS에 존재하지 않음.
        insert(key,V());
        //return을 해야 삽입된 노드의 값을 반환하는 것
        return operator[](key);
    }

    //어려운 것 []operator


};
#include "custommap.hpp"

int main(void) {
    CustomMap<int, string> map;
    map.deleteKey(5);
    map.insert(10, "ten");
    map.insert(6, "six");
    map.insert(13, "Five");
    map.insert(8, "Five");
      #main함수 테스트코드
   map.insert(5, "Five!!");
    map.insert(7, "Five");
    map.deleteKey(10);
    // map.print_map();
    // cout<<map.get_value(5)<<endl;
    cout<<map[6]<<endl;
    map[6] = "abcd";
    cout<<map[6]<<endl;
    cout<<map[123]<<endl;
    map[123] = "onetwothree";
    cout<<map[123]<<endl;
    map.print_map();



    // cout << endl;

    // map.insert(3, "Three");
    // map.insert(8, "Eight");
    // map.deleteKey(8);
    // map.print_map();
    // cout << endl;
    
    // map.insert(10, "Ten");
    // map.insert(11, "Eleven");
    // map.insert(3, "Three");
    // map.insert(5, "Five");
    // map.deleteKey(3);
    // map.print_map();
}