head.h
#ifndef HEAD_H_INCLUDED
#define HEAD_H_INCLUDED
#include
#include
#include
#include
#include
using namespace std;//标准程序库的所有标识符都被定义在这个名为std的命名空间
typedef int TElemType;
typedef struct BinaryTree
{
TElemType data;
struct BinaryTree *Left;
struct BinaryTree *Right;
}BTree;
BTree* CreateBinaryTree();//创建二叉树
void PreOderTraverse1(BTree*T);//前序遍历
void InOderTravers1(BTree*T);//中序遍历
void PostOderTravers1(BTree*T);//后序遍历
void PreOderTraverse2(BTree*T);//非递归前序遍历
void InOderTravers2(BTree*T);//非递归中序遍历
void PostOderTravers2(BTree*T);//非递归后序遍历
void LeavelOrderTravers1(BTree*T);//用队列实现的层序遍历
void LeavelOrderTravers2(BTree*T);//用数组实现的层序遍历
void Copy(BTree*T,BTree*NT);//复制树
void DestoryTree(BTree*T);//销毁树
int Depth(BTree*T);//计算二叉树深度
int NodeCount(BTree*T);//计算节点个数
#endif // HEAD_H_INCLUDED
main.cpp
#include"head.h"
int main()
{
printf("************************************\n");
printf("请输入数字选择要执行的操作\n");
puts("1. 构造二叉树");
puts("2. 前序遍历二叉树");
puts("3. 中序遍历二叉树");
puts("4. 后续遍历二叉树");
puts("5. 非递归前序遍历二叉树");
puts("6. 非递归中序遍历二叉树");
puts("7. 非递归后序遍历二叉树");
puts("8. 队列实现的层序遍历二叉树");
puts("9. 数组实现的层序遍历二叉树");
puts("10. 复制二叉树");
puts("11. 计算二叉树深度");
puts("12. 计算二叉树结点个数");
puts("13. 销毁二叉树");
printf("\n********************************\n\n");
int a;
while(1)
{
puts("请选择要执行的操作\n");
scanf("%d",&a);
if(a==0) break;
switch(a)
{
case 1 :
BTree*T;
T=CreateBinaryTree();
break;
case 2 :
puts("前序遍历如下:");
PreOderTraverse1(T);
break;
case 3 :
puts("中序遍历如下:");
InOderTravers1(T);
break;
case 4 :
puts("后序遍历如下:");
PostOderTravers1(T);
break;
case 5 :
puts("前序非递归遍历如下:");
PreOderTraverse2(T);
break;
case 6 :
puts("中序非递归遍历如下:");
InOderTravers2(T);
break;
case 7 :
puts("后序非递归遍历如下:");
PostOderTravers2(T);
break;
case 8 :
puts("队列层序递归如下:");
LeavelOrderTravers1(T);
break;
case 9 :
puts("数组层序递归如下:");
LeavelOrderTravers2(T);
break;
case 10 :
BTree*NT;
Copy(T,NT);
break;
case 11 :
int c;
c=Depth(T);
printf("树的深度为%d",c);
break;
case 12 :
int a;
a=NodeCount(T);
printf("共有%d个节点",a);
break;
case 13 :
DestoryTree(T);
break;
}
}
printf("谢谢使用");
system("pause");
return 0;
}
operation.cpp
创建链表:
BTree* CreateBinaryTree()
{
BTree *p;
TElemType a;
printf("输入元素");
scanf("%d",&a);
if(a==0) //递归结束,建空树
{
p = NULL;
}
else
{
p = (BTree*)malloc(sizeof(BTree));
p->data = a; //先递后归
p->Left = CreateBinaryTree(); //递归创建左子树
p->Right = CreateBinaryTree(); //递归创建右子树
}
return p;
}
递归遍历部分:
void PreOderTraverse1(BTree*T)//前序遍历
{
if(T==NULL)
{
return;
}
printf("%d\t",T->data);
PreOderTraverse1(T->Left);
PreOderTraverse1(T->Right);
}
void InOderTravers1(BTree*T)//中序遍历
{
if(T==NULL)
{
return;
}
InOderTravers1(T->Left);
printf("%d\t",T->data);
InOderTravers1(T->Right);
}
void PostOderTravers1(BTree*T)//后序遍历
{
if(T==NULL)
{
return;
}
PostOderTravers1(T->Left);
PostOderTravers1(T->Right);
printf("%d\t",T->data);
}
非递归部分:
void PreOderTraverse2(BTree*T)//非递归前序遍历
{
if (T == NULL)
return;
BTree* p = T;
stack<BTree*>s;
while (!s.empty() || p)
{
//边遍历边打印,并存入栈中,以后需要借助这些根节点(上一个保存的节点)进入右子树
while (p)
{
printf("%d\t",p->data);
s.push(p);
p = p->Left;
}
//当p为空时,说明根和左子树都遍历完了,该进入右子树了
if (!s.empty())
{
p = s.top();
s.pop();
p = p->Right;
}
}
}
void InOderTravers2(BTree*T)//非递归中序遍历
{
//空树
if (T == NULL)
return;
//树非空
BTree*p = T;
stack<BTree*> s;
while (!s.empty() || p)
{
//一直遍历到左子树最下边,边遍历边保存根节点到栈中
while (p)
{
s.push(p);
p = p->Left;
}
//当p为空时,说明已经到达左子树最下边,这时需要出栈了
if (!s.empty())
{
p = s.top();
s.pop();
printf("%d\t",p->data);
//进入右子树,开始新的一轮左子树遍历(这是递归的自我实现)
p = p->Right;
}
}
}
void PostOderTravers2(BTree*T)//后序非递归遍历
{
/*难点在于需要判断上次访问的节点是位于
左子树,还是右子树。若是位于左子树,则需跳过
根节点,先进入右子树,再回头访问根节点;
若是位于右子树,则直接访问根节点。*/
if (T == NULL)
return;
stack<BTree*> s;
//pN:当前访问节点,pL:上次访问节点
BTree*pN, *pL;
pN = T;
pL = NULL;
//先把pN移动到左子树最下边
while (pN)
{
s.push(pN);
pN = pN->Left;
}
while (!s.empty())
{
//走到这里,pN都是空,并已经遍历到左子树底端(看成扩充二叉树,则空,亦是某棵树的左孩子)
pN = s.top();
s.pop();
//一个根节点被访问的前提是:无右子树或右子树已被访问过
if (pN->Right== NULL || pN->Right == pL)
{
printf("%d\t",pN->data);
//修改最近被访问的节点
pL = pN;
}
/*这里的else语句可换成带条件的else if:
else if (pCur->lchild == pLastVisit)//若左子树刚被访问过,则需先进入右子树(根节点需再次入栈)
因为:上面的条件没通过就一定是下面的条件满足。
*/
else
{
//根节点再次入栈
s.push(pN);
//进入右子树,且可肯定右子树一定不为空
pN= pN->Right;
while (pN)
{
s.push(pN);
pN = pN->Left;
}
}
}
}
层序的数组与队的实现:
void LeavelOrderTravers1(BTree*T) //层序遍历队列实现
{
queue <BTree*> q;
if (T!=NULL)
{
q.push(T); //根节点进队列
}
while (q.empty() == false) //队列不为空判断
{
printf("%d\t",q.front()->data);
if (q.front()->Left != NULL) //如果有左孩子,left入队列
{
q.push(q.front()->Left);
}
if (q.front()->Right!= NULL) //如果有右孩子,right入队列
{
q.push(q.front()->Right);
}
q.pop(); //已经遍历过的节点出队列
}
}
void LeavelOrderTravers2(BTree*T)//层序遍历数组实现
{
BTree*temp[100]; //创建BTree指针类型的指针数组
int in = 0;
int out = 0; //可以将in和out看成指向数组位置的两个指针
temp[in++] = T; //先保存二叉树根节点
while (in > out)
{
if (temp[out])
{
printf("%d\t",temp[out]->data);
temp[in++] = temp[out]->Left;
temp[in++] = temp[out]->Right;
}
out++;
}
}
其余功能:
void Copy(BTree*T,BTree*NT)//复制树
{ //error: expected unqualified-id before '{'token
//函数名后面多加了个分号 void Copy();
if(T==NULL)
{
NT=NULL;
return;
}
else
{
NT = (BTree*)malloc(sizeof(BTree));
NT->data=T->data;
Copy(T->Left,NT->Left);
Copy(T->Right,NT->Right);
}
}
void DestoryTree(BTree*T)//销毁树
{
if(T!=NULL)
{
DestoryTree(T->Left);
DestoryTree(T->Right);
delete T;
}
else
printf("销毁完毕");
}
int Depth(BTree*T)//计算二叉树深度
{
int m,n;
if(T==NULL)
return 0;
else
{
m=Depth(T->Left);
n=Depth(T->Right);
if(m>n) return(m+1);
else
return(n+1);
}
}
int NodeCount(BTree*T)//计算节点个数
{
if(T==NULL)
{
return 0;
}
return NodeCount(T->Left)+NodeCount(T->Right)+1;
}