C++ 实现支持字符和数字的广义表
以下是一个实现可以同时存储字符和小数的广义表的 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 类的实现使用了递归方法来创建和销毁广义表节点,以及打印广义表。创建节点时,会根据节点的第一个字符来判断节点的类型,并相应地创建节点对象。如果是列表节点,则会递归地创建其子节点;如果是原子节点,则会从字符串中解析出其对应的值。打印广义表时,会先判断节点的类型,并相应地打印节点的值或子节点列表。
原文地址: https://www.cveoy.top/t/topic/oUIy 著作权归作者所有。请勿转载和采集!