1. 广义表的定义
     每个元素可以为Atom,原子,也可以为线性表。
     线性表的推广。线性表元素有唯一的前驱和后继,为线性表,而广义表是多层次的线性表
     表头:第一个元素,可能是原子,可能是广义表
     表尾:除了第一个元素,剩余的元素,所构成的广义表
     举例:
         A = (a,b,(c,d),e)
         head(A)  = a
         tail(A) = (b,(c,d),e)
     遍历操作:
     取表头,取表尾 ,取表头..
     长度:最外层的元素数,即最外层的','+1
     深度:括号层数
  2. 广义表的两种存储结构(子表法)
 
      2.1链式存储结构 - 每个数据元素可以用一个节点表示
         元素可以为原子或列表
         原子节点:标志域、值域
         列表节点:标志域、指示表头的指针域、指示表尾的指针域
         空表:A = NULL
         除了空表,表头指针指向一个表节点,表节点再分表头、表尾...
         最高层表节点(可能原子、子表)的个数就是表长度? A = (a,b,(c,d),e) 最高层表头是先a,表尾是(b,(c,d),e),表头是b,表尾((c,d),e)..就是第一层的表尾直到为空之前,有过的表尾指针+1
         判断是否在同一层次?
             是这样的: 最高层处于同一层,后继的tail指针指向的是同一层,否则,head指针,或者表头是Atom,都是下一层。
     2.2扩展线性表存储结构
         不是用表头表尾指针了,而是,每一个节点,不管是子表还是原子,都有一个指向本子表下一个元素的next指针
         A = (a,b,(c,d))
         A -> |1,HP,TP|
                 |    |
                 a -> b -> (c,d)
                             |
                             c -> d

下面,实现了广义表的两种定义,以及基于递归的一些操作。

 #include<bits/stdc++.h>
#define AtomType int
typedef enum{ATOM,LIST}ElemTag; //ATOM = 0:原子;LIST = 1:子表
/*线性表存储之链式*/
typedef struct GLNode{
ElemTag tag; //枚举类型的标志域,只能取定义了的枚举值
union{ //union联合体,下面两部分只能取其一;要么取AtomType;要么取结构体ptr,ptr包括两个指针hp,tp
AtomType atom;
struct{
struct GLNode *hp,*tp;
}ptr;
};
}*GList; //定义广义表类型,GList为指针 /*线性表存储之扩展线性表 = 子表法*/
typedef struct GLNode2{
ElemTag tag;
union{
AtomType atom;
struct GLNode2 *hp; //对于原子,tp就是指向其相同层次的下一个元素
//对于列表,hp指向本列表内部第一个元素,而tp是指向本层次上的下一个元素
};
struct GLNode2 *tp;
} *GList2;
/*
* 讨论广义表的递归算法 : 分治法进行递归算法设计
* 1. 问题可拆解成子问题,与原问题性质相同,规模变小
* 2. 有递归终止条件
*/ /*求广义表的深度 - 采用链式存储结构时
* 广义表的深度:()的重数 空表() 深度为1.原子深度为0
*
*/
int GListDepth(GList L) {
if(!L) return ; //空表1
if(L->tag ==ATOM ) return ;
GList pp;
//遍历同一层,递归下一层,取表尾,取表头,第一步先去一个表头
int max;
for(max = , pp =L;pp!=NULL;pp = pp->ptr.tp){
int dep = GListDepth(pp->ptr.hp) ;
if(dep > max) max = dep; //这一步比较,是比较同一层的depth
}
return max+;
}
//练习
int depth_my(GList L) {
if(L == NULL){
return ;
}
if(L->tag == ATOM){
return ;
}
int max = ;
GList pp;
for(max = ,pp=L;pp!=NULL;pp = pp->ptr.tp){
int dep = depth_my(pp->ptr.hp);
if(dep >max) max = dep;
}
return max+;
} /*
求Depth2 == 子表法求dep
*/
int GListDepth_2(GList2 L){
if(L == NULL) return ;
if(L->tag == ATOM) return ;
int max = ;
GList2 pp;
for(max = ,pp=L->hp;pp!=NULL;pp = pp->tp){
int dep = GListDepth_2(pp);
if(dep >max) max = dep;
}
return max+;
}
/*********************分界*****************************/
/*
* 复制广义表:copy深复制 -- 链式存储
* 分别复制表头、表尾,然后合成即可==递归
*/
void CopyGList(GList &T,GList L) {
//头尾链表存储,将L赋值给T
if(!L) T = NULL; //空
else{
//创建一个节点 ,这个节点要么是ATOM,要么是广义表
T = (GList)malloc(sizeof(GLNode));
if(!T) exit();
T->tag = L->tag;
if(L->tag == ATOM) //是原子的话,复制原子
T->atom = L->atom;
//复制广义表
else{
//分别复制表头和表尾
CopyGList(T -> ptr.hp,L->ptr.hp);
CopyGList(T->ptr.tp,L->ptr.tp);
}
}
}
//练习
void copy_my(GList&T,GList L) {
if(L == NULL) T = NULL;
else{
T = (GList)malloc(sizeof(GLNode));
if(!T) exit();
T -> tag = L -> tag;
if(L->tag == ATOM){
T->atom = L->atom;
}else{
copy_my(T -> ptr.hp,L->ptr.hp);
copy_my(T ->ptr.tp,L->ptr.tp);
}
}
}
/**********************分割线*************************/
/*
* 创建一个广义表:必考内容
* 广义表的书写,看成一个字符串S
* 下面头尾链表法创建一个广义表
*/
using namespace std;
string emp = "()" ; void sever(string &str,string &hstr){
//将非空串str分割成两部分,hstr是表头
int n = str.size();
int i = -;
int k = ; //k记录尚未配对的“(” 数
char ch;
do{ //搜索最外层第一个(
++i;
ch = str[i];
if(ch == '(') ++k;
else if(ch == ')') --k;
}while(i<n&&(ch != ','||k!=));
if(i<n){
hstr =str.substr(,i);
//printf("in\n");
str = str.substr(i+,n-i-);
//printf("out\n");
}else{
hstr = str.substr(,str.size());
str.clear();
}
} void CreateGList(GList &L,string s){
//采用头尾链表存储结构,创建L
if(s.compare(emp) == ) L = NULL;
else{
L = (GList)malloc(sizeof(GLNode));
if(!L) exit();
if(s.size() == ){ //单个元素,建立原子节点
L->tag = ATOM;
L->atom = s[];
}else{ //表节点 ,表尾
L->tag = LIST;
GList p,q;
p = L; //p是指向当前子表(表尾节点)的指针
string sub;
sub = s.substr(,s.size()-); //去掉外层括号
string hsub;
do{ //重复建立n个子表
sever(sub,hsub); //sub中分理出表头串hsub ,同时,sub去除了hsub
CreateGList(p->ptr.hp,hsub);
q = p; //记录p,下面sub不为空,要再建立一个表尾节点,q记录上一层的p,用以连接q->ptr.tp = q
if(!sub.empty()) {
p = (GList)malloc(sizeof(GLNode));
if(!p)exit();
p -> tag = LIST;
q -> ptr.tp = p;
}//if
}while(!sub.empty());
q -> ptr.tp = NULL;
// printf("has complete\n");
}
}
} int main(){
// string s = "1232342342";
// if(s.compare("123") == 0){
// printf("13");
// }
// printf("\n");
// s = s.substr(1,s.size()-2);
// for(int i = 0;i<s.size();i++){
// printf("%c",s[i]);
// } string ss = "(2,3,4,(1,2))";
GList L;
CreateGList(L,ss);
printf("深度:");
printf("%d",GListDepth(L));
return ;
}

【C/C++】实现数据结构广义表的更多相关文章

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

    任何一个算法的设计取决于选定的数据结构,而算法的实现依赖于采用的存储结构. 之前线性表的数据元素都是非结构的原子类型,元素的值是不可再分的.下面学习的这两个线性表是很特殊的,其中数据元素本身也可能是一 ...

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

    一.简述 传说Lisp的基本数据结构就是广义表,广义表也是具有典型递归属性的数据结构,此外,由于建表要处理字符串,用C语言处理起来也是一脸懵逼.....最后自己还想写一个将广义表还原成字符串的函数,一 ...

  3. javascript实现数据结构:广义表

    原文:javascript实现数据结构:广义表  广义表是线性表的推广.广泛用于人工智能的表处理语言Lisp,把广义表作为基本的数据结构. 广义表一般记作: LS = (a1, a2, ..., an ...

  4. 数据结构(C语言版)-第4章 串、数组和广义表

    补充:C语言中常用的串运算 调用标准库函数 #include<string.h> 串比较,strcmp(char s1,char s2) 串复制,strcpy(char to,char f ...

  5. 数据结构:广义表的实现(Java)

    广义表的简单理解在这篇博文中:https://blog.csdn.net/lishanleilixin/article/details/87364496,在此不做赘述. Java实现广义表: pack ...

  6. 数据结构28:广义表及M元多项式

    广义表,又称为列表.记作: LS = (a1,a2,…,an) ;( LS 为广义表的名称, an 表示广义表中的数据). 广义表可以看作是线性表的推广.两者区别是:线性表中的数据元素只能表示单个数据 ...

  7. 数据结构之---C语言实现广义表头尾链表存储表示

    //广义表的头尾链表存储表示 //杨鑫 #include <stdio.h> #include <malloc.h> #include <stdlib.h> #in ...

  8. 数据结构 c++ 广义表

    // CTest.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> #include &l ...

  9. 广义表操作 (ava实现)——广义表深度、广义表长度、打印广义表信息

    广义表是对线性表的扩展——线性表存储的所有的数据都是原子的(一个数或者不可分割的结构),且所有的数据类型相同.而广义表是允许线性表容纳自身结构的数据结构. 广义表定义: 广义表是由n个元素组成的序列: ...

随机推荐

  1. kafka模型理解

    1.消息发送至一个topic,而这个topic可以由多个partition组成,每条消息在partition中的位置称为offset 2.消息存在有效期,如果设置为2天,则消息2天后会被删除 3.每个 ...

  2. 朱晔的互联网架构实践心得S2E2:写业务代码最容易掉的10种坑

    我承认,本文的标题有一点标题党,特别是写业务代码,大家因为没有足够重视一些细节最容易调的坑(侧重Java,当然,本文说的这些点很多是不限制于语言的). 1.客户端的使用 我们在使用Redis.Elas ...

  3. 微信小程序页面跳转方法总结

    微信小程序页面跳转目前有以下方法(不全面的欢迎补充): 1. 利用小程序提供的 API 跳转: // 保留当前页面,跳转到应用内的某个页面,使用wx.navigateBack可以返回到原页面.// 注 ...

  4. Python-TXT文本操作

    一.列出IO操作的标识符及描述 标识符 描述 r 以只读方式打开文件.文件的指针将会放在文件的开头.这是默认模式. rb 以二进制格式打开一个文件用于只读.文件指针将会放在文件的开头.这是默认模式. ...

  5. Python_迭代器和生成器的复习_38

    迭代器和生成器 迭代器: 双下方法:很少直接调用的方法,一般情况下,是通过其他方法触发的 可迭代的协议——可迭代协议 含有__iter__ 的方法 ('__iter__' in dir(数据)) 可迭 ...

  6. Streaming Principal Component Analysis in Noisy Settings

    论文背景: 面对来袭的数据,连续样本不一定是不相关的,甚至不是同分布的. 当前,大部分在线PCA都只关注准确性,而忽视时效性! 噪声?数据缺失,观测有偏,重大异常? 论文内容: Section 2 O ...

  7. 03-HTML之body标签

    body标签 HTML标签按作用主要分为两类:字体标签和排版标签 HTML标签按级别主要分为两类:文本级标签和容器级标签 文本级标签:p.span.a.b.i.u.em.文本标签里只能放文字.图片.表 ...

  8. 最长递增子序列(lis)最长公共子序列(lcs) 最长公共上升子序列(lics)

    lis: 复杂度nlgn #include<iostream> #include<cstdio> using namespace std; ],lis[],res=; int ...

  9. (第十三周)Final阶段成员贡献分

    项目名:食物链教学工具 组名:奋斗吧兄弟 组长:黄兴 组员:李俞寰.杜桥.栾骄阳.王东涵 个人贡献分=基础分+表现分 基础分=5*5*0.5/5=2.5 成员得分如下: 成员 基础分 表现分 个人贡献 ...

  10. PS调出春夏外景婚纱照

    效果图 先来看看原图和夏季的效果图 先看看原图 教程终于来咯 原图暗部太深,需要将暗部提亮.可以把暗部选区选出来.为了精确选择暗部选区,我利用计算命令如上图所示.最后得到暗部的选区. 上图得到了暗部选 ...