以下是一个实现可以同时存储字符和小数的广义表的 C++ 代码:

#include <iostream>
#include <vector>
#include <string>

using namespace std;

class GList {
private:
    struct Node {
        bool isAtom;
        double dvalue;
        char cvalue;
        vector<GList> list;
        Node(bool isAtom = false, double dvalue = 0, char cvalue = '\0', vector<GList> list = vector<GList>())
            : isAtom(isAtom), dvalue(dvalue), cvalue(cvalue), list(list) {}
    };

    Node *root;

public:
    GList() {
        root = nullptr;
    }

    GList(const string& str) {
        root = createNode(str, 0, str.length() - 1);
    }

    ~GList() {
        destroyNode(root);
    }

    bool isEmpty() const {
        return root == nullptr;
    }

    bool isAtom() const {
        return root != nullptr && root->isAtom;
    }

    bool isList() const {
        return root != nullptr && !root->isAtom;
    }

    double getDoubleValue() const {
        if (root == nullptr || !root->isAtom) {
            throw invalid_argument("Invalid operation: not an atom");
        }
        return root->dvalue;
    }

    char getCharValue() const {
        if (root == nullptr || !root->isAtom) {
            throw invalid_argument("Invalid operation: not an atom");
        }
        return root->cvalue;
    }

    vector<GList> getList() const {
        if (root == nullptr || root->isAtom) {
            throw invalid_argument("Invalid operation: not a list");
        }
        return root->list;
    }

    void print() const {
        printNode(root);
    }

private:
    Node* createNode(const string& str, int start, int end) {
        if (start > end) {
            return nullptr;
        }

        if (str[start] == '(') {
            int pos = findMatchingParenthesis(str, start);
            if (pos == end) {
                // empty list
                return new Node(false, 0, '\0', vector<GList>());
            }

            vector<GList> list;
            int i = start + 1;
            while (i < pos) {
                int j = i;
                while (j < pos && str[j] != ',' && str[j] != ')') {
                    j++;
                }
                list.push_back(GList(str.substr(i, j - i)));
                i = j + 1;
            }

            return new Node(false, 0, '\0', list);

        } else if (str[start] == '+' || str[start] == '-' || isdigit(str[start])) {
            // numeric atom
            int i = start;
            while (i <= end && (isdigit(str[i]) || str[i] == '.')) {
                i++;
            }
            double value = stod(str.substr(start, i - start));
            return new Node(true, value, '\0', vector<GList>());

        } else {
            // character atom
            return new Node(true, 0, str[start], vector<GList>());
        }
    }

    int findMatchingParenthesis(const string& str, int start) {
        int count = 1, i = start + 1;
        while (i < str.length() && count > 0) {
            if (str[i] == '(') {
                count++;
            } else if (str[i] == ')') {
                count--;
            }
            i++;
        }
        if (count != 0) {
            throw invalid_argument("Invalid input: mismatched parentheses");
        }
        return i - 1;
    }

    void destroyNode(Node* node) {
        if (node != nullptr) {
            if (!node->isAtom) {
                for (auto& x : node->list) {
                    destroyNode(x.root);
                }
            }
            delete node;
        }
    }

    void printNode(Node* node) const {
        if (node != nullptr) {
            if (node->isAtom) {
                if (isdigit(node->cvalue) || node->cvalue == '+' || node->cvalue == '-') {
                    cout << node->dvalue;
                } else {
                    cout << node->cvalue;
                }
            } else {
                cout << '(';
                for (size_t i = 0; i < node->list.size(); i++) {
                    node->list[i].print();
                    if (i != node->list.size() - 1) {
                        cout << ", ";
                    }
                }
                cout << ')';
            }
        }
    }
};

这个实现使用了类 GList 来表示广义表,其中包含一个内部类 Node,用来表示广义表节点。节点有 4 个属性:

  • isAtom 表示节点是否为原子。
  • dvalue 表示节点的数值,如果节点不是数值类型的原子,则该属性无意义。
  • cvalue 表示节点的字符值,如果节点不是字符类型的原子,则该属性无意义。
  • list 表示节点的子节点列表,如果节点是原子,则该属性为空。

GList 类包含以下公共方法:

  • GList():无参数构造函数,创建一个空的广义表。
  • GList(const string& str):构造函数,从给定的字符串中创建广义表。
  • ~GList():析构函数,销毁广义表。
  • bool isEmpty() const:判断广义表是否为空。
  • bool isAtom() const:判断广义表是否为原子。
  • bool isList() const:判断广义表是否为列表。
  • double getDoubleValue() const:获取广义表的数值,如果广义表不是数值类型的原子,则抛出 invalid_argument 异常。
  • char getCharValue() const:获取广义表的字符值,如果广义表不是字符类型的原子,则抛出 invalid_argument 异常。
  • vector<GList> getList() const:获取广义表的子节点列表,如果广义表是原子,则抛出 invalid_argument 异常。
  • void print() const:打印广义表。

GList 类的实现使用了递归方法来创建和销毁广义表节点,以及打印广义表。创建节点时,会根据节点的第一个字符来判断节点的类型,并相应地创建节点对象。如果是列表节点,则会递归地创建其子节点;如果是原子节点,则会从字符串中解析出其对应的值。打印广义表时,会先判断节点的类型,并相应地打印节点的值或子节点列表。

C++ 实现支持字符和数字的广义表

原文地址: https://www.cveoy.top/t/topic/oUIy 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录