广义表简称表,是线性表的推广,表中元素可以是数据元素(原子),也可以是子表。
广义表的表头(head)是表中第一个表元素、表尾(tail)是除了表头外其它元素组成的表。
首先要对广义表结点类GenListNode和返还值的结构类Item进行定义。它们都有一个用来标明结点类型的标志域utype、一个信息域info。此外,广义表结点类还多了一个尾指针tlink指向下一个结点。
utype为0时为广义表专用的附加头结点,info存放引用计数ref
utype为1时为原子结点、info存放数据值value
utype为2时为子表结点,info存放指向子表表头的指针hlink
这种存储表示中,广义表中的所有表,无论是哪一层的子表,都带有一个附加头结点,空表也不例外
所有位于同一层的表元素,在其存储表示中也在同一层
最高一层的表结点个数(除附加头结点外)即为表的长度
#include <iostream> #include <assert.h> #include <stdlib.h> using namespace std; template <class T> struct Items{ //返回值的类结构定义 int utype; //标志域 union{ int ref; //utype=0,存放引用计数 T value; //utype=1,存放数值 GenListNode<T> *hlink; //utype=2.存放指向子表的指针 } info; Items():utype(0),info.ref(0){} //构造函数 Items(Items<T>& RL){utype=RL.utype;info=RL.info;} //复制构造函数 } template <class T> struct GenListNode{ //广义表结点类定义 public: GenListNode():utype(0),tlink(NULL),info.ref(0){} GenListNode(GenListNode<T>& RL){utype=RL.utype;tlink=Rl.tlink;info=RL.info;} private: int utype; GenListNode<T> *tlink; //比返回值的类结构多了一个tlink指针 union{ int ref; T value; GenListNode<T> *tlink; } info; } template <class T> class Genlist{ public: Genlist(); ~Genlist(); bool Head(Items& x); bool Tail(Genlist<T>& It); GenListNode<T> *First(); GenListNode<T> *Next(GenListNode<T> *elem); void Copy(const Genlist<T>& R); int Length(); int depth(); friend istream& operator>>(istream& in,Genlist<T>& L); private: GenListNode<T> *first; //广义表头指针 GenListNode<T> *Copy(GenListNode<T> *ls); int Length(GenListNode<T> *ls); int depth(GenListNode<T> *ls); bool equal(GenListNode<T> *s,GenListNode<T> *t); //判断s和t为表头的两个表是否相等 void Remove(GenListNode<T> *ls); void Createlist(istream& in,GenListNode<T> *&ls); } template <class T> Genlist<T>::Genlist(){ //构造函数 first=new GenlistNode; assert(first!=NULL); } //Head方法返回bool值,通过引用变量x返回是广义表第一个元素(Item类型的对象); template <class T> bool Genlist<T>::Head(Items<T>& x){ //若广义表非空,则通过x返回其第一个元素的值,否则函数没有意义 if(first->tlink==NULL) return false; else{ x.utype=first->tlink->utype; x.info=first->tlink->info; return true; } } template <class T> bool Genlist<T>::Tail(Genlist<T>& It){ //若广义表非空,则通过It返回广义表除表头元素以外其他元素组成的表,否则函数没有意义 if(first->tlink==NULL) return false; else{ It.first->utype=0; It.first->info.ref=0; It.first->tlink=Copy(first->tlink->tlink); return true; } } //First方法返回的是指向广义表第一个元素(GenlistNode类型的对象)的指针 template <class T> GenlistNode<T> *Genlist<T>::First(){ if(first->tlink==NULL)return NULL; else return first->tlink; } template <class T> GenlistNode<T> *Genlist<T>::Next(GenlistNode<T> *elem){ //返回表元素elem的直接后继元素 if(elem->tlink==NULL) return NULL; else return elem->tlink; }
广义表的遍历可以用如下方法:
template <class T> struct Items { int mark; int utype; union{ char *LName; //附加头结点的info域改为了表名 T value; GenListNode<T> *hlink; }info; Items():mark(0),utype(0),info.LName('