数据结构-广义表

广义表简称表,是线性表的推广,表中元素可以是数据元素(原子),也可以是子表。

广义表的表头(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> &lt);
    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<<')';
}

 

posted @ 2018-08-15 10:11  扬羽流风  阅读(1736)  评论(0编辑  收藏  举报