广义表

广义表
广义表的定义
广义表的存储结构
广义表的M元多项式
广义表的递归算法

一、广义表的定义:
广义表(Lists,又称列表)是一种非线性的数据结构,是线性表的一种推广。
广义表一般记作 LS = (d1,d2,....,dn);
其中LS是广义表的名称,n是它的长度;

单元素(数据元素)和子表(广义表)
表头(第一个元素d1)、表尾(剩余元素组成的表)

二、广义表的存储结构:
首先我们看一下顺序存储结构,如:单元素、子表、单元素、子表、子表……
可以看出这样存储很复杂,你不知道要分配多少存储空间给一个元素。


广义表_第1张图片
广义表顺序存储结构举例.png

链式存储结构:
每个数据元素用一个结点表示。(两种类型的结点:表结点和元素结点)


广义表_第2张图片
广义表的两种结点.png

(头尾链表存储表示)
可以看到,结点内容包含这些信息
表结点:标志域、指示表头的指针域、指示表尾的指针域
元素结点:标志域、值域

这种结构的三个好处:
指针域的作用是用来判断列表是否为空
容易分清列表中单元素和子表所在层次--?如下图中:BC在同一层,BC的内容在同一层。
最高层的表结点个数即为列表的长度--?比如说D的长度为3,表示元素A,B,C公3个。


广义表_第3张图片
广义表的链式存储结构.jpg

其中D为共享表,E为递归表。

(扩展线性链表存储表示)
另一种结点结构的链表表示列表
表结点和原子结点均由三个域组成:标志域、指示表头的指针域和指示表尾的指针域;原子结点的三个域为:标志域、值域和指示表尾的指针域。

一元多项式--线性表
一元多项式可以很容易的表示为线性表如:2X^8-9X5+5*X2+8,构成的线性表为{{2,8}, {-9,5}, {5,2}, {8,0}}

M元多项式---广义表 关联?


广义表_第4张图片
广义表与M元多项式.png

广义表的递归算法(对于非递归表且无共享子表的广义表)(递归:基本项 和 归纳项)
可实现广义表的三种操作:
1、求广义表的深度 即表中括弧的重数。
将广义表分解成n个子表,分别(递归)求得每个子表的深度。(递归的终止条件是空表和单元素)

3种情况的广义表的深度分别为:
空表的深度=1;
原子的深度=0;
广义表的深度= Max{子表的深度}+1;
具体实现:

2、复制广义表
3种情况的广义表复制:
空表直接复制;
原结点直接复制得到;
复制表头+表尾 (使用递归)
具体实现:

3、建立广义表的存储结构
3种情况:
空表的情况;
单字符建立的子表(一个原子结点)的情况;
由最简单的子表组合成广义表:广义表与子表的关系,相邻两个子表的关系。


//广义表,包括广义表的建立,求深度,复制; 采用的是将广义表划分为"头"和"尾"的模式。
//这些操作以"(((a,b),(c,d)),(e,(f,g),h),z)"形式的字符串为基础.一对括号代表一个表.
public class GLists {
    //节点类型
    public static int ATOM = 0;
    public static int LIST = 1;


    public int tag;//用于区分节点

    public Object atom;//原子类型
    public GLists hp, tp;//指向表头和表尾


    //建立广义表"(((a,b),(c,d)),(e,(f,g),h),z)"这样形式的字符串为内通建立广义表
    //同样采用递归方式。结束条件是空表和原子。
    //递归建立表头和表尾
    public static GLists createGList(GLists L, String s) {
        System.out.println(s);
        GLists p = null;
        GLists q = null;

        if (s.equals("()")) {
            L = null;//如果是空表
        }
        else {
            L = new GLists();
            if (s.length() == 1) {
                L.tag = ATOM;
                L.atom = s.charAt(0);
            }//创建单原子广义表
            else {
                L.tag = LIST;
                p = L;
                String sub = s.substring(1, s.length() - 1);

                do {//小尾中脱出头,循环建立同一层次的结点
                    Temp temp = new Temp(sub);
                    String hsub = sever(temp);
                    sub = temp.string;

                    p.hp = createGList(p.hp, hsub);
                    q = p;//hsub是头建立头

                    if (!sub.isEmpty()) {//如果有尾
                        p = new GLists();
                        p.tag = LIST;
                        q.tp = p;
                    }
                } while (!sub.isEmpty());
                q.tp = null;
            }
        }

        return L;
    }


    //该函数处理(((a,b),(c,d)),(e,(f,g),h),z)后,hstr = ((a,b),(c,d)) str = (e,(f,g),h),z.
//等于把表头和表尾分开
    public static String sever(Temp t) {
        String str = t.string;
        int n = str.length();
        int i = 0;
        int k = 0;
        char ch;
        String hstr = null;

        do {
            ch = str.charAt(i);
            i++;

            if (ch == '(') {
                k++;
            } else if (ch == ')') {
                k--;
            }
        } while (i < n && (ch != ',' || k != 0));

        if (i < n) {
            hstr = str.substring(0, i - 1);
            str = str.substring(i);
        } else {
            hstr = str;
            str = "";
        }

        t.string = str;
        return hstr;
    }

    //求广义表的深度
    public static int GetDeepth(GLists L) {
        if (L == null) {
            return 1;//空表
        }
        if (L.tag == ATOM) {
            return 0;//原子
        }
        int max = 0;
        GLists p = L;
        for (; p != null; p = p.tp) {//求同一层的光仪表元素的最大深度
            int tem = GetDeepth(p.hp);
            if (tem > max) {
                max = tem;
            }
        }

        return max + 1;
    }

    //复制广义表
    public static GLists Copy(GLists M, GLists L) {//复制广义表,把L复制到M
        if (L == null) {
            M = null;//空表
        } else {
            M = new GLists();
            M.tag = L.tag;
            if (M.tag == ATOM) {
                M.atom = L.atom;
            } else {
                M.hp = Copy(M.hp, L.hp);//复制头
                M.tp = Copy(M.tp, L.tp);//复制尾
            }
        }
        return M;
    }

    public static void main(String[] args) {
        GLists L = null;
        String s = "(((a,b),(c,d)),(e,(f,g),h),z)";

        //建表
        L = GLists.createGList(L, s);
        //求表深度
        int len = GLists.GetDeepth(L);
        System.out.println(len);
        //表复制
        GLists M = null;
        M = GLists.Copy(M, L);
    }
}

//为了应对值传递,只能传递引用拷贝,无法传递“地址”的问题
class Temp {
    String string = "";

    public Temp(String s) {
        string = s;
    }
}

你可能感兴趣的:(广义表)