广义表简称表,是线性表的推广,表中元素可以是数据元素(原子),也可以是子表。
广义表的表头(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('\0'){}
Items(Items<T>& RL){mark=Rl.mark;utype=RL.utypr;info=RL.info;}
}
template <class T>
struct GenListNode {
public:
GenListNode():mark(0),utype(0),tlink(NULL),info.LName('\0'){}
GenListNode(GenListNode<T>& RL){mark=RL.mark; utype=RL.utype; tlink=RL.tlink; info=RL.info;}
int getMark(GenListNode<T> *elem){return elem->mark;}
int getType(GenListNode<T> *elem){return elem->utype;}
int getListName(GenListNode<T> *elem){return elem->info.LName;}
T getValue(GenListNode<T>* elem){return elem->info.value;}
GenListNode* gettlink(GenListNode<T>* elem){return elem->tlink;}
GenListNode* gethlink(GenListNode<T>* elem){return elem->info.hlink;}
private:
int mark;
int utype;
GenListNode<T> *tlink;
union{
char *LName;
T value;
GenListNode<T> *hlink;
}info;
}
template GenList{
public:
GenList();
~GenList(){Remove(first);}
bool Head(Items& x);
bool Tail(GenList<T> <);
GenListNode<T> *First(){return first;}
GenListNode<T> *Next(GenListNode<T> *elem){return elem->tlink;}
void Traverse(); //非递归遍历
private:
GenListNode<T> *first;
void Traverse(GenListNode<T> *ls); //递归遍历
}
template <class T>
void GenList::Traverse(){
Stack<GenListNode<T>*> st;
GenListNode<T> *ls=first;
while (ls!=NULL) {
ls->mark=1;
if (ls->utype==2){ //子表结点
if (ls->info.hlink->mark==0){
st.Push(ls->tlink;) //暂时先把子表结点的右结点入栈
ls=ls->hlink;
}
else { //子表已经遍历过
cout<<ls->info.hlink->info.LName;
if(ls->tlink!=NULL){
cout<<',';
ls=ls->tlink;
}
}
}
else {
if (ls->utype==0) cout<<ls->info.LName<<'('; //表头结点
else if (ls->utype==1){ //原子结点
cout<<ls->info.value;
if(ls->tlink!=NULL) cout<<',';
}
if(ls->tlink==NULL){
cout<<')';
if(!st.isEmpty()){
st.Pop(ls);
if(ls!=NULL) cout<<',';
else cout<<')';
}
}
else ls=ls->tlink;
}
}
}
template <class T>
void GenList::Traverse(GenListNode<T> *ls){
if(ls!=NULL){
ls->mark=1;
if (ls->utype==0) cout<<ls->info.LName<<'('; //表头结点
else if (ls->utype==1) { //原子结点
cout<<ls->info.value;
if (ls->tlink!=NULL) cout<<',';
}
else if (ls->utype==2) { //子表结点
if (ls->info.hlink->mark==0) Traverse(ls->info.hlink);
else cout<<ls->info.hlink->info.LName; //子表已经遍历过
if (ls->tlink!=NULL) cout<<',';
}
Traverse(ls->tlink);
}
else cout<<')';
}