C++数据结构-广义表

news2024/11/20 19:35:07

广义表的定义

如果允许表中的数据元素具有自身结构,即数据元素也可以是一个线性表,这就是广义表,有时也称之为列表(Lists)。

广义表是n(n≥0)个元素a1, a2, …, an的有限序列,即LS=(a1, a2, …, an)。

其中,LS是广义表的名称,n是它的长度。ai可以是单个元素,也可以是广义表。若ai是单个元素,则称它是广义表LS的原子;若ai是广义表,则称它为LS的子表。当LS非空时,称第一个元素a1为LS的表头(Head),其余元素组成的表(a2, a3,…, an)为表尾(Tail)。

举一些广义表的例子,约定大写字母表示表,小写字母表示原子:

A=( ):A是一个空表,其长度为0。

B=(b, c):B是一个长度为2的列表。

C=(a, (d, e, f)):C是一个长度为2的列表,其中第一个元素是原子a,第二个元素是子表(d, e, f)。

D=(A, B, C):D是一个长度为3的列表,其中3个元素都是子表。

E=(a, E):E是一个长度为2的列表,它是一个递归表。

广义表可以用图形象地表示,如上述例子可以用下图表示。图中用圆圈表示广义表,用方块表示原子。

在这里插入图片描述
由广义表的定义可以推导出以下4个结论。

① 由于广义表中的元素可以是原子也可以是子表,因此广义表是一个多层次结构。

② 广义表是可以共享的。例如在上述例子中,广义表B是D的子表。

③ 广义表可以是其本身的一个子表,因此广义表允许递归。例如在上述例子中,广义表E是一个递归表。

④ 广义表的元素之间除了存在次序关系之外,还存在层次关系。把广义表展开后所包含的括号层数称为广义表的深度。例如,广义表C的深度为2, E的深度为∞。

广义表的操作主要有:

◉ 建立一个广义表。

◉ 判断广义表是否为空表。

◉ 判断指定数据元素是否为原子。

◉ 求广义表深度。

◉ 遍历广义表。

◉ 插入一个数据元素。

◉ 删除一个数据元素。

广义表的存储结构

由于广义表的数据元素具有不同结构,所以用顺序结构很难实现,通常采用链式结构,一个结点表示一个元素。

广义表的单链表示

类似线性表的单链表结构,可以用单链结构存储广义表。每个结点由如下3个域组成:

在这里插入图片描述
其中atom是标志域,true表示该元素是原子,false表示是广义表。如果元素是原子,则next保存后继结点的地址,只使用data值;如果元素是广义表,那么sublist保存子表的第一个结点的地址,next保存后继结点的地址
在这里插入图片描述
广义表的节点定义:

// 广义表节点的结构定义
struct GListNode {
    bool isAtom;  // 是否是原子类型节点
    union {
        int data;  // 原子类型节点的值
        GListNode* sublist;  // 子表类型节点的子表指针
    };
    GListNode* next;   // 下一个节点指针
};

为什么选用union?

广义表节点可以是原子类型或子表类型,因此我们需要为节点结构体定义两个不同的属性。使用union结构体可以使节点结构体的内存使用更为紧凑,从而减小内存的占用,比使用两个不同的属性更高效。

union结构体中,只有一个成员可以有效地保存数据,而使用布尔型的isAtom表示节点的类型,则可以使用union结构体中的另一个成员来存储节点所包含的数据。在该示例中,data成员用于存储原子类型节点的值,而sublist成员用于存储子表类型节点的子表指针。

此外,使用union结构体还可以减少代码的复杂度,使程序更加简洁易懂,提高代码的可读性和可维护性。

广义表的简单实现

#pragma once

#include <iostream>

// 广义表节点的结构定义
struct GListNode 
{
	bool isAtom;  // 是否是原子类型节点

	union 
	{

		int data;  // 原子类型节点的值

		GListNode* sublist;  // 子表类型节点的子表指针

	};

	GListNode* next;   // 下一个节点指针
};

class GenTable
{
public:

	// 创建原子
	GListNode* CreateAtom(const int& value);

	// 创建广义表
	GListNode* CreateSublist(GListNode* sublist);

	// 在广义表末尾添加节点
	void AppendNode(GListNode*& list, GListNode* node);

	// 打印广义表
	void PrintGList(GListNode* list);

	// 求广义表深度
	int GetDepth(GListNode* node);

	// 判断指定数据元素是否为原子
	bool IsAtom(GListNode* node);

private:

	GListNode* head_;
};
#include "GenTable.h"

GListNode* GenTable::CreateAtom(const int& value)
{
    GListNode* node = new GListNode;

    node->isAtom = true;
    node->data = value;
    node->next = nullptr;

    return node;
}

GListNode* GenTable::CreateSublist(GListNode* sublist)
{
    GListNode* node = new GListNode;
    
    node->isAtom = false;
    node->sublist = sublist;
    node->next = nullptr;

    return node;
}

void GenTable::AppendNode(GListNode*& list, GListNode* node)
{
    if (list == nullptr)
        list = node;
    else
    {
        GListNode* p = list;

        while (p->next)
            p = p->next;

        p->next = node;
    }
}

void GenTable::PrintGList(GListNode* list)
{
	if (list == nullptr) 
    {
		std::cout << "空表" << std::endl;
		return;
	}

	std::cout << "(";

	GListNode* p = list;

	while (p != nullptr) 
    {
	
        if (p->isAtom) 
			std::cout << p->data;
		else
			PrintGList(p->sublist);

		if (p->next != nullptr)
			std::cout << ", ";

		p = p->next;
	}
	std::cout << ")";
}

int GenTable::GetDepth(GListNode* node)
{
    // 空表的深度为0
    if (node == nullptr)
        return 0;

	if (node->isAtom && node->next == nullptr)
		// 原子的深度为1
		return 1;
	else if(node->isAtom)
		return GetDepth(node->next);

	int maxDepth = 0;
	
	// 遍历子表,并计算子表的深度
	GListNode* sublist = node->sublist;

	while (sublist != nullptr)
	{
		int currDepth = GetDepth(sublist);
		if (currDepth > maxDepth)
			maxDepth = currDepth;
		
		sublist = sublist->next;
	}

	// 子表的最大深度加1
	return maxDepth + 1;
}

bool GenTable::IsAtom(GListNode* node)
{
    return node != nullptr && node->isAtom;
}
#include <iostream>

#include "GenTable.h"

int main()
{
	GenTable table;

	GListNode* list = nullptr;

	GListNode* sublist = table.CreateSublist(table.CreateAtom(1));
	table.AppendNode(sublist->sublist, table.CreateAtom(5));

	GListNode* templist = table.CreateSublist(table.CreateAtom(6));
	table.AppendNode(templist->sublist, sublist);

	table.AppendNode(list, table.CreateAtom(2));
	table.AppendNode(list, table.CreateAtom(3));
	table.AppendNode(list, templist);
	table.AppendNode(list, table.CreateAtom(4));

	table.PrintGList(list);
	std::cout << std::endl;

	std::cout << "深度为:" << table.GetDepth(list) << std::endl;

	system("pause");
	return 0;
}

输出:

(2, 3, (6, (1, 5)), 4)
深度为:3

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1351266.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Objects are not valid as a React child (found: object with keys {name}).

在jsx中可以嵌套表达式&#xff0c;将表达式作为内容的一部分&#xff0c;但是要注意&#xff0c;普通对象不能作为子元素&#xff1b;但是数组&#xff0c;react元素对象是可以的 如下&#xff1a;不能将stu这个对象作为子元素放 function App() {const myCal imgStyleconst…

深度生成模型之GAN的评估 ->(个人学习记录笔记)

文章目录 深度生成模型之GAN的评估图像翻译的应用1. 风格迁移2. 数据增强3. 经典图像任务4. 内容创作5. 人脸图像编辑6. 人体图像编辑 图像翻译模型1. 有监督图像翻译模型2. 无监督图像翻译模型3. 多域图像翻译模型 深度生成模型之GAN的评估 图像翻译的应用 1. 风格迁移 各类…

本地计算机 上的 My5OL808 服务启动后停止,某些服务在未由其他服务或程序使用时将自动停止

客户反馈说mysql启动不了&#xff0c;报错信息&#xff1a; 本地计算机 上的 My5OL808 服务启动后停止&#xff0c;某些服务在未由其他服务或程序使用时将自动停止。 查了不少资料&#xff0c;最后分析问题是这样的&#xff0c;手动或者重复安装mysql时&#xff0c;创建了多个…

计算机网络 VLAN

路由器将多个局域网连接起来&#xff0c;而交换机将一个局域网里的设备连接起来。 路由器的端口分配局域网的网段&#xff08;子网网段&#xff09;&#xff0c;局域网的内部设备的ip都在这个网段里&#xff0c;再由交换机将数据派发到目的设备&#xff0c;交换机是按照MAC地址…

欢迎提交pr共同改进项目, pr的含义?

"提交PR"在软件开发和编程领域是一个常用术语&#xff0c;特别是在使用版本控制系统如Git时。这里的“PR”指的是“Pull Request”&#xff0c;它是一种通知项目维护人员您已经完成了一些代码改动并希望将这些改动合并到主项目中的方式。简单来说&#xff0c;当您对一…

lenovo联想小新Pro-13 2020 Intel IML版笔记本电脑(82DN)原装出厂Win10系统镜像

链接&#xff1a;https://pan.baidu.com/s/1bJpfXudYEC7MJ7qfjDYPdg?pwdjipj 提取码&#xff1a;jipj 原装出厂Windows10系统自带所有驱动、出厂主题壁纸、系统属性专属LOGO标志、Office办公软件、联想电脑管家等预装程序 所需要工具&#xff1a;16G或以上的U盘 文件格式&a…

electron预加载脚本

webPreferences 指定预加载脚本,可以使用部分node脚本 webPreferences: {preload: path.join(__dirname, "preload.js"),},创建preload.js 中 测试文件读取功能 const fs require(fs) const text fs.readFileSync(package.json, utf-8)console.log(text)报错,为了…

Mac环境下反编译apk

Mac环境下反编译apk 安装反编译工具dex2jar&#xff1a;[官网下载](https://sourceforge.net/projects/dex2jar/)JD-GUI&#xff1a;[官网下载](https://jd-gui.apponic.com/) 实操1. 将需要反编译的 .apk 文件放在下载的 dex2jar 文件夹目录下2. 使用 cd /xxx/dex2jar-2.0 命令…

【algorithm】自动驾驶常见常考的几个模型和推导,顺便总结自己遇到的考题经验不断更新之———控制版

写在前面 本来快达成目标了&#xff0c;没想到公司遭受了问题&#xff0c;公司和同事我感觉还是挺好的&#xff0c;有国企的正规也有小企业的灵活&#xff0c;大家都很有学习欲望。 作为本次再次复习回忆如下&#xff1a; 把之前面试准备的 机器学习&#xff08;基本搬运到CSD…

安全与认证Week4

目录 本章需要理解的问题 Web Security (TLS/SSL) 关于网络 使用网络会受到的威胁 各层安全协议 S/MIME、PGP&#xff08;后面和S/MIME一起出现&#xff09;、Kerberos、TLS/SSL 和 IP/IPSec 分别是&#xff1a; S/MIME (Secure/Multipurpose Internet Mail Extensions)&#x…

js文件上传 分片上传/断点续传/极速秒传

(极速秒传)利用md5判断上传的文件是否存在 MD5信息摘要算法&#xff0c;一种被广泛使用的密码散列函数&#xff0c;可以产生出一个128位&#xff08;16字节&#xff09;的散列值&#xff08;hash value&#xff09;&#xff0c;用于确保信息传输完整一致。 每一个文件都会生成…

杰发科技AC7840——Eclipse环境DMA注意事项

0.序 用 户 使 用 DMA 时 &#xff0c; 所 有 DMA 搬 运 的 SRAM 数 据 都 必 须 存 放 在 SRAM_U 区 (0x20000000~0x2000EFFF) 。 1. 修改办法 第一步&#xff1a; RAM定义 /* Specify the memory areas */ MEMORY {FLASH (rx) : ORIGIN 0x00000000, LENGT…

【零基础入门TypeScript】类型和变量

目录 任意类型 内置类型 Null 和 undefined ─ 它们是一样的吗&#xff1f; 用户定义类型 TypeScript 中的变量声明 示例&#xff1a;TypeScript 中的变量 TypeScript 中的类型断言 例子 TypeScript 中的推断类型 示例&#xff1a;推断类型 TypeScript 变量作用域 …

认识机器学习【woodwhales.cn】

为了更好的阅读体验&#xff0c;建议移步至笔者的博客阅读&#xff1a;认识机器学习 生活中的问题1&#xff1a;居民家庭生活用气价格 北京燃气小程序在线咨询&#xff0c;查询北京居民家庭生活用气价格 上图价格梯度&#xff0c;可以由文字转换成表格&#xff1a; 第一档用气…

DrGraph原理示教 - OpenCV 4 功能 - 二值化

二值化&#xff0c;也就是处理结果为0或1&#xff0c;当然是针对图像的各像素而言的 1或0&#xff0c;对应于有无&#xff0c;也就是留下有用的&#xff0c;删除无用的&#xff0c;有用的部分&#xff0c;就是关心的部分 在图像处理中&#xff0c;也不仅仅只是1或0&#xff0c;…

Linux 命令echo

命令作用 输出一行字符串在shell中&#xff0c;可以打印变量的值输出结果写入到文件在显示器上显示一段文字&#xff0c;起到提示的作用 语法 echo [选项] [字符串] 参数 字符含义-n不自动换行-e解释转义字符-E不解释转义字符 如果-e有效&#xff0c;则识别以下序列&…

【Unity入门】RequireComponent的使用

目录 RequireComponent的作用构造函数 RequireComponent的作用 RequireComponent 属性自动将所需的组件添加为依赖项。 当某个脚本必须依赖其他脚本或者组件共同使用时&#xff0c;为了避免人为添加过程的操作失误&#xff0c;可以在代码中使用RequireComponent&#xff0c;它…

c语言:设计投票小程序|练习题

一、题目 设计一个投票小程序 如图&#xff1a; 二、代码图片【带注释】 三、源代码【带注释】 #include <stdio.h> #include<string.h> void win(int,int,int); int main() { char ch[5]; int countLili0; int countjp0; int countzx0; int …

OS 7--DNS配置+Apache发布网站

环境准备 centOS 7 1.配置DNS 1.1 域名为lianxi.com 1.2 为WWW服务器、FTP服务器、NEWS服务器做域名解析 1)安装DNS yum -y install bind bind-utils (如果安装不上&#xff0c;就把磁盘在重洗挂载一下&#xff09; 2&#xff09;修改DNS配置文件 vim /etc/resolv.conf…

【一文入门】Git常用命令集锦--分支操作和版本管理篇

前言 Git 是一种分布式版本控制系统&#xff0c;可以帮助团队协作开发、管理和维护代码&#xff0c;提高代码质量和效率&#xff0c;掌握常用版本管理命令可以帮助我们更好地管理代码变更和历史记录。下面我将介绍开发中常用的一些Git分支操作和版本管理命令 1 分支操作 1.1 …