数据结构:广义表(C++模板)

数据结构:广义表

关于广义的表定义见下文的链接,暂不赘述。

总结:二维及以上的数组可以看作是特殊的广义表。


这几篇文章都特别不错,先把链接贴在这里,之后再整理:

其他几个链接:


暂时没有见到用继承和多态实现广义表的代码,自己写了一个:

glist.hpp

#ifndef GLIST_HPP
#define GLIST_HPP

template<typename T>
class GListElement {
public:
    enum GListElementType {ATOM, LIST};
    GListElement(GListElementType _type) : 
        element_type(_type) {}
    virtual ~GListElement() = default;
    GListElementType type() { return element_type; }
    bool equal_type(const GListElement<T> & a) { return this->type() == a.type(); }
    virtual T& data() = 0;
protected:
    GListElementType element_type;
};

template<typename T>
class GAtom : public GListElement<T>
{
private:
    T element;
public:
    GAtom() : 
        GListElement<T>(GListElement<T>::ATOM) {}
    // GAtom(T && e) : 
    //     GListElement<T>(GListElement<T>::ATOM), T(e) {}
    GAtom(const T & e) : 
        GListElement<T>(GListElement<T>::ATOM), element(e) {}
    ~GAtom() {};
    GAtom & operator=(const T & val) { element = val; return *this; } 
    T& data() { return element; };
};

template<typename T>
class GList : public GListElement<T> 
{
    struct node {
        GListElement<T>* element_ptr;
        node* next;
        node* prior;
        node() : 
            element_ptr(nullptr), next(this), prior(this) {};
        node(GListElement<T>* _ptr, node * _n = nullptr, node * _p = nullptr) : 
            element_ptr(_ptr), next(_n), prior(_p) {};
        ~node() { delete element_ptr; }
    };
    node * head;
public:
    GList() : GListElement<T>(GListElement<T>::LIST) { head = new node(); }
    GList(const GList & glist) : 
        GListElement<T>(GListElement<T>::LIST) {
        head = new node();
        GListElement<T>* item_ptr = nullptr;
        for (auto item : glist) {
            switch (item->type())
            {
            case GListElement<T>::ATOM:
                item_ptr = new GAtom<T>(*dynamic_cast<GAtom<T>*>(item)); break;
            case GListElement<T>::LIST:
                item_ptr = new GList<T>(*dynamic_cast<GList<T>*>(item)); break;
            }
            auto last = head->prior;
            auto new_node = new node(item_ptr, head, last);
            last->next = new_node;
            head->prior = new_node;
        }
    } 
    ~GList() {
        auto node_ptr = head->next;
        while (node_ptr != head) {
            auto tmp = node_ptr; node_ptr = node_ptr->next; delete tmp;
        }
        delete head;
    }
    T& data() { return head->next->element_ptr->data(); }

    friend class iterator;
    
    class iterator {
        node * the_node;
    public:
        iterator(const GList & glist) {
            the_node = (glist.head)->next;
        }
        iterator(node * _node) : the_node(_node) {}
        iterator & operator++() { // pre increment
            the_node = the_node->next; 
            return *this;
        }
        iterator operator++(int) { // post increment
            auto tmp = *this;
            the_node = the_node->next;
            return tmp;
        }
        bool operator==(const iterator & rhs) { 
            return the_node == rhs.the_node || 
                (the_node->element_ptr == nullptr && rhs.the_node->element_ptr == nullptr); 
        } 
        bool operator!=(const iterator & rhs) { return the_node != rhs.the_node; } 
        GListElement<T>* operator*() { return (the_node->element_ptr); }
    };
    iterator end() const { return iterator(head); };
    iterator begin() const { return iterator(*this); };
    void push_back(const T & item) {
        GListElement<T>* item_ptr = nullptr;
        item_ptr = new GAtom<T>(item);
        auto last = head->prior;
        auto new_node = new node(item_ptr, head, last);
        last->next = new_node;
        head->prior = new_node;
    }
    void push_back(const GList<T> & item) {
        GListElement<T>* item_ptr = nullptr;
        item_ptr = new GList<T>(item);
        auto last = head->prior;
        auto new_node = new node(item_ptr, head, last);
        last->next = new_node;
        head->prior = new_node;
    }
    int depth() {
        int depth = 0;
        for (auto i : *this) {
            if (i->type() == GListElement<T>::LIST) {
                auto sublist_ptr = dynamic_cast<GList<T>*>(i);
                auto t = sublist_ptr->depth();
                if (t > depth) depth = t;
            }
        }
        return depth + 1;
    }
};

#endif

对移动语义还不完全了解,暂时无法优化。

迭代器解引用之后得到的是基类GListElement<T>的指针,如此,迭代器的operator->就不是很有意义了,便不实现了。

关于如何使用看下边的代码:

glist_test.cpp

#include "glist.hpp"
#include <iostream>

template<typename T>
void print_glist(const GList<T> & list, int depth = 0) {
    std::cout << "(";
    for (auto i : list) {
        if (i->type() == GListElement<T>::LIST) {
            auto sublist_ptr = dynamic_cast<GList<T>*>(i);
            print_glist<T>(*sublist_ptr, depth+1);
        } 
        else { std::cout << i->data(); }
        std::cout << ",";
    }
    std::cout << "\b)";
}

int main() {
    GList<char> list;
    list.push_back('a');
    list.push_back('b');
    list.push_back(list);
    list.push_back('c');
    for (auto i : list) {
        std::cout << i->data() << ' ';
    }
    print_glist(list);
    std::cout << " depth: " << list.depth() << std::endl;
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值