C++实现广义表
2015-11-08 16:31
363 查看
定义:
广义表是n(n≥0)个元素a1,a2,…,ai,…,an的有限序列。
其中:
①ai--或者是原子或者是一个广义表。
②广义表通常记作:
Ls=( a1,a2,…,ai,…,an)。
③Ls是广义表的名字,n为它的长度。
④若ai是广义表,则称它为Ls的子表。
注意:
①广义表通常用圆括号括起来,用逗号分隔其中的元素。
②为了区分原子和广义表,书写时用大写字母表示广义表,用小写字母表示原子。
③若广义表Ls非空(n≥1),则al是LS的表头,其余元素组成的表(a1,a2,…,an)称为Ls的表尾。
④广义表是递归定义的
画图举例:
代码实现:
测试代码
运行结果
广义表是n(n≥0)个元素a1,a2,…,ai,…,an的有限序列。
其中:
①ai--或者是原子或者是一个广义表。
②广义表通常记作:
Ls=( a1,a2,…,ai,…,an)。
③Ls是广义表的名字,n为它的长度。
④若ai是广义表,则称它为Ls的子表。
注意:
①广义表通常用圆括号括起来,用逗号分隔其中的元素。
②为了区分原子和广义表,书写时用大写字母表示广义表,用小写字母表示原子。
③若广义表Ls非空(n≥1),则al是LS的表头,其余元素组成的表(a1,a2,…,an)称为Ls的表尾。
④广义表是递归定义的
画图举例:
代码实现:
#include <iostream> using namespace std; //表示广义表的结点类型 enum NodeType { HEAD_TYPE,//头结点类型 VALUE_TYPE,//值结点类型 SUB_TYPE//子表类型 }; //表示广义表结点的结构体 struct GeneraListNode { NodeType _type;//结点类型 GeneraListNode *_next;//存放结点的下一个元素的地址 //一个结点要么是值结点要么是子表,故用联合体来存放节省一定的空间 //若是值结点则存放的是值,是子表结点的话存放的是子表结点头结点的地址 union{ char _value; GeneraListNode *_subLink; }; GeneraListNode(NodeType type = HEAD_TYPE, char value = '\0') :_type(type) ,_next(NULL) { if (type == VALUE_TYPE) { _value = value; }else if(type == SUB_TYPE) { _subLink = NULL; } } }; class GeneraList { private: GeneraListNode *_link;//用来存放广义表头结点地址 public: GeneraList(const char *str) :_link(NULL) { _CreateGeneraList(_link, str);//根据指定序列创建广义表 } ~GeneraList() {} public: void Print();//对外提供的打印广义表的接口 int Size();//广义表中值结点的数目的对外获取接口 int Depth();//广义表的最深层次的对外获取接口 private: void _CreateGeneraList(GeneraListNode *& link, const char *& str); bool _IsValue(const char ch);//判断指定字符是否为值结点所允许的类型 int _Size(GeneraListNode *head);//计算广义表中值结点的数目的实现 int _Depth(GeneraListNode *head);//计算广义表的最深层次的实现 void _Print(GeneraListNode *link);//打印广义表的接口的底层实现 }; //创建广义表 void GeneraList::_CreateGeneraList(GeneraListNode *& link, const char *& str) { //广义表最前端有一个头结点,用来记录实现广义表链表的首地址 //故每次调用该创建广义表的函数首先创建一个头结点 GeneraListNode* head = new GeneraListNode(HEAD_TYPE, NULL); head->_next = NULL; link = head; GeneraListNode* cur = link;//用来记录创建广义表链表时当前创建出的结点位置游标指针 str++;//将广义表序列后移,相当于跳过了'(' while(*str != '\0') { if(_IsValue(*str)){//如果当前扫描到的字符是值 //创建一个值结点 GeneraListNode* newNode = new GeneraListNode(VALUE_TYPE, *str); newNode->_next = NULL; cur->_next = newNode;//将该值结点加入到链表中 cur = cur->_next;//游标后移 str++;//将广义表序列后移 }else if(*str == '('){//如果扫描到'('创建子表结点 GeneraListNode* subLink = new GeneraListNode(SUB_TYPE, NULL); subLink->_next = NULL; cur->_next = subLink;//将子表结点加入到链表中 cur = cur->_next; _CreateGeneraList(cur->_subLink, str);//递归创建子表 }else if(*str == ')'){ str++; return;//若扫描到')'表示广义表创建结束 }else{ str++;//空格等其他无效字符跳过 } } } int GeneraList::Size() { return _Size(_link); } //计算广义表值结点的个数 int GeneraList::_Size(GeneraListNode *head) { int size = 0; GeneraListNode *cur = head; while(cur != NULL){ if(cur->_type == VALUE_TYPE){ ++size;//遇到值结点则将size加一 }else if(cur->_type == SUB_TYPE){ size += _Size(cur->_subLink);//遇到子表进行递归 } cur = cur->_next; } return size; } int GeneraList::Depth() { return _Depth(_link); } int GeneraList::_Depth(GeneraListNode *head) { int depth = 1,maxDepth = 1;//depth表示当前表的深度,maxDepth表示目前最大的深度 GeneraListNode *cur = head; while(cur != NULL){ if(cur->_type == SUB_TYPE){ depth += _Depth(cur->_subLink); } if(depth > maxDepth){//更新最大深度 maxDepth = depth; depth = 1;//将当前深度复位 } cur = cur->_next; } return maxDepth; } void GeneraList::Print() { _Print(_link); cout<<endl; } //打印广义表 void GeneraList::_Print(GeneraListNode *link) { GeneraListNode *cur = link;//遍历广义表的游标 while(cur != NULL){ if(cur->_type == VALUE_TYPE){ cout<<cur->_value; if(cur->_next != NULL) { cout<<','; } }else if(cur->_type == HEAD_TYPE){ cout<<"("; }else if(cur->_type == SUB_TYPE){ _Print(cur->_subLink);//遇到子表递归打印 if(cur->_next != NULL)//如果打印完子表后广义表未结束则打印',' { cout<<","; } } cur = cur->_next; } cout<<")"; } bool GeneraList::_IsValue(const char ch) { if(ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '(') { return true; } return false; }
测试代码
#include"GeneraList.hpp" //测试空表 void Test1() { GeneraList genList("()"); genList.Print(); cout<<"Size is :"<<genList.Size()<<endl; cout<<"Depth is :"<<genList.Depth()<<endl<<endl; } //测试单层表 void Test2() { GeneraList genList("(a,b)"); genList.Print(); cout<<"Size is :"<<genList.Size()<<endl; cout<<"Depth is :"<<genList.Depth()<<endl<<endl; } //测试双层表 void Test3() { GeneraList genList("(a,b,(c,d))"); genList.Print(); cout<<"Size is :"<<genList.Size()<<endl; cout<<"Depth is :"<<genList.Depth()<<endl<<endl; } //测试多层表 void Test4() { GeneraList genList("(a,b,(c,d),(e,(f),h))"); genList.Print(); cout<<"Size is :"<<genList.Size()<<endl; cout<<"Depth is :"<<genList.Depth()<<endl<<endl; } //测试多层空表 void Test5() { GeneraList genList("(((),()),())"); genList.Print(); cout<<"Size is :"<<genList.Size()<<endl; cout<<"Depth is :"<<genList.Depth()<<endl<<endl; } int main() { Test1(); Test2(); Test3(); Test4(); Test5(); return 0; }
运行结果
相关文章推荐
- loadrunner通过C语言实现自定义字符出现次数截取对应字符串
- loadrunner通过C语言实现字符的替换(只能替换单个字符,慎用)
- ZQUOJ 24127 Milk Routing (dp)
- VS2010配置C/C++多线程使用环境
- C++中虚函数工作原理和(虚)继承类的内存占用大小计算
- 深入讲解C语言编程中volatile修饰符的作用
- C++实现对输入数字组进行排序
- C++实现动态绑定代码分享
- C++中静态变量、常量、静态整型常量、静态非整型常量、引用变量的初始化方法
- STM32按键输入、所需要的C语言复习、时钟系统框图
- [leetcode]Lowest Common Ancestor of a Binary Search Tree
- C标准库(1)
- 【C/C++学院】0826-文件重定向/键盘输入流/屏幕输出流/字符串输入输出/文件读写简单操作/字符文件读写二进制与文本差别/get与getline挖掘数据/二进制与文本差别/随机位置/多线程初级
- 第9周项目2 对称矩阵压缩存储的实现与应用
- C语言中的结构体(struct)
- 蓝桥杯练手之堆煤球
- 【C/C++学院】0826-文件重定向/键盘输入流/屏幕输出流/字符串输入输出/文件读写简单操作/字符文件读写二进制与文本差别/get与getline挖掘数据/二进制与文本差别/随机位置/多线程初级
- 蓝桥杯练手之回文数字
- 使用MPI并行求解前缀和(prefix sum)
- 【C语言】 实现strlen