数据结构二叉树的基本操作c语言版二叉链表
```java
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXSIZE 100
//定义操作符栈 (链式存储)
typedef struct OptrNode
{ char optr;//节点数据域,存放操作符
int test;
struct OptrNode *next;//指针域
}OptrNode,*OpStackLink;
//定义二叉树链表
typedef struct BiTNode{
char optr;//数据域,如果是分支结点存运算符,如果是叶子结点存运算数
float data;//运算数
int flag;//标志位
struct BiTNode *lchild,*rchild;//左右孩子指针
}BiTNode,*BiTree;
typedef struct BiTreeLink
{
BiTree Tree;
int count;
} BiTreeNode,*BiTreeLink;
//定义树根结点栈(链式存储)
typedef struct ExptNode
{ BiTNode *BiRoot;
struct ExptNode *next; //指针域
}ExptNode,*BiRootStackLink;
//初始化操作符栈
void InitOptrStack(OpStackLink *optrLink)
{
*optrLink=NULL;//初始化为空栈
}
//初始化二叉树根结点栈
void InitExptStack(BiRootStackLink *exptLink)
{
*exptLink = NULL;//初始化为空栈
}
//创建只有根结点的二叉树链表
void CreatBiTreeList(BiTree *biTree,char optr,float data,int flag)
{
//结点赋值
(*biTree)->optr=optr ;
(*biTree)->data= data ;
(*biTree)->flag= flag ;
(*biTree)->lchild=NULL; // 左子树为空
(*biTree)->rchild=NULL; //右子树为空
printf("新创建的树:%f\n",(*biTree)->data);
}
//为二叉树添加左右子树(多态应用)
void creatBiTreeList(BiTree *biTree,BiTree lchild,BiTree rchild,char optr,float data,int flag)
{
(*biTree)->optr=optr ;
(*biTree)->data= data ;
(*biTree)->flag= flag ;
(*biTree)->lchild = lchild;
(*biTree)->rchild = rchild;
}
/*栈的相关操作函数=================================================================*/
//运算符栈入栈操作
void PushOpStack(OpStackLink *optrStack,char data)
{
//分配结点空间
OpStackLink p = (OptrNode*)malloc(sizeof(OptrNode));
if(p)//如果分配成功
{
p->test=100;
//strcmp(p->optr,data);
p->optr=data;
p->next = *optrStack; //将新结点插入栈顶
*optrStack=p; //修改栈顶指针为p
}
}
//二叉树根结点栈入栈操作
void PushBiRootStack(BiRootStackLink *exptStack,BiTree biTree)
{
//分配结点空间
BiRootStackLink p = (BiRootStackLink)malloc(sizeof(ExptNode));
if(p)//如果分配成功
{
//printf("当前入栈的树根原来是:%s\n",biTree->data);
p->BiRoot=biTree; //将树的根结点赋值给新结点
p->next=*exptStack;//将新结点插入栈顶
//printf("当前入栈的树根是:%s\n",p->BiRoot->data);
*exptStack=p; //修改栈顶指针为p
}
}
//算符栈出栈操作
char PopOpStack(OpStackLink *optrStack,char data)
{
//判断栈是否为空
char ch;
if(*optrStack!=NULL)
{
data = (*optrStack)->optr; //取栈顶元素
ch = (*optrStack)->optr;
//printf("%c",data);
//用结点p暂存栈顶结点
OpStackLink p = (OpStackLink)malloc(sizeof(OptrNode));
p = *optrStack;
*optrStack= (*optrStack)->next;//修改栈顶指针
free(p) ;//释放原栈顶元素空间
}
return ch;
}
//二叉树根结点栈出栈操作
void PopBiRootStack(BiRootStackLink *exptStack,BiTree *biTree)
{
//判断栈是否为空
if(*exptStack!=NULL)
{ *biTree = (*exptStack)->BiRoot;
BiRootStackLink p = (BiRootStackLink)malloc(sizeof(ExptNode));
p = *exptStack;
*exptStack=(*exptStack)->next;
//
printf("222当前弹出的树根是:%c\n",(*biTree)->optr);
printf("222当前弹出的树根是:%f\n",(*biTree)->data);
free(p);
}
}
//如果操作符栈和树根栈不为空,则弹出组合成最终的二叉树
void GetBiTree(BiTree *b,OpStackLink *p,BiRootStackLink *s)
{
int i=0;
while((*p)->optr!='#')
{
printf("OPTR");
char data;
BiTree rchild=(BiTree)malloc(sizeof(BiTNode)) ;
BiTree lchild=(BiTree)malloc(sizeof(BiTNode)) ;
data = PopOpStack(p,data) ;
PopBiRootStack(s,&rchild); //第一次弹出的为右子树
PopBiRootStack(s,&lchild); //第二次弹出的为左子树
i++;
BiTree biTree_Temp = (BiTree)malloc(sizeof(BiTNode)) ;
creatBiTreeList(&biTree_Temp,lchild,rchild,data,0,0) ;
*b= biTree_Temp;
}
}
//遍历二叉树得到运算结果
void TravelCompute(BiTree b,float *tValue)
{
float lvalue=0.0,rvalue=0.0;
if(b!=NULL)
{
if(b->lchild==NULL&&b->rchild==NULL)
{
*tValue=b->data;
}
else
{
TravelCompute(b->lchild,&lvalue) ;
TravelCompute(b->rchild,&rvalue) ;
*tValue=lvalue+rvalue;
}
}
}
//输入算术表达式
void InputExpression(BiTree *biTree)
{
char express[MAXSIZE],temp[MAXSIZE] ; //辅助字符数组,用来存储连续的数字
BiRootStackLink rootStack= (BiRootStackLink)malloc(sizeof(ExptNode)) ;//存树根结点的栈
OpStackLink opStack = (OpStackLink)malloc(sizeof(OptrNode)) ;//存放运算符的栈
InitOptrStack(&opStack);
InitExptStack(&rootStack);
gets(express) ;
//先压入'#'作为出栈完成标志
PushOpStack(&opStack,'#');
int i;
for(i=0;express[i]!='\0';i++)
{
memset(temp,'\0',sizeof(temp)); //将上一次匹配的数字清空,重新匹配
//如果是数字
if(express[i]>='0'&&express[i]<='9')
{
//构建只有根结点的树,并压入expt栈中
BiTree biTree_Temp = (BiTree)malloc(sizeof(BiTNode)) ;
//biTree_Temp = NULL;
//将连续的数字存放在temp中
temp[0]=express[i];
//继续判断是否为数字
int j,ti=1;
for(j=i+1;express[j]!='\0';j++)
{
if(express[j]>='0'&&express[j]<='9')
{
temp[ti]=express[j];//存入temp
ti++;
}
else
{
break;//如果为非数字退出循环
}
i=j;//从j位置开始匹配
}
float num=atof(temp) ;
CreatBiTreeList(&biTree_Temp,'#',num,1);
printf("当前构造的树的根为:%f\n",biTree_Temp->data);
PushBiRootStack(&rootStack,biTree_Temp);
}
//如果式运算符 ,根据运算符优先级进行操作
else if(express[i]=='+')
{
switch(express[i])
{
//与栈顶元素进行比较
case '+' :
if(opStack->optr!='+'&&opStack->optr!='-'&&opStack->optr!='*'&&opStack->optr!='/') //优先级高于栈顶元素,入栈
{
PushOpStack(&opStack,'+');
}
else
{
//如果优先级低于栈顶元素,弹出栈顶元素 ,同时需从二叉树树根栈弹出两个结点,用于构造新的二叉树
char data;
data = PopOpStack(&opStack,data) ;
printf("当前弹出的是:%c\n",data);
//printf("当前弹出的是:%s\n",dataStr[0]);
//弹出树根栈的顶部两个元素
BiTree lchild=(BiTree)malloc(sizeof(BiTNode)) ;
BiTree rchild=(BiTree)malloc(sizeof(BiTNode)) ;
BiTree biTree_Temp1 = (BiTree)malloc(sizeof(BiTNode)) ;
PopBiRootStack(&rootStack,&rchild) ; //第一次弹出的为右子树
PopBiRootStack(&rootStack,&lchild) ; //第二次弹出的为左子树
printf("弹出的左子树为:%f",lchild->data) ;
printf("弹出的右子树为:%f",rchild->data) ;
//构造新树
creatBiTreeList(&biTree_Temp1,lchild,rchild,data,0,0) ;
//将新树根结点压入expt栈
PushBiRootStack(&rootStack,biTree_Temp1);
//将'+'入OPTR栈
PushOpStack(&opStack,'+');
}
break;
}
}
}
GetBiTree(biTree,&opStack,&rootStack);
}
int main()
{
BiTree biTree;
biTree = (BiTree)malloc(sizeof(BiTNode));
//CreatBiTreeList(biTree,"+"); //传入字符串
InputExpression(&biTree);
printf("二叉树根的值为:%c\n",biTree->optr);
printf("二叉树左子树的值为:%c\n",biTree->lchild->optr);
printf("二叉树右子树的值为:%f\n",biTree->rchild->data);
printf("二叉树右子树的值为:%c\n",biTree->rchild->optr);
float sum=0.0;
TravelCompute(biTree,&sum);
printf("计算结果为:%.2f",sum);
return 0;
}