二叉树的相关操作
-
二叉树的构造,清空操作
-
二叉树的遍历
- 递归前序遍历、中序遍历、后序遍历
- 非递归前序遍历、中序遍历、后序遍历
- 层次遍历
-
寻找指定二叉树结点
- 递归查找
- 非递归查找
-
寻找父结点
- 递归查找
- 非递归查找
-
删除指定节点及其左右子树
-
指定位置插入结点
-
求二叉树第k层的节点数
- 递归
- 非递归
-
深拷贝二叉树
-
求二叉树的深度
一:二叉树的构造,清空操作
/**
* 前序递归构造二叉树
* @param f
* @param Tree
* @return
*/
int CreatBinTree(BinTree* Tree){
char ch;
scanf("%c",&ch);
if (ch == ' '){
*Tree = NULL;
} else{
(*Tree) = (BinTree)malloc(sizeof (BinNode));
if (!(*Tree)){
exit(0);
}
(*Tree)->data = ch;
CreatBinTree(&(*Tree)->lchild); //构造左子树
CreatBinTree(&(*Tree)->rchild); //构造右子树
}
return 1;
}
//清空二叉树
void ClearBiTree(BinTree *T){
if (*T){ //如果当前结点不为空
if (!(*T)->lchild){
ClearBiTree((*T)->lchild); //清空左子树
} else if (!(*T)->rchild){
ClearBiTree((*T)->rchild); //清空右子树
}
free(*T); //释放节点
*T = NULL;
}
}
```
`
二:二叉树的遍历
1、递归:
/**
* 递归前序遍历
* @param T
*/
void PreOrderTraverse(BinTree T){
if (T){
printf("%c\t",T->data);
PreOrderTraverse(T->lchild);
PreOrderTraverse(T->rchild);
}
}
/**
* 中序遍历二叉树
* @param T
*/
void InorderTraverse(BinTree T){
if (T){
InorderTraverse(T->lchild);
printf("%c\t",T->data);
InorderTraverse(T->rchild);
}
}
/**
* 后续遍历二叉树
* @param T
*/
void PostOrderTraverse(BinTree T){
if (T){
PostOrderTraverse(T->lchild);
PostOrderTraverse(T->rchild);
printf("%c\t",T->data);
}
}
2、非递归
/**
* 非递归前序遍历
*/
void PreOrder(BinTree T){
//创建一个数组,用数组来模仿栈
BinTree stack[15];
int top = -1; //栈顶指针
BinTree p = T;
while (p!=NULL || top!=-1){
//当p不为空是将结点压入栈中
if (p!=NULL){
stack[++top] = p;
printf("%c\t",p->data); //前序遍历在压入栈时候访问结点数据
p = p->lchild;
} else{ //当p为空,证明p的父结点没有左子树,则将p弹出访问右子树
p = stack[top];
top--;
p = p->rchild;
}
}
}
/**
* 非递归遍历二叉树
* @param T
*/
void InOrder(BinTree T){
BinTree stack[15]; //定义一个数组用来模拟栈的使用
int top = -1;
BinTree p = T;
while (p!=NULL||top!=-1){
if (p!=NULL){
//将p结点压入栈
stack[++top] = p;
p = p->lchild;
} else{
p = stack[top--];
printf("%c\t",p->data);
p = p->rchild;
}
}
}
/**
* 非递归后续遍历二叉树
* @param T
*/
void PostOrder(BinTree T){
BinTree stack[15];
int flage[15];
int top = -1; //栈顶指针
BinTree p = T;
while (p!=NULL||top!=-1){
if (p!=NULL){
stack[++top] = p;
flage[top] = 1; //第一次访问,设个标志为1
p = p->lchild;
} else{
if (flage[top] == 1){
p = stack[top]; //获取栈顶元素,但是不取出
flage[top] = 2; //标志这第二次访问
p = p->rchild; //访问右子树
} else{ //第二次访问,证明也已经访问完了右子树,这时访问根节点
p = stack[top--];
printf("%c\t",p->data);
p = NULL; //置空,以便继续退栈,
}
}
}
}
3、层次遍历
/**
* 层次遍历二叉树
* 层次遍历需要借助队列,先进先出,使用一个数组来模拟队列操作,循环队列
* @param T
*/
void LevelTraverse(BinTree T){
BinTree queue[15];
int front = 0;
int rear = 0;
BinTree p = T;
if (!T){
return;
} else{
queue[rear] = p;
rear = (rear+1)%15;
while (rear!=front){ //当队列不为空时
p = queue[front];
printf("%c\t",p->data);
front = (front+1)%15; //元素出栈
if (p->lchild!=NULL){
//该结点的左孩子不为空
queue[rear] = p->lchild;
rear = (rear+1)%15;
}
if (p->rchild!=NULL){
queue[rear] = p->rchild;
rear = (rear+1)%15;
}
}
}
}
三:寻找指定二叉树结点
1、递归查找
/**
* 递归查找指定元素的结点
* @param T
* @param e
* @return 返回当前元素的地址
*/
BinTree LocateNode(BinTree T,BinElemType e){
BinTree p = NULL;
if (T!=NULL){
if (T->data == e){
p = T;
} else{
if (p=LocateNode(T->lchild,e)){
return p;
}
if (p=LocateNode(T->rchild,e)){
return p;
}
}
}
return p;
}
3、非递归查找
/**
* 非递归前序遍历查找在二叉树中给定数据的结点
* @param T
* @param e
* @return
*/
BinTree FindTreeNode(BinTree T,BinElemType e){
//使用非递归前序遍历寻找
BinTree stack[15]; //创建一个栈
int top = -1;
BinTree p = T;
while (p!=NULL||top!=-1){
if (p!=NULL){
//判断是否相等
if (p->data == e){
return p;
} else{
stack[++top] = p;
p = p->lchild;
}
} else{
p = stack[top--];
p = p->rchild;
}
}
return NULL;
}
/**
* 非递归后续遍历查找结点
* @param e
* @return
*/
BinTree PostFindTreeNode(BinTree T,BinElemType e){
BinTree stack[15];
int top = -1;
int flage[15];
BinTree p = T;
while (p!=NULL||top!=-1){
if (p!=NULL){
stack[++top] = p;
flage[top] = 1;
p = p->lchild;
} else{
if (flage[top]!=2){
//左子树为空,进行回退
p = stack[top];
flage[top] = 2;
p = p->rchild;
} else{
p = stack[top--];
if (e == p->data){
return p;
} else{
p = NULL;
}
}
}
}
return NULL;
}
四:寻找父结点
1、递归查找
/**
* 递归寻找指定节点的父结点
* @param T 树
* @param p 指定节点
* @return 返回父结点地址
*/
BinNode* FatherRe(BinTree T,BinNode* p){
BinNode* parent = NULL;
if (T!=NULL){
if (T->lchild == p||T->rchild == p){
parent = T;
} else{
if (parent = FatherRe(T->lchild,p)){
return parent;
}
if (parent = FatherRe(T->rchild,p)){
return parent;
}
}
}
return parent;
}
2、非递归查找
/**
* 非递归前序遍历查找给定节点的父结点
* 相当于双指针
* @param T
* @param e
* @return
*/
BinTree Parent(BinTree T,BinElemType e){
BinTree stack[15];
int top = -1;
BinTree p = T;
BinTree father;
while (p!=NULL||top!=-1){
if (p!=NULL){
if (p->data == e){
return father;
}
father = p;
stack[++top] = p;
p = p->lchild;
} else{
p = stack[top--];
father = p;
p = p->rchild;
}
}
return NULL;
}
五:删除指定节点及其左右子树
/**
* 删除结点及其左右子树
* 寻找数据值为e的节点的父结点,令为p,待删结点为q结点,让父结点的指向为空,调用clear函数,将q所表示的子树删除。
*
* @param T
* @param e
* @return
*/
int DleteTreeNode(BinTree T,BinElemType e){
BinTree p;
BinTree parentTree = Parent(T,e);
if ((parentTree->lchild)->data == e){
p = parentTree->lchild;
parentTree->lchild = NULL;
// ClearBiTree(&p);
return 1;
} else if ((parentTree->rchild)->data == e){
p = parentTree->rchild;
parentTree->rchild = NULL;
// ClearBiTree(&p);
return 1;
}
return 0;
}
六:指定位置插入结点
/**
* 在树T中的e结点之下插入一个新节点,并根据LR来决定插入的是右节点还是左节点
* @param T 待插入的树
* @param e 插入节点的父结点
* @param newNode 插入的新节点
* @param LR 判断是左节点还是右节点
* @return 1表示插入成功,0表示插入失败
* 思路:寻找数值为e的数据,并根据LR来决定插入的是做还是右子树,并用一个指针p来表示当前值为e的左或右节点,
* 然后执行插入
*/
int InsertNode(BinTree T,BinElemType e,BinNode* newNode,char LR){
BinTree parent = LocateNode(T,e);
if (T==NULL||parent==NULL){
return 0;
}
BinTree p = NULL;
if (LR=='L'){
p = parent->lchild;
parent->lchild = newNode;
newNode->lchild = p;
} else if ('R'){
p = parent->rchild;
parent->rchild = newNode;
newNode->rchild = p;
}
return 1;
}
七:求二叉树第k层的节点数
1、递归
/**
* 递归求第k层的节点数
* @param T
* @param kLevel
* @return
*/
int GetKLevelNum(BinTree T,int kLevel){
if(T==NULL||kLevel<=0){
return 0;
}
if (T!=NULL&&kLevel == 1){
return 1;
}
return (GetKLevelNum(T->lchild,kLevel-1) + GetKLevelNum(T->rchild,kLevel-1));
}
2、非递归
kong
八:深拷贝二叉树
/**复制二叉树
//递归后续遍历递归复制二叉树
*/
BinTree CopyTreePre(BinTree T){
if (T==NULL){
return NULL;
}
BinTree lchild = CopyTreePre(T->lchild);
BinTree rchild = CopyTreePre(T->rchild);
//创建一个根节点
BinTree newNode = malloc(sizeof (BinNode));
newNode ->data = T->data;
newNode ->lchild = lchild;
newNode->rchild = rchild;
return newNode;
}
九:求二叉树的深度
/**
* 求树的深度
* @param T
* @return
*/
int BiTreeDepth(BinTree T){
int LD,RD; //计算左右子树的深度
if (T == NULL){
return 0;
}
LD =BiTreeDepth(T->lchild);
RD = BiTreeDepth(T->rchild);
return (LD>=RD?LD:RD)+1;
}