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);
}