数据结构与算法之美:广义表

Hello大家好!很高兴我们又见面啦!给生活添点passion,开始今天的编程之路!

我的博客: <但凡.

我的专栏: 《编程之路》《数据结构与算法之美》《题海拾贝》《C++修炼之路》《Linux修炼:终端之内 洞悉真理》

欢迎点赞,关注!

1、广义表的定义

**广义表(Generalized List)是一种非线性的数据结构,可以看作线性表的推广。**与线性表不同,广义表中的元素可以是原子(不可再分的单个数据项),也可以是另一个广义表,意思就是广义表可以嵌套广义表。这种递归定义使得广义表具有高度的灵活性。

广义表的长度定义为最外层包含的元素个数,深度定义为嵌套的层数。例如,广义表 (a, (b, c), d) 的长度为 3(元素分别为 a(b, c)d),深度为 2(嵌套一层子表 (b, c))。

2、广义表的表示方法

广义表通常用括号和逗号表示,形式为:
LS = (a₁, a₂, ..., aₙ)

其中 LS 是广义表名,aᵢ 可以是原子或子表。空表用 () 表示。

广义表的存储结构通常采用链式实现,每个结点包含两个域:

**(1)tag:**标识结点类型(0 为原子,1 为子表)。

(2)联合域:tag=0,存储原子值 data;若 tag=1,存储指向子表的指针 sublist

**(3)next:**指向下一个结点的。

2、广义表的操作

创建广义表

通过递归解析输入字符串实现。例如,输入 (a,(b,c),d)

  1. 遇到 ( 时创建子表,递归处理后续元素。
  2. 遇到原子时直接存储。
  3. 遇到 ) 时结束当前子表。

求广义表长度

遍历顶层元素计数,直到 nextNULL。例如 (a,(b,c),d) 的长度为 3。

求广义表深度

递归计算子表的最大深度加 1。空表深度为 1,原子深度为 0。

公式:
depth(LS) = 1 + max{depth(aᵢ) | aᵢ ∈ LS}

遍历广义表

递归访问每个元素:

  1. 若为原子,直接输出。
  2. 若为子表,递归遍历子表内容。

3、广义表模拟实现

3.1、节点

cpp 复制代码
struct GLNode {
    NodeType tag;
    union {
        char atom;
        GLNode* sublist;
    };
    GLNode* next;

    GLNode(NodeType t, char a = '\0', GLNode* sl = nullptr, GLNode* n = nullptr)
        : tag(t), next(n) {
        if (t == ATOM) atom = a;
        else sublist = sl;
    }
};

3.2、各种操作

cpp 复制代码
class GeneralizedList {
public:
    GeneralizedList() : head(nullptr) {}
    ~GeneralizedList() { destroy(head); }

    void create(const string& s) {
        int pos = 0;
        head = createHelper(s, pos);
    }

    int depth() const { return depthHelper(head); }
    void print() const { printHelper(head); cout << endl; }

private:
    GLNode* head;

    GLNode* createHelper(const string& s, int& pos) {
        if (pos >= s.size() || s[pos] == ')') return nullptr;
        
        GLNode* node = nullptr;
        if (s[pos] == '(') {
            pos++;
            node = new GLNode(SUBLIST);
            node->sublist = createHelper(s, pos);
            pos++; // skip ')'
        }
        else {
            if (s[pos] == ',') pos++;
            if (s[pos] == '(') {
                pos++;
                node = new GLNode(SUBLIST);
                node->sublist = createHelper(s, pos);
                pos++; // skip ')'
            }
            else
            {
                node = new GLNode(ATOM, s[pos]);
                pos++;
            }
        }
        node->next = createHelper(s, pos);
        return node;
    }

    void destroy(GLNode* node) {
        if (!node) return;
        if (node->tag == SUBLIST) destroy(node->sublist);
        destroy(node->next);
        delete node;
    }

    int depthHelper(GLNode* node) const {
        if (!node) return 0;
        int max_depth = 0;
        while (node) {
            if (node->tag == SUBLIST) {
                int d = depthHelper(node->sublist) + 1;
                if (d > max_depth) max_depth = d;
            }
            node = node->next;
        }
        return max_depth;
    }

    void printHelper(GLNode* node) const {
        if (!node) return;
        if (node->tag == ATOM) {
            cout << node->atom;
        }
        else {
            cout << "(";
            printHelper(node->sublist);
            cout << ")";
        }
        if (node->next) {
            cout << ",";
            printHelper(node->next);
        }
    }
};

3.3、测试代码

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include"head.h"
int main() {
    GeneralizedList gl;

    // 测试用例1: (a,(b,c),d)
    gl.create("(a,(b,c),d)");
    cout << "List: ";
    gl.print();
    cout << "Depth: " << gl.depth() << endl; // 应输出2

    // 测试用例2: ((a,(b)),c)
    GeneralizedList gl2;
    gl2.create("((a,(b)),c)");
    cout << "List: ";
    gl2.print();
    cout << "Depth: " << gl2.depth() << endl; // 应输出3

    // 测试用例3: a
    GeneralizedList gl3;
    gl3.create("a");
    cout << "List: ";
    gl3.print();
    cout << "Depth: " << gl3.depth() << endl; // 应输出1

    return 0;
}

4、广义表的应用场景

  1. 多层次数据表示
    如文件目录结构、HTML/XML 文档的嵌套标签。
  2. 多项式存储
    广义表可以表示多元多项式,例如 (x, (y, 2), 3) 表示 x + y² + 3
  3. 递归算法实现
    广义表的递归特性适合解决分治问题,如树形结构的遍历。

5、广义表与线性表的区别

特性 线性表 广义表
元素类型 只能是原子 可以是原子或子表
结构 严格顺序 递归嵌套
操作复杂度 插入/删除 O(n) 递归操作复杂度较高

广义表的灵活性使其在需要层次化或递归数据的场景中优于线性表,但也带来了更高的实现复杂度。

好了,今天的内容就分享到这,我们下期再见!

相关推荐
呆呆的小鳄鱼19 分钟前
leetcode:322. 零钱兑换[完全背包]
算法·leetcode·职场和发展
Gyoku Mint28 分钟前
深度学习×第7卷:参数初始化与网络搭建——她第一次挑好初始的重量
人工智能·pytorch·rnn·深度学习·神经网络·算法·机器学习
mit6.82439 分钟前
[Vroom] 位置与矩阵 | 路由集成 | 抽象,解耦与通信
c++·人工智能·算法
ChuHsiang40 分钟前
【C++】模板(二)
c++
用户403159863966344 分钟前
在工作中学算法——专线配置
java·算法
用户40315986396631 小时前
在工作中学算法——基于日志的系统故障预测
java·算法
এ᭄画画的北北1 小时前
力扣-240.搜索二维矩阵 II
算法·leetcode·矩阵
浩瀚星辰20241 小时前
C++树状数组详解
java·数据结构·算法
JJ1M81 小时前
前缀和+贪心总结,基于每日一题力扣3439、3440
python·算法·leetcode