广义表(Generalized List)

广义表(Generalized List)

1. 广义表的概念

1.1 广义表的定义
  • 广义表(Generalized List,又称列表,或表)是一种非线性的数据结构,是线性表的一种推广。
  • 广义表中放松对表元素的原子限制,容许它们具有其自身结构。即广义表的定义是递归的,因为在表的描述中又用到了表,允许表中有表,这种递归的定义能够很简洁地描述庞大而复杂的结构。
  • 一个广义表LS定义为n(n≥0)个元素 a0,a1,a2,...an1 组成的有限序列,记作LS=( a0,a1,a2,...an1 ),其中,LS为表名; ai (0≤i≤n-1)是表中元素,它或者是数据元素(称为原子),或者是子表;n是表的长度,即表中元素的个数;表的长度不包括作为分界符的左括号“(”和右括号“)”和表元素之间的分隔符“,”;长度为0的表为空表。
  • 一个广义表如果长度n≥1,则称其第一个表元素 a0 为广义表的表头(head),而由表中除 a0 外其他元素组成的表( a1,a2,...an1 )称为广义表的表尾(tail)。
  • 广义表的一些例子及其对应的示例图:

    (1)A = (),A是一个空表,表的长度为0,没有表头和表尾。
    (2)B = (a,b),B是一个只包括原子的表,称为线性表,表的长度为2,表头是a,表尾是(b)(表尾还是一个表,其表头是b,表尾是空表())。
    (3)C = (c,(d,e,f)),C是一个包括一个原子和一个子表的表,表的长度为2,表头是c,表尾是((d,e,f))(表尾还是一个表,其表头是(d,e,f),表尾是空表())。
    (4)D = (B,C,A) = ((a,b),(c,(d,e,f)),()),D是一个包括三个子表的表,表的长度为3,表头是B,表尾是(C,A)。
    (5)E = (B,D) = ((a,b),(B,C,A)) = ((a,b),((a,b),(c,(d,e,f)),())),E是一个包括两个子表的表,表的长度为2,表头是B,表尾是(D)。
    (6)F = (g,F) = (g,(g,(g,(…)))),F是一个包括一个原子和一个子表的表,表的长度为2,表头是g,表尾是(F)(表尾还是一个表,其表头是(F),表尾是空表()),对于表头来说出现了递归。

    这里写图片描述

  • 注:广义表()和(())不同,前者是长度为0的空表,对其不能做求表头和表尾的运算;而后者是长度为1的非空表(只不过该表中惟一的一个元素是空表),对其可进行分解,得到的表头和表尾均是空表()。
1.2 广义表的特性
  • 有次序性:各表元素在表中以线性序列排列,每个表元素至多一个直接前驱,一个直接后继,这个次序不能交换(ps:这句话我也不是很懂,为什么不是可以有多个直接后继。)
  • 有长度:表元素个数一定,不能是无限的,可以是空表。
  • 有深度:表元素可以是原表的子表,子表的表元素还可以是子表,……,因此广义表是多层次结构。
  • 可递归:广义表本身可以是自己的子表,一般称具有这种性质的表为递归表。
  • 可共享:广义表可以为其他广义表共享,一般称具有这种性质的表为共享表或再入表。
1.3 广义表的存储表示及结点结构
  • 广义表的存储表示:用链表结构作为广义表的存储表示。
  • 广义表的的结点包括3个部分:标志域(utype),信息域(info),尾指针域(tlink)。
    (1)标志域(utype):用来标明该结点是什么类型的结点。
      当utype=0时,表示该结点是广义表专用的附加头结点;
      当utype=1时,表示该结点是原子节点;
      当utype=2时,表示该结点是子表结点。
    (2)信息域(info):不同类型的结点在这个域中存放的内容不同。
      当utype=0时,该信息域存放引用计数(ref);
      当utype=1时,该信息域存放数据值(value);
      当utype=2时,该信息域存放指向子表表头的指针(hlink)。
    (3)尾指针域(tlink):用于存放一个指针,该指针指向下一个结点的开始存储地址。
      当utype=0时,该指针域存放指向该表表头元素结点的指针;
      当utype≠0时,该指针域存放同一层下一个表结点的地址。
  • 广义表的结点结构示意图:
    这里写图片描述

2. 广义表的实现

2.1 广义表的结点结构定义
  • 文件:GenListNode.h

    
    #ifndef GEN_LIST_NODE_H_
    
    
    #define GEN_LIST_NODE_H_
    
    
    
    #include <iostream>
    
    
    #include <string>
    
    
    #include <strstream>
    
    
    using namespace std;
    
    template <class T>
    struct GenListNode              //广义表结点类定义
    {
        int utype;                  //标志域,utype={0,1,2}
        GenListNode<T> *tlink;      //尾指针域,tlink
        union                       //信息域,info
        {
            int ref;                //当utype=0时,该信息域存放引用计数(ref)
            T value;                //当utype=1时,该信息域存放数据值(value)
            GenListNode<T> *hlink;  //当utype=2时,该信息域存放指向子表表头的指针(hlink)
        }info;
        //构造函数
        GenListNode():utype(0),tlink(NULL),info.ref(0) { }
        //拷贝构造函数
        GenListNode(GenListNode<T>& RL) { utype = RL.utype; tlink = RL.tlink; info = RL.info; }
    };
    
    #endif /* GEN_LIST_NODE_H_ */
    
2.2 广义表的类定义及其操作的实现
  • 文件:GenList.h

    
    #ifndef GEN_LIST_H_
    
    
    #define GEN_LIST_H_
    
    
    
    #include "GenListNode.h"
    
    
    template<class T>
    class GenList
    {
    public:
        GenList();      //构造函数
        ~GenList();        //析构函数
    
    public:
        GenListNode<T>* Head();                         //返回表头元素
        GenListNode<T>* First();                        //返回第一个元素
        GenListNode<T>* Next(GenListNode<T>* elem);     //返回表元素elem的直接后继元素
        GenList<T>* Tail();                             //返回表尾元素
        void Copy(const GenList<T>& R);                 //广义表的复制
        int Length();                                   //计算广义表的长度
        int Depth();                                    //计算一个非递归广义表的深度
    
    public:
        template<class T>
        friend istream& operator >> (istream& in, GenList<T>& L);   //输入广义表元素的重载操作>>
    
    private:
        GenListNode<T>* Copy(GenListNode<T>* ls);           //复制一个ls指示的无共享非递归表
        int Length(GenListNode<T>* ls);                     //求由ls指示的广义表的长度
        int Depth(GenListNode<T>* ls);                      //计算由ls指示的非递归表的深度
        bool Equal(GenListNode<T>* s, GenListNode<T>* t);   //判以s和t为表头的两个表是否相等
        void Remove(GenListNode<T> *ls);                    //释放以ls为附加头结点的广义表
        void GreateList(istream& in, GenListNode<T> *& ls); //从输入流对象输入广义表的字符串描述,建立一个带附加头结点的广义表结构
    
    private:
        GenListNode<T> *first;      //广义表头指针
    };
    
    //构造函数
    template<class T>
    GenList<T>::GenList()
    : first(new GenListNode<T>)
    {
        cout << "$ 执行构造函数" << endl;
    }
    
    //析构函数
    template<class T>
    GenList<T>::~GenList()
    {
        cout << "$ 执行析构函数" << endl;
        Remove(first);
    }
    
    //返回表头元素
    template<class T>
    GenListNode<T>* GenList<T>::Head()
    {
        return first;
    }
    
    //返回第一个元素
    template<class T>
    GenListNode<T>* GenList<T>::First()
    {
        return first->tlink;
    }
    
    //返回表元素elem的直接后继元素
    template<class T>
    GenListNode<T>* GenList<T>::Next(GenListNode<T>* elem)
    {
        return elem->tlink;
    }
    
    //返回表尾元素
    template<class T>
    GenList<T>* GenList<T>::Tail()
    {
        if (first->tlink == NULL)
        {
            return NULL;
        }
    
        GenList<T>* lt;
        lt->first->tlink = Copy(first->tlink->tlink);
        return lt;
    }
    
    //广义表的复制
    template<class T>
    void GenList<T>::Copy(const GenList<T>& R)
    {
        first = Copy(R.first);
    }
    
    //计算广义表的长度
    template<class T>
    int GenList<T>::Length()
    {
        return Length(first);
    }
    
    //计算一个非递归广义表的深度
    template<class T>
    int GenList<T>::Depth()
    {
        return Depth(first);
    }
    
    //输入广义表元素的重载操作>>
    template<class T>
    istream& operator >> (istream& in, GenList<T>& L)
    {
        return in;
    }
    
    //复制一个ls指示的无共享非递归表
    template<class T>
    GenListNode<T>* GenList<T>::Copy(GenListNode<T>* ls)
    {
        GenListNode<T> *q = NULL;
        if (ls != NULL)
        {
            q = new GenListNode<T>;     //处理当前的结点q
            q->utype = ls->utype;       //复制结点类型
            switch (ls->utype)          //根据utype传送信息
            {
                case 0:
                {
                    q->info.ref = ls->info.ref;             //附加头结点
                    break;
                }
                case 1:
                {
                    q->info.value = ls->info.value;         //原子结点
                    break;
                }
                case 2:
                {
                    q->info.hlink = Copy(ls->info.hlink);   //表结点
                    break;
                }
                default:
                {
                    break;
                }
            }
            q->tlink = Copy(ls->tlink); //处理同一层下一结点为头的表
        }
        return q;
    }
    
    //求由ls指示的广义表的长度
    template<class T>
    int GenList<T>::Length(GenListNode<T>* ls)
    {
        if (ls != NULL)
        {
            return 1 + Length(ls->tlink);
        }
        else
        {
            return 0;
        }
    }
    
    //计算由ls指示的非递归表的深度
    template<class T>
    int GenList<T>::Depth(GenListNode<T>* ls)
    {
        if (ls->tlink == NULL)
        {
            return 1;
        }
        GenListNode<T> *temp = ls->tlink;
        int m = 0;
        int n = 0;
        while (temp != NULL)
        {
            if (temp->utype == 2)
            {
                n = Depth(temp->info.hlink);
                if (m < n)
                {
                    m = n;
                }
            }
            temp = temp->tlink;
        }
        return m + 1;
    }
    
    //判以s和t为表头的两个表是否相等
    template<class T>
    bool GenList<T>::Equal(GenListNode<T>* s, GenListNode<T>* t)
    {
        int x = 0;
        if ((s->tlink == NULL) && (t->tlink == NULL))
        {
            return true;
        }
        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
            {
                x = Equal(s->tlink->info.hlink, t->tlink->info.hlink);
            }
            if (x == 1)
            {
                return Equal(s->tlink, t->tlink);
            }
        }
        return false;
    }
    
    //释放以ls为附加头结点的广义表
    template<class T>
    void GenList<T>::Remove(GenListNode<T> *ls)
    {
        ls->info.ref--; //附加头结点的引用计数减1
        if (ls->info.ref >= 0)  //如果减到0
        {
            GenListNode<T> *q;
            while (ls->tlink != NULL)   //横扫表顶层
            {
                q = ls->tlink;          //到第一个结点
                if (q->utype == 2)      //递归删除子表
                {
                    Remove(q->info.hlink);
                    if (q->info.hlink->info.ref <= 0)
                    {
                        delete q->info.hlink;   //删除子表附加头结点
                    }
                }
                ls->tlink = q->tlink;
                delete q;
            }
        }
    }
    
    //从输入流对象输入广义表的字符串描述,建立一个带附加头结点的广义表结构
    template<class T>
    void GenList<T>::GreateList(istream& in, GenListNode<T> *& ls)
    {
    
    }
    
    
    #endif /* GEN_LIST_H_ */
    
2.3 主函数(main函数)的实现
  • 文件:main.cpp

    
    #include "GenList.h"
    
    
    int main()
    {
        system("pause");
        return 0;
    }

参考文献:
[1]《数据结构(用面向对象方法与C++语言描述)(第2版)》殷人昆——第四章
[2] 百度搜索关键字:广义表
[3] 网络资源:http://blog.csdn.net/pi9nc/article/details/9228581

  • 6
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值