以下是一些基础操作:
#include "stdio.h"
#include "stdlib.h"
#include
#define N 30
//定义二叉树的节点结构
typedef struct node
{
char data;
struct node *left,*right,*pa;
}BT;
BT *createbt(char *pre,int *k);//根据先序创建二叉树
BT *createbt2(char *pre,char *in,int k);//根据先序,中序创建二叉树
void showbt(BT *T);//以括号的形式显示二叉树
void preorder(BT *T);//先序遍历二叉树(递归)
void preorder2(BT *T);//先序遍历(非递归)
void inorder(BT *T);//中序遍历二叉树(递归)
void inorder2(BT *T);//中序遍历二叉树 (非递归)
void postorder(BT *T);//后序遍历二叉树(递归)
void postorder2(BT *T);//后续遍历二叉树(非递归)
void layer(BT *T);//层次遍历(非递归)
BT *delbt(BT *T);//销毁二叉树
void getpa(BT *T);//给父亲节点赋值
void getpa2(BT *T)//为二叉树的每个节点的pa指针赋值(非递归算法)
void showpa(BT *T);//遍历显示父节点
void countleaf(BT*T,int &count);//统计叶子节点的个数
int countlayer(BT*T);//统计树的层数
BT *gettreenode(char,BT*,BT*,BT*);//得到一个树的节点
BT *copytree(BT *);//复制树
int main()
{
char pre[]="ABD G CE F ";//先序序列,空格对应的是NULL
BT *T=NULL;//
int k=0;
//T=createbt(pre,&k);
char pre2[]="ABDGCEF";
char in[]="DGBAECF";
T=createbt2(pre2,in,strlen(pre2));
if(!T)
printf("树为空\n");
else
showbt(T);
printf("\n\n");
printf("\n先序遍历:\n");
preorder2(T);
printf("\n中序遍历:\n");
inorder2(T);
printf("\n后序遍历:\n");
postorder2(T);
printf("\n层次遍历:\n");
layer(T);
int count=0;
countleaf(T,count);
printf("\n叶子个数:%d\n",count);
printf("\n树的层数: %d\n",countlayer(T));
BT *newT=copytree(T);
printf("\nNewtree!!!\n");
if(!newT)
printf("树为空\n");
else
showbt(newT);
printf("\n\n");
printf("\n先序遍历:\n");
preorder2(newT);
printf("\n中序遍历:\n");
inorder2(newT);
printf("\n后序遍历:\n");
postorder2(newT);
printf("\n层次遍历:\n");
layer(newT);
count=0;
countleaf(newT,count);
printf("\n叶子个数:%d\n",count);
printf("\n树的层数: %d\n",countlayer(newT));
T=delbt(T);
newT=delbt(newT);
return 0;
}
BT *createbt(char *pre,int *k)
//这里用int*是为了保证进行递归时先序数组会一直向下读取,当左子节点完成初始化后读取的是右子节点
{ BT *A;
//注意:两种情况都要有返回值 (k对应的值所在节点的指针)
if (pre[*k]!=' ')//根节点非空 ,表示该根节点存在
{
A=(BT *)malloc(sizeof(BT));//分配空间
A->data=pre[*k];//赋值
(*k)++;//读取左子节点
A->left=createbt(pre,k);//以左子节点作为新的根初始化
(*k)++;//读取右子节点
A->right=createbt(pre,k); //以右子节点作为新的根初始化
return A;
}
else return NULL;
}
BT *createbt2(char *pre,char *in,int k)//根据先序,中序创建二叉树
//pre指向根节点,in为中序遍历得到的列表,k为中序序列当前根节点左/右侧的点个数
{
BT *T;
int i,j;
if (k<=0) //如果该点下一层左或右侧没有子节点,则将该节点的子节点赋为NULL
return NULL;
else
{
T=(BT *)malloc(sizeof(BT));
T->data=pre[0];
for(i=0;in[i]!=pre[0];i++);
//每次递归传入新的根节点值在先序表里面的指针,新的搜索起点,集合元素个数
T->left=createbt2(pre+1,in,i);
T->right=createbt2(pre+i+1,in+i+1,k-i-1);
return T;
}
}
void showbt(BT *T)//以括号的形式显示二叉树
{
if (T)//该节点非空 ,空的话执行空操作
{
printf("%c",T->data);//输出该点的值
if(T->left||T->right)//若该点有子节点
{
printf("(");
showbt(T->left);//以左子节点作为新的根节点进行输出,若左子节点为空,那么将不会有任何输出
printf(",");
showbt(T->right);//以右子节点作为新的根节点进行输出。。。。。。
printf(")");
}
}
}
//--------------遍历递归算法:虽然简单,但要深刻理解访问顺序------------void preorder(BT *T)//先序遍历二叉树(递归)
{
if(T)
{
printf("%c ",T->data);
preorder(T->left);
preorder(T->right);
}
}
void inorder(BT *T)//中序遍历二叉树(递归)
{
if(T)
{
inorder(T->left);
printf("%c ",T->data);
inorder(T->right);
}
}
void postorder(BT *T)//后序遍历二叉树(递归)
{
if(T)
{
postorder(T->left);
postorder(T->right);
printf("%c ",T->data);
}
}
BT *delbt(BT *T)//销毁二叉树
{ //后序遍历,先销毁左右子节点,再销毁根节点
if(T)
{
delbt(T->left);
delbt(T->right);
free(T);
return NULL;
}
else return NULL;
}
void getpa(BT *T)//给父亲节点赋值--后序遍历
{
if(T)
{
getpa(T->left);
getpa(T->right);
if(T->left) T->left->pa=T;
if(T->right) T->right->pa=T;
T->pa=NULL;
}
}
void showpa(BT *T)//显示父节点
{
if (T)
{
if(T->pa) printf("%c father is %c\n",T->data,T->pa->data);
else printf("%c father is NULL\n",T->data);
showpa(T->left);
showpa(T->right);
}
}
void preorder2(BT *T)//先序遍历非递归算法
{
BT *t[N];//定义栈,指针数组,可以存放指向结点的指针
BT *p;//指针p用来做遍历-
int top=0;//栈顶
t[0]=T;//初始将根节点入栈
while(top>=0)//只要栈非空
{
p=t[top];//
top--;//弹栈
printf("%c ",p->data);//输出被弹出的节点数值
if(p->right)//当前结点如果有右孩子
{
top++;//
t[top]=p->right;//右孩子压栈
}
if(p->left)//当前结点如果有左孩子
{
top++;//
t[top]=p->left;//左孩子压栈
}
}
printf("\n");
}
void inorder2(BT *T)//中序遍历二叉树 (非递归)
{
BT *t[N],*p=T;//定义栈,指针数组,可以存放指向结点的指针,指针p用来做遍历,p初始指向根节点
int top=-1;//栈顶,初始栈为空
while(top>=0||p)//只要栈非空或者指针p为真
{
while(p)//只要p为真
{
top++;//
t[top]=p;//将p指向的节点压栈
p=p->left;//继续向左走
}
p=t[top];//
top--;//弹栈
printf("%c ",p->data);//输出弹出的节点数值
p=p->right;//指针p指向当前弹出节点的右,如果有右,继续按照如上的步骤找到最左,然后弹栈
//输出....;如果没有右,则继续弹栈
}
printf("\n");
}
void postorder2(BT *T)//后续遍历二叉树(非递归)
{
BT *t[N];//定义栈,指针数组,可以存放指向结点的指针
BT *p=T,*b;//指针p用来做遍历,初始指向根节点;指针b用来存放刚刚访问过的节点
int top=-1;//初始栈为空
do//注意循环的样式
{
while(p)//只要指针p为真
{
top++;//
t[top]=p;//将指针p指向的节点压栈
p=p->left;//继续向左走
}
b=NULL;//给b赋起始值
while(top>=0)//如果当前栈非空
{
p=t[top];//观察栈顶,判断栈顶元素的右孩子有没有被访问过
if(p->right==b)//如果刚访问过的节点就是栈顶的右
{
p=t[top];//说明当前的栈顶元素可以弹出(弹出意味着可以访问)
top--;//
printf("%c ",p->data);//输出该结点数值
b=p;//将刚刚访问的节点指向赋值给b
}
else//如果刚访问过的节点不是栈顶的右
{
p=p->right;//不能弹栈,要进入栈顶的右分支,
break;//并从当前的循环中退出,回到第一层的循环体内,继续上述的操作
}
}
}while(top>=0);//只要栈非空
printf("\n");
}
void layer(BT *T)//层次遍历(非递归)
{
BT *t[N],*p;
int top=-1,rear=-1;//初始化空队列
if(T) t[++rear]=T;//根节点入队
while(top!=rear)//当队列非空时
{
p=t[top+1];//根节点开始向下遍历
printf("%c ",p->data);//输出根节点
if(p->left) t[++rear]=p->left;//左孩子入队
if(p->right) t[++rear]=p->right;//右孩子入队
top++;//根节点出队,进行其右侧相邻兄弟节点或下一个层次的最左侧节点的遍历
}
printf("\n");
}
void countleaf(BT *T,int &count)//统计叶子节点的个数(先序遍历)
{
if(T)
{
if(!(T->left||T->right)) count++;
countleaf(T->left,count);
countleaf(T->right,count);
}
}
//这里任意遍历方法都可以,本质就是简单地遍历所有节点并判断它是不是叶子
int countlayer(BT *T)//统计树的层数 (先序遍历)
{
if (!T) return 0;
else return 1+(countlayer(T->left)>countlayer(T->right)?countlayer(T->left):countlayer(T->right));//注意要加一
}
BT *gettreenode(char data,BT *left,BT *right,BT *pa)//得到一个树的节点
{
BT *node=(BT*)malloc(sizeof(BT));
node->data=data;
node->left=left;
node->right=right;
node->pa=pa;
return node;
}
BT *copytree(BT *T)//复制树
{ BT *L,*R;
if(!T) return NULL;
else
{
L=copytree(T->left);
R=copytree(T->right);
}
return gettreenode(T->data,L,R,T->pa); //获得左右子树再与根节点链接
}
void getpa2(BT *T)//为二叉树的每个节点的pa指针赋值(非递归算法)——————层次遍历
{
BT *t[N],*p;
int front=-1,rear=-1;//初始化队列
t[++rear]=T;//根节点入队
T->pa=NULL;//根节点pa赋值为NULL
while(rear!=front)
{
p=t[front+1];
if(p->left)
{
t[++rear]=p->left;
p->left->pa=p;
}
if(p->right)
{
t[++rear]=p->right;
p->right->pa=p;
}
front++;
}
}
先缀表达式建树
#include
#include
#include
#include
using namespace std;
typedef struct node
{
char data;
struct node *left,*right;
}BT;
BT *createtree(char*,int*);
int isoperator(char);
int isnum(char);
void showbt(BT*T);
BT *delbt(BT *T);
int main()
{
char temp[]="-*+abc/de";
int k=0;
int *p=&k;
BT *T=createtree(temp,p);
showbt(T);
delbt(T);
return 0;
}
BT *createtree(char *expression,int *k)
{
if(isoperator(expression[*k]))
{
BT *T=(BT*)malloc(sizeof(BT));
T->data=expression[*k];
(*k)++;
T->left=createtree(expression,k);
(*k)++;
T->right=createtree(expression,k);
return T;
}
else
{
BT *T=(BT*)malloc(sizeof(BT));
T->data=expression[*k];
T->left=NULL;
T->right=NULL;
return T;
}
}
int isoperator(char c)
{
if(c==43||c==45||c==42||c==47) return 1;
else return 0;
}
int isnum(char c)
{
if((c>='a'&&c<='z')||(c>='A'&&c<='Z'))
return 1;
else return 0;
}
void showbt(BT *T)//以括号的形式显示二叉树
{
if (T)//该节点非空
{ //输出该点的值
printf("%c ",T->data);
if(T->left||T->right)//若该点有子节点
{
printf("(");
showbt(T->left);//以左子节点作为新的根节点进行输出,若左子节点为空,那么将不会有任何输出
printf(",");
showbt(T->right);//以右子节点作为新的根节点进行输出。。。。。。
printf(")");
}
}
}
BT *delbt(BT *T)//销毁二叉树
{ //后序遍历,先销毁左右子节点,再销毁根节点
if(T)
{
delbt(T->left);
delbt(T->right);
free(T);
return NULL;
}
else return NULL;
}