广义表的递归实现 C/C++

概论

广义表是一种重要的数据结构,可以看作内置数据类型数组的扩展,即推广数组的定义,可以将另一个数组作为这个数组的元素,再进一步推广,内涵数组中的元素还可以是一个数组,即广义表中的元素可以是一个广义表

如下

数组:[a,b,c,d,e,f,g]

广义表:[a,b,c,[e,[f,g]]]

在python等语言中已经将广义表作为合法数据类型

存储结构

广义表中的元素有两类,一类是广义表,一类是原子,并且一个位置出现的类型是唯一的,所以使用union数据类型来存储元素

同时使用链表类型来构建广义表能节省很大的工作量

typedef struct Glnode           //头尾链表存储结构
{
    ElemTage type;              //用于区存储数据是元素还是子表
    union              //由于有两种数据类型使用共用体来存储相应元素(注意union中的数据只能出现一种)
    {
        char n;                  //元素
        struct Glnode* begin;
    };
    struct Glnode* next;
}*glode;

头尾结点存储(这种办法使得后续构建广义表更加复杂)


typedef struct GLNode
{
    ElemTage type;
    union
    {
        int n;
        struct GLNode* hp,*tp;
    };
}*GList;

初始化广义表

初始化广义表实际就是创建第一个结点,并初始化其中的指针(注意指针在使用和结束以后都要初始化,将指针指向一个安全的区域,否则很可能在后续程序的运行过程中出现内存错误,野指针给cpp的内存操作等提供了很大的便捷性,但是同时也给cpp的内存安全造成很大麻烦)

glode CreatList(glode head,strin S)
{
    glode dim;
    dim = head;
    S->count0 += 1;
    while (S->count0 != S->count-1)
    {
        
        if (S->string[S->count0] <= 'z' && S->string[S->count0] >= 'a')                  //在表中所有元素都是原子时实际上可以直接看作是一个链表的构建
        {
            dim->type = ATOM;
            dim->n = S->string[S->count0];
            if (S->string[S->count0+1] == ')')                                           //这个条件实际是用来判定递归什么时候终止
            {
                dim->next = NULL;                 //同时将最后一个指针指向NULL(实际上这个NULL最好在初始化函数中定义)初始化指针很重要否则cpp中的野指针可能造成很大的麻烦
                return head;
            }
            dim->next = new Glnode;
            dim = dim->next;
            S->count0 += 1;
            continue;
        }
        if (S->string[S->count0] == '(')                                              //在遇到子表时就需要考虑侧枝的构建
        {
            dim->type = LIST;
            dim->begin = new Glnode;
            dim->begin = CreatList(dim->begin, S);                                     //这里通过递归的方法来构建侧链
            if (S->string[S->count0 + 1] == ')')
            {
                dim->next = NULL;
                return head;
            }
            else 
            {
                dim->next = new Glnode;                                                   
                dim = dim->next; 
            }
                                                              //其实把构建侧枝的语句删去,剩下的其实就是链表构建语句
            S->count0 += 1;
            continue;
        }

        S->count0 += 1;
        
    }
    return head;

}

销毁广义表

在数据结构使用结束后应当及时释放内存,初始化指针,否则内存被大量无用数据占用可能会出现内存溢出等问题

void Distorylist(glode head)                        //同样用递归的方法销毁广义表
{
    glode dim;
    dim = head;
    while (dim->next != NULL)
    {
        if (dim->type == ATOM)
        {
            head = head->next;
            free(dim);
            dim = head;
        }
        else if (dim->type == LIST)
        {
            head = head->next;
            Distorylist(dim->begin);               //递归删除支链
            free(dim);
            dim = head;
        }
    }
    if (dim->next == NULL)
    {
        free(dim);
    }
    cout << "广义表成功销毁";
}

广义表深度

即内部最多嵌套的括号的数目

void Deep(glode head)                                      
{
    int count = 1;
    int middle = 0;
    glode dim;
    dim = head;
    while (dim->next != NULL)
    {
        if (dim->type == LIST)
        {
            middle += 1;
            Deep(dim->begin);
        }
        if (middle > count)
        {
            count = middle;
            middle = 1;
        }
        dim = dim->next;
    }
    if (dim->next == NULL)
    {
        if (dim->type == LIST)
        {
            middle += 1;
            Deep(dim->begin);
        }
        if (middle > count)
        {
            count = middle;
        }
    }
    cout << "最深层数" << count << endl;
}

打印广义表

同样使用递归的方法遍历广义表以输出数据

void Print(glode head)
{
    glode dim = head;
    cout << '(';
    while (dim->next != NULL)
    {
        if (dim->type == ATOM)
        {
            cout << dim->n << ',';
            dim = dim->next;
        }
        else if (dim->type == LIST)
        {
            Print(dim->begin);
            dim = dim->next;
            cout << ')';
        }

    }
    if (dim->next == NULL)
    {
        if (dim->type == ATOM)
        {
            cout << dim->n;
            cout << ')';
        }
        if (dim->type == LIST)
        {
            Print(dim->begin);
            cout << ')';
        }
    }
}

完整代码

经过测试能够正常运行

#include<iostream>
#include<stdio.h>
using namespace std;
const int maxsize = 20;

typedef enum{ATOM,LIST}ElemTage;


//以下为辅助函数

typedef struct sqstring                           //使用数据结构串来为广义表导入数据
{
    char string[maxsize];
    int count;                                   //(目前需要的)总数
    int count0 = 0;                                  //起始元素位置
}str, * strin;

strin Initstring()                                //创建并初始化串
{
    strin str1;
    str1 = (strin)malloc(sizeof(str));
    if (!str1)
    {
        cout << "串空间分配失败" << endl;
        abort();
    }
    str1->count = 0;
    str1->count0 = 0;
    return str1;
}
strin Insertstring()                             //一个专门为广义表构建的串输入函数
{
    strin a;
    a = Initstring();
    cout << "请输入广义表序列" << endl;
    char ap;
    cin >> ap;
    while (ap != '#')
    {
        a->string[a->count] = ap;
        a->count += 1;
        cin >> ap;
    }
    return a;
}

void Print(strin S)
{
    int countt = S->count;
    for (int i = 0; i < S->count; i++)
    {
        cout << S->string[i] << " ";
    }
    cout << endl;
}

//广义表的数据类型包括子表和元素,所以使用链表来存储相应结构
//对广义表可以这么理解,如果将所有元素一视同仁则可以看作是一个链表,再分开来看子表实际上相当于在主链上加上侧链

typedef struct Glnode           //头尾链表存储结构
{
    ElemTage type;              //用于区存储数据是元素还是子表
    union                       //由于有两种数据类型使用共用体来存储相应元素
    {
        char n;                  //元素
        struct Glnode* begin;
    };
    struct Glnode* next;
}*glode;
glode InitList()                                   //初始化广义表
{
    glode head;
    head = (glode)malloc(sizeof(Glnode));
    if (!head)                                     //如果初始化失败直接终止程序,弹出错误
    {
        cout << "初始化分配空间失败" << endl;
        abort();
    }
    head->next = NULL;
    return head;
}

void Distorylist(glode head)                        //同样用递归的方法销毁广义表
{
    glode dim;
    dim = head;
    while (dim->next != NULL)
    {
        if (dim->type == ATOM)
        {
            head = head->next;
            free(dim);
            dim = head;
        }
        else if (dim->type == LIST)
        {
            head = head->next;
            Distorylist(dim->begin);               //递归删除支链
            free(dim);
            dim = head;
        }
    }
    if (dim->next == NULL)
    {
        free(dim);
    }
    cout << "广义表成功销毁";
}

glode CreatList(glode head,strin S)
{
    glode dim;
    dim = head;
    S->count0 += 1;
    while (S->count0 != S->count-1)
    {
        
        if (S->string[S->count0] <= 'z' && S->string[S->count0] >= 'a')                  //在表中所有元素都是原子时实际上可以直接看作是一个链表的构建
        {
            dim->type = ATOM;
            dim->n = S->string[S->count0];
            if (S->string[S->count0+1] == ')')                                           //这个条件实际是用来判定递归什么时候终止
            {
                dim->next = NULL;                 //同时将最后一个指针指向NULL(实际上这个NULL最好在初始化函数中定义)初始化指针很重要否则cpp中的野指针可能造成很大的麻烦
                return head;
            }
            dim->next = new Glnode;
            dim = dim->next;
            S->count0 += 1;
            continue;
        }
        if (S->string[S->count0] == '(')                                              //在遇到子表时就需要考虑侧枝的构建
        {
            dim->type = LIST;
            dim->begin = new Glnode;
            dim->begin = CreatList(dim->begin, S);                                     //这里通过递归的方法来构建侧链
            if (S->string[S->count0 + 1] == ')')
            {
                dim->next = NULL;
                return head;
            }
            else 
            {
                dim->next = new Glnode;                                                   
                dim = dim->next; 
            }
                                                              //其实把构建侧枝的语句删去,剩下的其实就是链表构建语句
            S->count0 += 1;
            continue;
        }

        S->count0 += 1;
        
    }
    return head;

}

void Print(glode head)
{
    glode dim = head;
    cout << '(';
    while (dim->next != NULL)
    {
        if (dim->type == ATOM)
        {
            cout << dim->n << ',';
            dim = dim->next;
        }
        else if (dim->type == LIST)
        {
            Print(dim->begin);
            dim = dim->next;
            cout << ')';
        }

    }
    if (dim->next == NULL)
    {
        if (dim->type == ATOM)
        {
            cout << dim->n;
            cout << ')';
        }
        if (dim->type == LIST)
        {
            Print(dim->begin);
            cout << ')';
        }
    }
}

void Deep(glode head)                                      //还未经过测试
{
    int count = 1;
    int middle = 0;
    glode dim;
    dim = head;
    while (dim->next != NULL)
    {
        if (dim->type == LIST)
        {
            middle += 1;
            Deep(dim->begin);
        }
        if (middle > count)
        {
            count = middle;
            middle = 1;
        }
        dim = dim->next;
    }
    if (dim->next == NULL)
    {
        if (dim->type == LIST)
        {
            middle += 1;
            Deep(dim->begin);
        }
        if (middle > count)
        {
            count = middle;
        }
    }
    cout << "最深层数" << count << endl;
}
int main()
{
    glode head;
    head = InitList();
    strin S;
    S = Insertstring();
    Print(S);
    head = CreatList(head, S);
    Print(head);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值