当前位置: 首页 > article >正文

数据结构:广义表( Generalized List)及其实现

什么是广义表?

广义表(Generalized List)是一种扩展的线性表,它可以存储原子(单个数据元素)或子表(另一个广义表)。广义表的特点是:它可以递归定义,也就是说,一个广义表的元素可以是另一个广义表。

举个例子:

  • A = (1, 2, 3):这是一个普通的线性表,包含 3 个原子。

  • B = (1, (2, 3), 4):这是一个广义表,包含 2 个原子和 1 个子表 (2, 3)

  • C = (1, (2, (3, 4)), 5):这是一个更复杂的广义表,包含嵌套的子表。

广义表的灵活性使其非常适合表示复杂的数据结构,比如树、图等。


广义表的存储方式

1. 顺序存储

顺序存储是用数组来存储广义表。由于广义表的元素可以是原子或子表,因此需要额外的标记来区分原子和子表。

优点

  • 访问速度快,可以通过下标直接访问元素。

  • 实现简单。

缺点

  • 插入和删除操作需要移动大量数据,效率低。

  • 数组大小固定,不适合动态变化的广义表。


2. 链式存储

链式存储是用链表来存储广义表。每个节点可以是原子节点或子表节点,通过指针连接。

优点

  • 插入和删除操作效率高,不需要移动大量数据。

  • 适合动态变化的广义表。

缺点

  • 访问速度慢,需要从头开始遍历。

  • 内存开销大,每个节点需要额外存储指针。


广义表的基本概念

1. 长度

广义表的长度是指广义表中元素的个数。例如:

  • A = (1, 2, 3) 的长度是 3。

  • B = (1, (2, 3), 4) 的长度是 3(原子 1、子表 (2, 3) 和原子 4)。

2. 深度

广义表的深度是指广义表中嵌套的层数。例如:

  • A = (1, 2, 3) 的深度是 1。

  • B = (1, (2, 3), 4) 的深度是 2。

  • C = (1, (2, (3, 4)), 5) 的深度是 3。


广义表的基本操作

广义表的基本操作包括:增、删、查、改。下面我们用大白话解释这些操作。

  1. 增加元素

    • 在广义表的指定位置插入一个原子或子表。

  2. 删除元素

    • 删除广义表中指定位置的原子或子表。

  3. 查找元素

    • 查找广义表中是否存在指定的原子或子表。

  4. 修改元素

    • 修改广义表中指定位置的原子或子表。


C 语言实现广义表

下面是一个简单的广义表实现代码,包含初始化、插入、删除、查找和打印功能。

#include <stdio.h>
#include <stdlib.h>

// 定义广义表节点类型
typedef enum { ATOM, LIST } NodeType;

// 定义广义表节点结构体
typedef struct GLNode {
    NodeType tag;  // 节点类型:ATOM(原子)或 LIST(子表)
    union {
        char data;  // 原子数据
        struct GLNode *sublist;  // 子表指针
    };
    struct GLNode *next;  // 指向下一个节点的指针
} GLNode;

// 创建原子节点
GLNode* CreateAtom(char data) {
    GLNode *node = (GLNode*)malloc(sizeof(GLNode));
    node->tag = ATOM;
    node->data = data;
    node->next = NULL;
    return node;
}

// 创建子表节点
GLNode* CreateList(GLNode *sublist) {
    GLNode *node = (GLNode*)malloc(sizeof(GLNode));
    node->tag = LIST;
    node->sublist = sublist;
    node->next = NULL;
    return node;
}

// 插入元素
void InsertElement(GLNode *list, int pos, GLNode *element) {
    GLNode *current = list;
    for (int i = 0; i < pos && current != NULL; i++) {
        current = current->next;
    }
    if (current != NULL) {
        element->next = current->next;
        current->next = element;
    }
}

// 删除元素
void DeleteElement(GLNode *list, int pos) {
    GLNode *current = list;
    for (int i = 0; i < pos && current != NULL; i++) {
        current = current->next;
    }
    if (current != NULL && current->next != NULL) {
        GLNode *temp = current->next;
        current->next = temp->next;
        free(temp);
    }
}

// 查找元素
GLNode* FindElement(GLNode *list, char data) {
    GLNode *current = list;
    while (current != NULL) {
        if (current->tag == ATOM && current->data == data) {
            return current;
        }
        current = current->next;
    }
    return NULL;
}

// 打印广义表
void PrintList(GLNode *list) {
    GLNode *current = list;
    printf("广义表内容:");
    while (current != NULL) {
        if (current->tag == ATOM) {
            printf("%c ", current->data);
        } else if (current->tag == LIST) {
            printf("(");
            PrintList(current->sublist);
            printf(") ");
        }
        current = current->next;
    }
}

int main() {
    // 创建广义表 B = (1, (2, 3), 4)
    GLNode *sublist = CreateList(CreateAtom('2'));
    sublist->next = CreateAtom('3');
    GLNode *list = CreateAtom('1');
    list->next = CreateList(sublist);
    list->next->next = CreateAtom('4');

    PrintList(list);  // 打印广义表
    printf("\n");

    // 插入元素
    InsertElement(list, 1, CreateAtom('5'));
    PrintList(list);  // 打印广义表
    printf("\n");

    // 删除元素
    DeleteElement(list, 2);
    PrintList(list);  // 打印广义表
    printf("\n");

    // 查找元素
    GLNode *target = FindElement(list, '2');
    if (target != NULL) {
        printf("找到元素:%c\n", target->data);
    } else {
        printf("未找到元素\n");
    }

    return 0;
}

广义表的复制

广义表的复制需要递归地复制每个节点。如果是原子节点,直接复制数据;如果是子表节点,递归复制子表。


广义表的使用场景

  1. 表示树结构:广义表可以表示树结构,比如文件系统的目录结构。

  2. 表示图结构:广义表可以表示图结构,比如社交网络的关系图。

  3. 数学表达式:广义表可以表示数学表达式,比如 (a + b) * (c - d)


应用实例:文件系统

文件系统的目录结构可以用广义表表示:

  • 原子节点:表示文件。

  • 子表节点:表示目录,目录中可以包含文件或其他目录。


总结

广义表是一种非常灵活的数据结构,适合表示复杂的数据结构。通过学习广义表的基本操作和实现,你可以更好地解决实际问题。希望通过这篇文章,你能轻松掌握广义表的相关知识!


http://www.kler.cn/a/554337.html

相关文章:

  • SpringMVC的基本使用
  • SpringBoot 项目配置日志输出
  • mysql中union all和WITH ROLLUP实现汇总的两种方式
  • Flink CDC详解
  • 在实时大数据处理中如何平衡延迟和吞吐量
  • AI(12)-设备端部署
  • 基于腾讯云大模型知识引擎×DeepSeek构建八字、六爻赛博算卦娱乐应用
  • 【Research Proposal】基于提示词方法的智能体工具调用研究——研究背景
  • 力扣hot100——螺旋矩阵 超简单易懂的模拟搜索方法
  • FastGPT快速将消息发送至飞书
  • OpenCV形态学操作
  • Spring DI
  • 【AB-01】 AUTOSAR Builder软件安装
  • Debezium 报错:“The db history topic is missing” 的处理方法
  • 知识库-知识收藏、取消收藏接口
  • Hutool - DB:基于 ActiveRecord 思想的 JDBC 封装数据操作工具
  • 爱普生 SG-8101CE 可编程晶振在笔记本电脑的应用
  • LabVIEW开发中的电机控制与相机像素差
  • 智能检测摄像头模块在客流统计中的应用
  • Mongoose 搜索注入漏洞分析