博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
广义表的类定义及其操作的实现
阅读量:4094 次
发布时间:2019-05-25

本文共 5724 字,大约阅读时间需要 19 分钟。

1.头文件

# include 
using namespace std;struct GenListNode{ //广义表结点 int utype; //结点类型:=0附加头结点;=1原子结点;=2子表结点 GenListNode *tlink; //尾指针 union { //联合体:utype=0,该结点存引用计数ref;=1该结点存值value;=2该结点存子表的头指针 int ref; int value; GenListNode *hlink; } info; GenListNode():utype(0),tlink(NULL){ //结点构造函数 info.ref=0; } GenListNode(GenListNode& RL){ //复制构造函数 utype=RL.utype; tlink=RL.tlink; switch(utype){ //根据utype的值进行赋值操作 case'0':info.ref=RL.info.ref; break; case'1':info.value=RL.info.value; break; case'2':info.hlink=RL.info.hlink; break; } }};struct Items{ //该数据类型用于取表头,表尾函数,不包含tlink,与单链表比较即可理解。 int utype; union{ int ref; int value; GenListNode *hlink; }info; Items():utype(0){ //构造函数 info.ref=0; } Items(Items& RL){ //复制构造函数 utype=RL.utype; switch(utype){ case'0':info.ref=RL.info.ref; break; case'1':info.value=RL.info.value; break; case'2':info.hlink=RL.info.hlink; break; } }};class GenList{ //广义表类private: GenListNode *first; //头指针 GenListNode* Copy(GenListNode *ls); //复制ls指的广义表并返回该表的头指针 int Length(GenListNode *ls);//求ls指示的广义表的长度 int Depth(GenListNode *ls); //求ls所指的广义表的深度 bool Equal(GenListNode *s,GenListNode *t); //判断两个广义表是否相同 void Remove(GenListNode *ls); //释放ls所指的广义表 void Createlist(istream& istr,GenListNode *&ls); //根据输入流建立广义表 void delvalue(GenListNode *ls,int x); //删除广义表中原子结点值为x的结点public: GenList(); //构造函数 ~GenList(); //析构函数 bool Head(Items& x); //取表头 bool Tail(GenList& lt); //取表尾 GenListNode* First(); //求第一个元素的地址 GenListNode* Next(GenListNode *elem); //求elem所指的下一个元素的地址 void Copy(const GenList& R); //复制广义表R给调用该函数的广义表 int Length(); //求调用该函数的广义表的长度 int Depth(); //求广义表深度 friend istream& operator>>(istream& istr,GenList& L); //根据输入流建立广义表};
2.操作的实现

# include
# include
# include"GenList.h"using namespace std;GenList::GenList(){ //构造函数,构造一个空表 first=new GenListNode; assert(first!=NULL);}bool GenList::Head(Items& x){ //取表头 if(first->tlink==NULL) return false; else{ x.utype=first->tlink->utype; switch(x.utype){ case'1':x.info.value=first->tlink->info.value; break; case'2':x.info.hlink=first->tlink->info.hlink; break; } return true; }};bool GenList::Tail(GenList& lt){ //取表尾 if(first->tlink==NULL) return false; else{ lt.first->utype=0; //设置附加头结点 lt.first->info.ref=0; lt.first->tlink=Copy(first->tlink->tlink); //调用Copy函数取表尾 return true; }}GenListNode* GenList::First(){ //取第一个元素的地址 if(first->tlink==NULL) return NULL; else return first->tlink;}GenListNode* GenList::Next(GenListNode *elem){ //取elem下一个结点的地址 if(elem->tlink==NULL) return NULL; else return elem->tlink;}void GenList::Copy(const GenList& R){ //把广义表R赋值给调用该函数的广义表 first=Copy(R.first);//调用了下面的Copy函数}GenListNode* GenList::Copy(GenListNode *ls){ //赋值ls所指的广义表并返回副本的头指针 GenListNode *p=NULL; if(ls!=NULL){ p=new GenListNode; p->utype=ls->utype; //复制表头 switch(ls->utype){ case'0':p->info.ref=ls->info.ref; break; case'1':p->info.value=ls->info.value; break; case'2':p->info.hlink=Copy(ls->info.hlink); break; } p->tlink=Copy(ls->tlink); //复制表尾 } return p; //返回头指针}int GenList::Length(){ //返回广义表的长度 return Length(first);}int GenList::Length(GenListNode *ls){ //求广义表长度 if(ls==NULL) return 0; else return 1+Length(ls->tlink);//递归求长度}int GenList::Depth(){ //返回广义表的深度 return Depth(first);}int GenList::Depth(GenListNode *ls){ //求广义表深度 if(ls->tlink==NULL) //空表深度为一 return 1; GenListNode *temp=ls->tlink; int m=0,n; while(temp!=NULL){ //求子表的最大深度 if(temp->utype==2){ n=Depth(temp->info.hlink); if(m
tlink; } return m+1; //广义表的深度就是子表的最大深度+1}bool GenList::Equal(GenListNode *s,GenListNode *t){ //判断两个广义表是否相等 int x; if(s->tlink==NULL&&t->tlink==NULL) return true;//都为空表,相等 else if(s->tlink!=NULL&&t->tlink!=NULL&&s->tlink->utype==t->tlink->utype){ //判断表头是否相等 if(s->tlink->utype==1) x=(s->tlink->info.value==t->tlink->info.value)?1:0; else if(s->tlink->utype==2) x=Equal(s->tlink->info.hlink,t->tlink->info.hlink); if(x==1) //表头相等,接着判断表尾是否相等 return Equal(s->tlink,t->tlink); } return false;}void GenList::delvalue(GenListNode *ls,int x){ //删除广义表中所有原子值为x的结点 if(ls->tlink==NULL) return; //ls为空表 GenListNode *temp=ls->tlink; while(temp!=NULL){ while(temp->utype==1){ //如果该点为原子结点,用while因为可能连续几个结点都是原子结点 if(temp->info.value==x){ //值为x,删除该结点 ls->tlink=temp->tlink; delete temp; } temp=ls->tlink; } if(temp->utype==2){ //该点为子表结点 delvalue(temp->info.hlink,x); //删除子表中所有原子值为x的结点 temp=temp->tlink; } } return ; //删除完毕,返回到主函数}GenList::~GenList(){ //析构函数 Remove(first);}void GenList::Remove(GenListNode *ls){ //释放ls指示的广义表 if(ls->tlink==NULL) //如果ls为空表,删除附加头结点 delete ls; GenListNode *temp=ls->tlink; while(temp!=NULL){ while(temp!=NULL&&temp->utype==1){ //原子结点 ls->tlink=temp->tlink; delete temp; temp=ls->tlink; } if(temp->utype==2&&temp!=NULL){ //子表结点 Remove(temp->info.hlink); //删除该节点hlink指示的子表 ls->tlink=temp->tlink; //删除该结点 delete temp; temp=ls->tlink; } } delete ls; //删除附加头结点 return ; //返回主函数}

3.阅读建议

(1)由于建立广义表的算法比较复杂,因此本文中并未包括CreateList函数的实现,过几天我再单独写一篇。

(2)本文中基本所有重要函数的实现都用到了递归算法,对对递归不熟悉的小伙伴帮助应该会比较大(包括我)。很多函数只看代码应该不太容易看懂,于是附加一张广义表的结构图,大家可以手动在纸上执行递归的过程:

(3)关于递归过程中创建局部变量的问题,跟大家分享一个百度知道的问题,相信对大家理解递归有帮助:(在此处谢谢答主)

问题:当函数发生递归调用时,同一个局部变量在不同程度上可以同时存在不同的取值,这在底层是如何做到的? 

解答:

你在源代码中看到的一个局部变量,其实在函数递归过程中是存在很多副本的。

比如,你在源代码中看到一个一个局部变量 a
其实在函数递归掉用的时候,每调用一次都会在所调用函数的运行空间里存储一个a的,所以其实存在很多很多的不同的a,他们各自的存储空间是不一样的,当然能存储不同的取值了。
开始调用t(),先为t()分配存储空间,存储空里有一个a
然后t()调用t()(我们称之为t1()),先为t1()分配存储空间,存储空间里有存一个a(与前面的a是不同的)
t1()又调用t()(我们称之为t2()),先为t2分配存储空间,存储空间里存一个a(又是一个不同的a)
.....................以此类推
所以,并不是“同一个局部变量在不同程度上可以同时存在不同的取值” 
而是“不同的局部变量在不同的函数空间里存储了不同的值”

你可能感兴趣的文章
Java访问类中的私有成员(private member)
查看>>
输出一个集合所有子集的元素和(Print sums of all subsets of a given set)
查看>>
Java中的迭代器(Iterators in Java)
查看>>
Ubuntu 16.04中安装Vim 8.0
查看>>
Java中的迭代器(Iterators in Java)
查看>>
动态规划之最长公共子序列(Longest Common Subsequence)
查看>>
动态规划之编辑距离(Edit Distance)
查看>>
迭代的快速排序(Iterative Quick Sort)
查看>>
快速排序最坏的情况啥时候出现?
查看>>
动态规划之最小带权路径(Min Cost Path)
查看>>
给定链表中某个节点的指针,删除链表中的该节点
查看>>
C++类默认的成员函数与Java Object类中的成员函数
查看>>
动态规划之硬币兑换(Coin Change)
查看>>
Vim分屏显示
查看>>
已知一个字符串,输出它包含字符的所有排列(permutations)
查看>>
已知一个有重复字符的字符串,打印其所有不同的字符排列
查看>>
What are the most important data structure and algorithms to prepare for Google Interview?
查看>>
Linux环境中安装JDK
查看>>
所有整数对之间的位差异数之和(Sum of bit differences among all pairs)
查看>>
计算任意两个定点的最长路径
查看>>