c++数据结构之广义表

最近学习了广义表,我们知道广义表也是一种线性表,而顾名思义广义表就是不止一个表,下面来举个栗子:

A=( )

B=(1 , 2,3)

C=(1 ,2 ,3, ( a , b ,c) )

D=(1, 2, 3, (a,( b,c),d),4)

以上A,B,C,D都是广义表,只不过深度不一样,也就是括号的对数不一样,A是个特殊的广义表,即空表。B里面有三个元素,C里面有6个元素,包括一个子表(a,b,c),C也同理,只不过多了一层子表。由此可总结为一句话:表里有表

这样看可能不太直观,下面以广义表C为例来看一下它的结构图:

(图画得有点丑,不要吐槽我)

每当遇到一个前括号,就要创建一个子表,直到遇见收括号。

那么如何创建一个广义表呢,在创建节点结构体的时候,我们要考虑每个节点的类型,有可能是头结

点,也有可能是子表节点,也有可能是普通的值节点,所以在构造节点的时候就要定义一个三元体,由

于是表里有表,我们可以用递归的方法来解决广义表的问题,每个子表都可以递归为一个子问题,就可

以很轻松的解决掉这个问题了。

下面是具体实现的代码:

先构造一个三元结构体:

enum Type
{
	HEAD,
	VALUE,
	SUB,
};
template<class T>
struct GeneralizedNode
{
	Type _type;
	GeneralizedNode<T>* _next;

	union
	{
		char _value;
		GeneralizedNode<T>* _sublink;   //子表的头结点
	};
public:
	GeneralizedNode(Type type = HEAD,char value = ‘\0‘)
		:_type(type)
		,_next(NULL)
	{
			if (type == VALUE)
			{
				_value = value;
			}
			else if (type == SUB)
			{
				_sublink = NULL;
			}
		}
};

下面来构造一个广义表类

template<class T>
class GeneralizedList
{
public:
	GeneralizedList()
		:_head(new GeneralizedNode<T>(HEAD))
	{}
	GeneralizedList(const char* str)
	{
		_head=_CreateList(str);
	}
	GeneralizedList(const GeneralizedList& g)    //拷贝构造
	{
		_head = Copy(g._head;)
	}
	size_t Size()
	{
		return size(_head);
	}
	size_t depth()
	{
		return Depth(_head);
	}

	void print()
	{
		Print(_head);
	}
protected:
	GeneralizedNode<T>* _CreateList(const char*& str)
	{
		assert(str && *str == ‘(‘);
			++str;

		GeneralizedNode<T>* Head = new GeneralizedNode<T>(HEAD,NULL);
		GeneralizedNode<T>* cur = Head;

		while (*str)
		{
			if (_IsValue(*str))
			{
				cur->_next = new GeneralizedNode<T>(VALUE,*str);

				cur = cur->_next;
				str++;
			}
			else if (*str == ‘(‘)
			{
				GeneralizedNode<T>* newNode= new GeneralizedNode<T>(SUB);        //将一个子表结点加入到链表中
				cur->_next = newNode;
				cur = cur->_next;
				cur->_sublink = _CreateList(str);

				str++;//递归创建一个子表结点
			}
			else if (*str == ‘)‘)               //表示一个表已经结束
			{
				str++;
				return Head;
			}
			else
			{
				str++;     //不需要处理的情况
			}

		}
		assert(false);
		return Head;
	}

	size_t Depth(GeneralizedNode<T>* head)
	{
		GeneralizedNode<T>* cur = head;
		size_t depth = 1;

		while (cur)
		{
			if (cur->_type == SUB)
			{
				size_t subdepth = Depth(cur->_sublink);

			if (subdepth+1 > depth)
			{
				depth=subdepth;//保存较大的深度
			}
			}
			cur = cur->_next;
		}

		return depth;
	}

	size_t size(GeneralizedNode<T>* head)
	{
		GeneralizedNode<T>* cur = head;

		size_t count = 0;
		while (cur)
		{
			if (cur->_type != SUB)
			{
				count++;
			}
			else
			{
				count += size(cur->_sublink);
			}
			cur = cur->_next;
		}
		return count;
	}

	void Print(GeneralizedNode<T>* head)
	{
		GeneralizedNode<T>* cur = head;
		while (cur)
		{
             if (cur->_type == HEAD)
			{
				cout << ‘(‘;
			}
			else if (cur->_type == VALUE)
			{
				cout << cur->_value ;
				if (cur->_next != NULL)
				{
					cout << ‘,‘ ;
				}
			}

			else if (cur->_type == SUB)
			{
				Print(cur->_sublink);
				if (cur->_next != NULL)
				{
					cout << ‘,‘;
				}
			}
			cur = cur->_next;
		}
		cout << ‘)‘;

	}

	bool _IsValue(char ch)   //检查是否为合法值
	{
		if ((ch >= ‘0‘&&ch<=‘9‘) || (ch>=‘a‘&&ch<=‘z‘) || (ch>=‘A‘&&ch <= ‘Z‘))
		{
			return true;
		}
		return false;
	}
protected:
	GeneralizedNode<T>* _head;
};

下面给出测试代码:

#include"Generalized.h"
void Test()
{
	char* ch = "(a,b,c,(1,2),c)";
	GeneralizedList<char> gl1(ch);
	gl1.print();
	cout << endl;
	cout << "广义表深度为:" << gl1.depth() << endl;
	cout << "广义表大小为:" << gl1.Size() << endl;
}

int main()
{
	Test();
	getchar();
	return 0;
}

运行结果:

以上就是C++实现广义表的方法啦,里面也许还存在着一些问题,希望大家能够指正出来,共同促进学习。

时间: 2024-12-24 03:24:51

c++数据结构之广义表的相关文章

javascript实现数据结构:广义表

原文:javascript实现数据结构:广义表  广义表是线性表的推广.广泛用于人工智能的表处理语言Lisp,把广义表作为基本的数据结构. 广义表一般记作: LS = (a1, a2, ..., an) LS是广义表的名称,n是它的长度,ai可以是单个元素,也可以是广义表,分别称为广义表LS的原子和子表.习惯上,用大写字母表示广义表的名称,小写字母表示原子.当广义表LS非空时,称第一个元素a1为LS的表头,称其余元素组成的表(a2, a3, ..., an)是LS的表尾. 下面列举一些广义表的例

数据结构实践——广义表的原子统计

本文针对数据结构基础系列网络课程(5):数组与广义表的实践项目. [项目 -广义表的原子统计] 设计算法,求出给定广义表g中的原子个数和最大原子 [参考解答] (头文件glist.h是广义表算法库建设的成果,见链接-) #include <stdio.h> #include "glist.h" int atomnum(GLNode *g) //求广义表g中的原子个数 { if (g!=NULL) { if (g->tag==0) return 1+atomnum(g-

数据结构之广义表

#include<stdio.h> //广义表的头尾链表存储结构 typedef int AtomType; typedef enum NodeType{ATOM,LIST}ElemTag;//ATOM表示原子结点,LIST表示表节点 typedef struct GLNode{ ElemTag tag; union{ AtomType atom; struct List{ struct GLNode* hp,*tp; } htp; }atom_htp; }GLNode,*GList; //求

数据结构 c++ 广义表

// CTest.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> #include <string.h> #include <stdio.h> using namespace std; typedef char ElemType; struct GLNode{ bool tag; //标志位 union{ //值域或子表的表头指针域 ElemType data; GLNo

【数据结构】广义表的默认成员函数、深度、大小、打印

广义表的定义: 广义表是非线性的结构,是n个元素的有限序列. 举例:A=(a,b,(c,d)) 我们先定义它的结构: (1)它有三种节点,头节点.值节点.子表节点. (2)两种指向下一节点的指针:指向下一值值节点的指针_next,指向子表节点的指针_sublink. (3)_next与_sublink只有一种 enum Type//用枚举形式来定义广义表中三种节点类型 {     HEAD, //头类型     VALUE,//值类型     SUB,//子表类型 }; struct Gener

数据结构:广义表转置

问题描述 设计算法,将指定的广义表的内容原地逆置.例如:若广义表GL为[1, [2, 3], 4, [5, [6, 7], 8], 9],逆置后GL为 [9, [8, [7, 6], 5], 4, [3, 2], 1] . 基本思路 如题,一眼就能看出问题具有递归性,因此采用递归来求解,代码就非常简单了. Python实现 #encoding = utf8 def reverse_table(table): ''' 递归 ''' if not isinstance(table,list) or

数据结构算法C语言实现(十九)--- 5.5&amp;5.6&amp;5.7广义表

一.简述 传说Lisp的基本数据结构就是广义表,广义表也是具有典型递归属性的数据结构,此外,由于建表要处理字符串,用C语言处理起来也是一脸懵逼.....最后自己还想写一个将广义表还原成字符串的函数,一是使其可视化,而是验证算法5.6.花了不少功夫才写出来(强烈建议自己动手写一写),最后是借助树形结构的角度才找到一个不错的解决办法.按照<数据结构编程实验>的分类,数据结构无非线性结构.树状结构.图结构,可以说树是特殊的图(图的最小生成树),线性表示特殊的树.....扯远了! 二.头文件 补充版字

数据结构(C语言第2版)-----数组,广义表,树,图

任何一个算法的设计取决于选定的数据结构,而算法的实现依赖于采用的存储结构. 之前线性表的数据元素都是非结构的原子类型,元素的值是不可再分的.下面学习的这两个线性表是很特殊的,其中数据元素本身也可能是一种数据结构. 认识数组和广义表 数组可以看成是一种特殊的线性表,也就是线性表中的数据元素本身也是一个线性表,数组中的个元素具有统一的类型.其实说白了就是在脑海中想数组中的数据如何在内存中以什么形式的线性表来存储.在C语言中,一个二维数组可以定义为其分量类型为一维数组类型的一维数组类型. 数组一旦被建

广义表 (五)

5.1广义表-广义表的定义和基本运算 顾名思义,广义表是线性表的推广.也有人称其为列表(Lists,用复数形式以示与统称的表List 的区别). ⒈广义表的定义和性质 我们知道,线性表是由n 个数据元素组成的有限序列.其中每个组成元素被限定为单元素,有时这种限制需要拓宽.例如,中国举办的某体育项目国际邀请赛,参赛队清单可采用如下的表示形式: (俄罗斯,巴西,(国家,河北,四川),古巴,美国,(),日本) 在这个拓宽了的线性表中,韩国队应排在美国队的后面,但由于某种原因未参加,成为空表.国家队.河