广义表的读取和输出,树的拷贝及比较的实现

1. 树采用链表的形式保存,每一个节点设计成一个数据域和n个指针域, n为树的度,为了方便固定为树的最大度,但是有点浪费空间。

2. 实现的函数使用到栈来处理,遍历树时采用递归的方法。


//tree.h

#include <stdio.h>
#define DEGREE 3

typedef struct Node{
    char ch;
    struct Node * link[DEGREE];
}Node;

typedef Node * NodePointer;

int getTree(NodePointer * ptree);
void showTree(NodePointer * ptree);
int getDegree(const NodePointer *ptree);
void destoryTree(NodePointer * ptree);
void copyTree(NodePointer * dstTree, const NodePointer * srtTree);
int isEqual(const NodePointer *ptree1, const NodePointer * ptree2);

//tree.c

#include <stdio.h>
#include <ctype.h>
#include "Stack.h"
#include "tree.h"
#include <assert.h>
#define DEGREE 3
#define DEBUG 0


int getTree(NodePointer * ptree)
{
    Stack * ps;
    NodePointer  pnode;
    char input;
    Element e;
    int done = 1;
    int alpha = 0;
    int i;
    int count = 0;
    
    ps = initStack();
    
    //跳过其它字符,直到遇到左括号,表示开始
    while((input = getchar()) != '(')
        continue;
    do{
        input = getchar();
        if(isspace(input))//跳过空格
            continue;
        
        switch(input)
        {
            case '('://遇到“(”就把上一个读到的字母入栈
                e.elem = pnode;
                PUSH(ps, e);
                break;
            case ','://遇到逗号无需操作
                
                break;
            case ')':
                if(isEmpty(ps))//栈为空表示输入结束
                {
                    done = 0;
                }
                POP(ps, &e);//出栈
                break;
            default://遇到字符
                //申请内存保存字符,并将结点的链域初始化为0
                pnode = (NodePointer)malloc(sizeof(Node));
                if(pnode == NULL)
                {
                    printf("getTree malloc error.\n");
                    exit(1);
                }
                #if DEBUG
                printf("[debug] malloc space @ %p\n", (void *)pnode);
                #endif
                pnode->ch = input;
                for(i = 0; i < DEGREE; i++)
                    pnode->link[i] = NULL;
                
                if(isEmpty(ps))//第一个节点
                {
                    *ptree = pnode;
                }
                else
                {
                    NodePointer temp;
                    getTop(ps, &e);  //获取栈顶元素
                    temp = (NodePointer)e.elem;
                    for(i = 0; i < DEGREE; i++)
                    {
                        //将新结点连接到链表中,按顺序由左右表示为第0,1,2个结点
                        //链域为空表示还没有插入结点
                        if(temp->link[i] == NULL)
                        {
                            temp->link[i] = pnode;
                            break;
                        }        
                        else//表示当前链域已经插入过结点了
                        {
                            if(i == DEGREE -1)
                            {
                                printf("The max degree of tht tree is %d.\n", DEGREE);
                                free(pnode);
                                return 0;
                            }
                            continue;
                        }
                            
                    }
                }
                break;
        }
        
    }while(done);
    
    return 1;
}

/*采用递归的方法实现, 每颗树只考虑根节点和子节点,简化问题*/
void showTree(NodePointer * ptree)
{
    int degree;
    int i;
    
    //树为空
    if(*ptree == NULL)
    {
        return;
    }
    
    printf("%c", (*ptree)->ch);
    //获取子树个数,如果子树个数为零就无需输出其它括号或者逗号信息
    //如果子树个数不为零,就把子树当成一个数来显示
    degree = getDegree(ptree);
    if(degree != 0)
    {
        for(i = 0; i < degree; i++)
        {
            if(i == 0)
                printf("(");
            else
                printf(",");
            showTree(&((*ptree)->link[i]));
        }
        printf(")");
    }    
}

int getDegree(const NodePointer *ptree)
{
    int i, count = 0;
    
    if(*ptree == NULL)
        return -1;
    for(i = 0; i< DEGREE; i++)
    {
        if((*ptree)->link[i] != NULL)
            count++;
    }
    return count;
}

/*销毁一个颗树,也需要遍历所有节点,也采用递归方式实现*/
void destoryTree(NodePointer * ptree)
{
    int degree;
    int i;
    
    if(*ptree == NULL)
    {
        return;
    }
    
    degree = getDegree(ptree);
    //如果是叶子结点,直接释放空间
    if(degree == 0)
    {
        #if DEBUG
        printf("[debug] free space %c @ %p\n", (*ptree)->ch, (void *)(*ptree));
        #endif
        free(*ptree);
        *ptree = NULL;//需要把指针置空,因为统计树的度时是根据非空指针来的
        return;
    }
    else
    {
        /*1. 释放子树*/
        for(i = 0; i < degree; i++)
        {
            destoryTree(&((*ptree)->link[i]));
            (*ptree)->link[i] == NULL;
        }
        /*2. 释放树根结点*/
        #if DEBUG
        printf("[debug] free space %c @ %p\n", (*ptree)->ch, (void *)(*ptree));
        #endif
        free(*ptree);
        *ptree = NULL;
    }
}

void copyTree(NodePointer * dstTree, const NodePointer * srtTree)
{
    NodePointer pnode;
    int degree, i;
    
    assert(*srtTree != NULL);
    pnode = (NodePointer)malloc(sizeof(Node));
    if(pnode == NULL)
    {
        printf("copyTree malloc error.\n");
        exit(1);
    }
    pnode->ch = (*srtTree)->ch;
    *dstTree = pnode;
    degree = getDegree(srtTree);
    if(degree == 0)
    {
        for(i = 0; i < degree; i++)
        {
            pnode->link[i] == NULL;
        }
        return;
    }    
    else
    {
        for(i = 0; i < degree; i++)
        {
            copyTree(&(*dstTree)->link[i], &(*srtTree)->link[i]);
        }
    }
}

int isEqual(const NodePointer *ptree1, const NodePointer * ptree2)
{
    int degree1, degree2;
    int i;
    int ret;
    
    assert(*ptree1 && *ptree2);
    if((*ptree1)->ch != (*ptree2)->ch)
    {
        return 0;
    }
    else
    {
        degree1 = getDegree(ptree1);
        degree2 = getDegree(ptree2);
        if(degree1 != degree2)
        {
            return 0;
        }
        
        if(degree1 == 0)
        {
            return 1;
        }
        else
        {
            for(i = 0; i < degree1; i++)
            {
                ret = isEqual(&((*ptree1)->link[i]), &((*ptree2)->link[i]));
                if(!ret)
                {
                    return 0;
                }    
            }

           return 1;//为真的出口处

        }
    }
}



//Stack.h


#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

typedef struct Element {
    void * elem;
} Element;

typedef struct Stack {
    Element * pelem;
    int top;
    int capacity;
}Stack;

Stack * initStack(void);
int isEmpty(const Stack * st);
int isFull(const Stack * st);
int addSpace(Stack * st);
int PUSH(Stack * st, Element e);
int POP(Stack * st, Element * e);
int destoryStack(Stack * st);
int getTop(Stack * st, Element *e);

//Stack.c

#include "Stack.h"
#define CAP 100

Stack * initStack(void)
{
    Stack * pst;
    pst = (Stack *)malloc(sizeof(Stack));
    if(NULL == pst)
    {
        return NULL;
    }
    pst->top = -1;
    pst->capacity = CAP;
    pst->pelem = (Element *)malloc(CAP * sizeof(Element));
    if(NULL == pst->pelem)
    {
        fprintf(stderr, "initStack failed.\n");
        return NULL;
    }
    
    return pst;
}

int isEmpty(const Stack * st)
{
    if (st->top == -1)
        return 1;
    return 0;
}

int isFull(const Stack * st)
{
    if(st->top == st->capacity -1)
        return 1;
    return 0;
}

int addSpace(Stack * st)
{
    if(NULL == st)
    {
        printf("addSpace error.\n");
        return 0;
    }
    st->pelem = (Element *)realloc(st->pelem, 2 * st->capacity * sizeof(Element));
    if(NULL == st->pelem)
    {
        return 0;
    }
    st->capacity = 2 * st->capacity;
    return 1;
}

int PUSH(Stack * st, Element e)
{
    if(++st->top == st->capacity)
    {
        addSpace(st);
    }
    st->pelem[st->top] = e;
    return 1;
}

int POP(Stack * st, Element * e)
{
    if(st->top == -1)
        return 0;
    memcpy(e, &st->pelem[st->top--], sizeof(Element));
    return 1;
}

int destoryStack(Stack * st)
{
    if(NULL == st)
        return 1;
    free(st->pelem);
    free(st);
    return 1;
}

int getTop(Stack * st, Element *e)
{
    if(NULL == st || NULL == e)
    {
        printf("getTop error\n");
        return 0;
    }
    *e = st->pelem[st->top];
    return 1;
}

测试以上函数:

//main.c

#include "Stack.h"
#include "tree.h"

// (A(B(E(K, L), F),C(G),D(H(M),I,J)))
// (a(b,d(e,f(g, h, i)), j))
// (a(b,d(e,f(g, h, i)), j(k)))
int main()
{
    NodePointer tree;
    NodePointer cptree;
    NodePointer newtree;
    int ret;
    
    printf("请输入广义表:\n");
    ret = getTree(&tree);
    if(!ret)
    {
        printf("getTree error.\n");
        exit(1);
    }
    printf("Output:\n");
    printf("(");
    showTree(&tree);
    printf(")\n");
    
    printf("copy tree: \n");
    copyTree(&cptree, &tree);
    printf("(");
    showTree(&cptree);
    printf(")\n");
    
    ret = isEqual(&tree, &cptree);
    if(ret)
    {
        printf("tree and cp tree is equaled.\n");
    }
    else
    {
        printf("tree and cp tree is not equaled.\n");
    }
    printf("请输入另外一个广义表: ");
    getTree(&newtree);
    ret = isEqual(&tree, &newtree);
    if(ret)
    {
        printf("tree and  new tree is equaled.\n");
    }
    else
    {
        printf("tree and new tree is not equaled.\n");
    }
    
    destoryTree(&tree);

   destoryTree(&cptree);


    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值