树和二叉树
//树的表示
//儿子-兄弟表示法
// Element-FirstChild-NextSibling
//n个结点,2n个指针域,n-1个指针域非空
//向右旋转45°->二叉树
//Element Left Right
//二叉树
//链表存储
typedef struct TreeNode *BinTree;
typedef BinTree Position
struct TreeNode{
ElementType Data;
BinTree Left;
BinTree Right;
};
//二叉树的遍历——递归
//1.先序遍历
void PreOrderTraversal(BinTree BT)
{
if(BT){
printf("%d",BT->Data);//如果非空,先访问根结点
PreOrderTraversal(BT->Left);//对左子树递归
PreOrderTraversal(BT->Right);//对右子树递归
}
}
//2.中序遍历
void PreOrderTraversal(BinTree BT)
{
if(BT){
PreOrderTraversal(BT->Left);//对左子树递归
printf("%d",BT->Data);
PreOrderTraversal(BT->Right);//对右子树递归
}
}
//3.后序遍历
void PreOrderTraversal(BinTree BT)
{
if(BT){
PreOrderTraversal(BT->Left);//对左子树递归
PreOrderTraversal(BT->Right);//对右子树递归
printf("%d",BT->Data);
}
}
//先序,中序和后序遍历过程:遍历过程中经过结点的路线
//一样,只是访问各结点的时机不同 ->此处有个黑科技
//二叉树的非递归遍历
//中序遍历非递归遍历算法
//基本思路:使用堆栈
//遇到一个结点,把它压栈,并去遍历它的左子树
//当左子树遍历结束后,从栈顶弹出这个结点并访问它
//然后按其右指针在取中序遍历该节点的右子树
void InOrderTraversal(BinTree BT)
{
BinTree T=BT;
Stack S=CreatStack(MaxSize);//创建并初始化堆栈S
while(T||!IsEmpty(S)){//树或堆栈不空
while(T){//树不空 一直向左并将沿途结点压入堆栈
push(S,T);//(1)
T=T->Left;
}
if(!IsEmpty(S)){//堆栈不空
T=Pop(S);//结点弹出堆栈 (2)
printf("%5d",T->Data);//访问打印结点
T=t->Right;//转向右子树
}
}
}
//先序遍历 把printf语句调整到(1)处
void PreOrderTraversal(BinTree BT)
{
BinTree T=BT;
Stack S=CreatStack(MaxSize);//创建并初始化堆栈S
while(T||!IsEmpty(S)){//树或堆栈不空
while(T){//树不空 一直向左并将沿途结点压入堆栈
push(S,T);//(1)
printf("%5d",T->Data);//访问打印结点
T=T->Left;
}
if(!IsEmpty(S)){//堆栈不空
T=Pop(S);//结点弹出堆栈 (2)
T=t->Right;//转向右子树
}
}
}
//后序遍历怎么实现?
//层序遍历:队列实现
//基本过程:先根结点入队,然后
//1.从队列中取出一个元素
//2.访问该元素所指结点
//3.若该元素所指结点的左、右孩子结点非空,
//则将其左、右孩子的指针顺序入队
void LevelOrderTraversal(BinTree BT)
{
Queue Q;
BinTree T;
if(!BT)//若是空树直接返回
return;
Q=CreateQueue(MaxSize);//创建并初始化队列Q
AddQ(Q,BT);
while(!IsEmptyQ(Q)){
T=DeleteQ(Q);
printf("%d\n",T->Data);//访问取出队列的结点
if(T->Left)
AddQ(Q,T->Left);
if(T->Right)
AddQ(Q,T->Right);
}
}
//遍历二叉树的应用:输出二叉树中的叶子结点
//在二叉树遍历算法中增加检测结点的“左右子树是否都为空”
//改造先序遍历
void PreOrderPrintLeaves(BinTree BT)
{
if(BT){
if(!BT->Left&&!BT->Right)
printf("%d",BT->Data);
PreOrderPrintLeaves(BT->Left);
PreOrderPrintLeaves(BT->Right);
}
}
//求二叉树的高度
//Height=Max{Hl,Hr}+1
//改造后序遍历
int PostOrderGetHeight(BinTree BT)
{
int HL,HR,MaxH;
if(BT){
HL=PostOrderGetHeight(BT->Left);//求左子树的深度
HR=PostOrderGetHeight(BT->Right);//求右子树的深度
MaxH=(HL>HR)?HL:HR;//取左右子树较大的深度
return(MaxH+1);//返回树的深度
}
else
return 0;//空树深度为0
}
//二元运算表达式树及其遍历
//先序遍历得到前缀表达式
//中序遍历得到中缀表达式/中缀表达式会受到运算符优先级的影响 ->加括号解决
//后序遍历得到后序表达式
//由两种遍历序列确定二叉树:必须要有中序遍历才可以