二叉树部分算法代码

#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

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值