#if 1
#include <stdio.h>
#include <stdbool.h>
#include <malloc.h>
#include <math.h>
//树形定义
typedef struct BitNode
{
char data;
struct BiTree*lchild;//左子节点
struct BiTree*rchild;//右子节点
}BiTree;
//单链表节点定义
typedef struct LinkNode
{
int data;
struct LinkNode*next;
}SLink,LinkList,LinkNode;
/***909 - 1997***/
/**递归判断两颗二叉树是否相等**/
/*******************************
算法思想:采用先序遍历的方式,首先判断两棵树的根节点是否相同,如果相同,
则递归判断左右子树,左右子树都相同返回ture,否则返回false;
******************************/
bool IsSameTree(BiTree* A,BiTree* B)
{
//两节点点同空,一般指比较到叶子节点的左右子节点
if (A==NULL&&B==NULL)
{
return true;
}
//当前比较节点其中有一个为空
if (A == NULL || B == NULL)
{
return false;
}
//同位置节点值不相同
if (A->data!=B->data)
{
return false;
}
//递归比较左右子树
return IsSameTree(A->lchild, B->lchild) && IsSameTree(A->rchild, B->rchild);
}
/**递归复制二叉树**/
/*******************************
算法思想:采用先序遍历的方式,若节点为空返回NULL,
否则创建新节点复制当前节点值,然后递归复制创建左右子树
******************************/
BiTree *CopyTree(BiTree* T)
{
if (T == NULL)//节点为空返回空
{
return NULL;
}
BiTree *root = (BiTree*)malloc(sizeof(BiTree));
root->data = T->data;//复制节点值
//递归复制左子树
root->lchild = CopyTree(T->lchild);
//递归复制右子树
root->rchild = CopyTree(T->rchild);
//返回复制结果
return root;
}
/***909 - 1998***/
/**根据前序中序序列创建一棵二叉树**/
/*******************************
算法思想:由前序以及中序序列可以唯一的确定一棵二叉树;
首先根据前序序列确定根节点,然后根据根节点在中序序列中的
位置划分出左右子树包含的节点,再根据前序序列中的节点
确定已经划分出的左右子树各包含节点的根节点,如此反复
即可创建一棵二叉树。
******************************/
BiTree *PreOrderBuildTree(char preorder[], char inorder[], int size)
{
if (0 == size)//子序为空
return NULL;
BiTree * root = (BiTree*)malloc(sizeof(BiTree));//创建根节点
root->data = preorder[0];//传递节点值
//查找根节点在中序序列中的下标,用于计算左右子树大小
int i = 0;
for (i = 0; root->data != inorder[i]; i++);
//递归创建左子树
root->lchild = PreOrderBuildTree(preorder + 1, inorder, i);//从前序下一个节点开始
//递归创建右子树
root->rchild = PreOrderBuildTree(preorder + i + 1, inorder + i + 1, size - i - 1);
//返回创建结果
return root;
}
/**根据后序中序序列创建一棵二叉树**/
/*******************************
算法思想:类似前序,只是根节点参考变为后序序列
******************************/
BiTree *PostOrderBuildTree(char postorder[], char inorder[], int size)
{
if (0 == size)//子序为空
return NULL;
BiTree * root = (BiTree*)malloc(sizeof(BiTree));//创建根节点
root->data = postorder[size-1];//传递节点值,后序根在最后
//查找根节点在中序序列中的下标,用于计算左右子树大小
int i = 0;
for (i = 0; root->data != inorder[i]; i++);
//递归创建左子树
root->lchild = PostOrderBuildTree(postorder, inorder, i);//左子树节点长度
//递归创建右子树
//传递右子树节点位置时,注意刨除中序序列中根节点的个数(+1)
//最后size-左子树长度-根数(-1)
root->rchild = PostOrderBuildTree(postorder + i, inorder + i + 1, size - i-1);
//返回创建结果
return root;
}
/***909 - 1999***/
/**判别B是否是A的子序列,链表**/
/*******************************
算法思想:首先从A B的头结点开始比较,若A B节点值相等,指针后移,如出现不一致情况时,
B链表回归起点,A从下一个节点开始,如此循环,直到A到尾B不到到尾(非子序列),
或者B到尾(为子序列)
******************************/
bool IsSubSequence(SLink *A,SLink *B)
{
SLink *p = A;//遍历指针
SLink *q = B;
SLink *pre = p;//记录A序列的当前遍历位置
while (p != NULL&&q != NULL)
{
if (p->data == q->data)//数值相同指针后移
{
p = p->next;
q = q->next;
}
else//数值不同,比较 A的下一个节点是否含有B子序
{
pre = pre->next;
p = pre;
q = B;
}
}
if (q == NULL)//若q指针为空 说明B序列比较完成,B为A的子序
{
return true;
}
else
{
return false;
}
}
/**判别二叉树是否是平衡二叉树**/
/*******************************
算法思想:用high表示树的高度。借助后序遍历递归算法。
1)若根为空,high = 0,树平衡返回true;
2)若仅有根节点,high = 1,树平衡返回true;
3)否则,对左右子树进行递归遍历,返回左右子树的高度,T的高度为最高子树+1,
若左右子树高度相差大于1,返回false ;若左右子树相差小于等于1,且左右子树均平衡,返回true,
否则返回false。
扩展:求树的高度基本类似思路
******************************/
bool JudgeAVL(BiTree *T, int* high)//C语言没有引用 这里采用指针
{
//初始定义左右子树 高度、平衡标记均为0
int high_left = 0,high_right = 0;
if (T == NULL)//空节点
{
*high = 0;
return true;
}
else if (T->lchild == NULL &&T->rchild == NULL)//仅有根节点
{
*high = 1;
return true;
}
else
{
bool blance_left = JudgeAVL(T->lchild, &high_left);//递归判断左子树
bool blance_right = JudgeAVL(T->rchild, &high_right);//递归判断右子树
*high = (high_left > high_right ? high_left : high_right) + 1;//获取树高
if (abs(high_left - high_right) < 2)//若左右子树高度相差不超过2 则看左右子树是否平衡
{
return blance_left&&blance_right;
}
else//左右子树不平衡直接返回false
{
return false;
}
}
}
/**将二叉树叶子结点链接成双链表**/
/*******************************
算法思想:中序递归遍历二叉树,将各个叶子节点链接为带头节点的双链表
这个可以扩展为 链接叶子节点的单链表,实现方式基本相同
(带头声明为全局变量较为方便)
******************************/
BiTree*Leaf_head = NULL;//头结点
BiTree*Leaf_pre = NULL;//哨兵指针
void LinkLeaf(BiTree *T)
{
if (T)
{
LinkLeaf(T->lchild);
if ((T->lchild == NULL) && (T->rchild==NULL) )//叶子节点
{
if (Leaf_head == NULL)
{
Leaf_head = (BiTree*)malloc(sizeof(BiTree));//首次递归前添加头结点
Leaf_head->rchild = T;//添加第一个叶子节点
T->lchild = Leaf_head;//指向头
Leaf_pre = T;//哨兵指针
}
else
{
Leaf_pre->rchild = T;
T->lchild = Leaf_pre;
Leaf_pre = T;
}
}
LinkLeaf(T->rchild);
}
return;
}
//递归前序遍历
void PreOrderBiTree(BiTree* T)
{
if (T)
{
printf("%c", T->data);
PreOrderBiTree(T->lchild);
PreOrderBiTree(T->rchild);
}
}
//带头节点分离奇偶数 //带头节点
LinkList* Split(LinkList* L)
{
LinkNode* p = L;
LinkList* B = (LinkList*)malloc(sizeof(LinkList));//新带头链表B
B->next = NULL;
LinkNode *r = NULL,*q = B;//尾插哨兵
while (p->next)
{
if (p->next->data%2 == 1)//判断为奇数留在本链表
{
p = p->next;
}
else//偶数拆下来放入B
{
r = p->next;
p->next = r->next;
q->next = r;//尾插B
q = r;
}
}
return B;
}
//2020年 获取叶子到根的最短路径
/*
0
/ \
0 0
/
0
此类情况要注意
*/
int GetMinHeight(BiTree *T)
{
if (T==NULL)
{
return 0;
}
if (T->lchild == NULL &&T->rchild==NULL ) //叶子节点
{
return 1;
}
int L = GetMinHeight(T->lchild);
int R = GetMinHeight(T->rchild);
if (L&&R)//左右高度均不为0
{
return (L > R ? R : L) + 1;//返回较小高度子树
}
else//单分支节点,保留叶子节点路径
{
return (L > R ? L : R) + 1;//返回单分支路径长度
}
}
int main()
{
char *preorder = "ABDEHCFG";//前序序列
char *inorder = "CBAD"; //"DBEHAFCG";//中序序列
char *postorder = "CBDA"; //"DHEBFGCA";//后序序列
int size = strlen(inorder);
//BiTree*A = PreOrderBuildTree(preorder, inorder, size);
BiTree*B = PostOrderBuildTree(postorder, inorder, size);
/* int p = 0;
if (JudgeAVL(B,&p))
{
printf("平衡二叉树\n");
}*/
//BiTree *C = CopyTree(A);
//PreOrderBiTree(B);
printf("%d", GetMinHeight(B));
return 0;
}
#endif