二叉平衡树(只有实现没有讲解)

实现步骤:

二叉树的实现:
功能:
	1. 添加
	2. 删除
	3. 查找
	4. 排序(中序遍历)
实现:
	1. 建立一个结构体;表示二叉树的节点包含值,左孩子和右孩子
	2. 添加:
		a. 参数传入根的二级指针,记得初始化要不会出错(在Create里BinaryTree *pRoot);
		b. 将节点封装到树的节点里
		c. 是否有根,即是否根为空,空则给根赋值,这也是为啥要传入2级指针的目的,记得只要修改根就需要传入二级指针
		d. 不空即有根的情况,设置一个变量,为当前节点
			i. 和当前节点比较大小
				1) 大:表示该节点要放在当前节点的右边,判断当前节点的右节点是否空,空则放入,不空则继续赋值变量为当前节点的右边节点继续讨论,
				2) 小:表示该节点要放在当前节点的左边,判断当前节点的左边是否为空,空则表示位置正确,放入即可,否则重新赋值,重新讨论即可
				3) 一样:报错,二叉树不允许有一样值。
	3. 查找:
		a. 和添加一样,遍历被,小则往左走,大则往右走直到找到或者不存在,返回
	4. 删除:
		a. 查找要删除的点,因为二叉树,结构体里不存在父亲的节点,但是删除的时候需要父亲的节点,因此需要设置一个父亲的变量保存要删除的点的父亲,因此修改查找,将查找修改为可以返回当前节点和父亲节点或者直接返回父亲节点,只不过多几次判断而已。
		b. 分析要删除的情况:删除高明的地方就在于为了保存二叉树的整体结构不散,nb的人发现可以直接用左的最右边或者右的最左边替换要删除的节点,把值换了,所以就不需要删除那个节点了,直接删除替换的那个即可,将删除总是放到叶子节点及其父亲节点的删除上,满足了改变最少使得二叉树平衡的条件
			i. 两个孩子:转化为一个孩子
				1) 设置临时变量保存pDl
				2) 得到左边的,pFather = pTemp;pTemp = pLeft,::::::时刻记的父亲变了,爷爷也得变化
				3) 得到左的最右 while(pTemp->pRight)pFather = pTemp; pTemp = pTemp->pRight;
				4) 替换: pDel->nValue = pTemp->nVlaue; pDel = pTemp;
			注意:时刻注意pFather,让他始终是pTemp的父亲,pTemp变化了,其父亲肯定变化。
			ii. 一个孩子
			iii. 没有孩子
		c. 仔细研究发现,没有孩子和一个孩子情况一直都是看左孩子在不在,在直接爷爷连接左孩子,不在爷爷连接右孩子 ,但有个问题没有没爷爷啊,即要删除的节点的父亲在不在啊,不在,你还搁置左右孩子,不报错吗,因此先判断父亲在不在,也就是根在不在。
			i. pFather == NULL          *pRoot = pDel->pLeft != NULL ? pDel->pLeft : pDel->pRight;
			ii. 删除节点的父亲不为空,则判断删除节点在父亲哪里啊,因为要让被删除节点的孩子连接被删除节点的父亲啊,因此
				1) pFather->pLeft == pDel         pFather->pLeft = pDel->pLeft != NULL ? pDel->pLeft : pDel->pRight;
				2) pFather->pRight = pDel->pLeft != NULL ? pDel->pLeft : pDel->pRight;
			注意:这部分你总把==写成=,还容易将pFather->pLeft 写成pFather->pRight或者pFather->Right没有改直接写。

代码:

#include<stdio.h>
#include<stdlib.h>

typedef struct tree
{
	int nValue;
	struct tree *pLeft;
	struct tree *pRight;
}BinaryTree;

BinaryTree *CreateBinaryTree(int arr[], int nLength);
void AddBinaryTreeNode(BinaryTree **ppRoot, int nValue);
BinaryTree *FindBinaryTree(BinaryTree *pRoot, int nKey,int **ppFather);
void DeleteBinaryTree(BinaryTree **ppRoot, int nKey);
void InorderTraversal(BinaryTree *pRoot);

BinaryTree *CreateBinaryTree(int arr[], int nLength)
{
	int i;
	BinaryTree *pRoot = NULL;
	if(arr==NULL || nLength<=0)return NULL;
	for(i=0; i<nLength; i++)
	{
		AddBinaryTreeNode(&pRoot,arr[i]);
	}
	return pRoot;
}

void AddBinaryTreeNode(BinaryTree **ppRoot, int nValue)
{
	BinaryTree *pTemp = NULL;
	BinaryTree *pNode = (BinaryTree *)malloc(sizeof(BinaryTree));
	pNode->nValue = nValue;
	pNode->pLeft = NULL;
	pNode->pRight = NULL;
	if(*ppRoot == NULL)
	{
		*ppRoot = pNode;
		return;
	}
	pTemp = *ppRoot;//注意
	while(pTemp)
	{
		if(nValue > pTemp->nValue)
		{
			if(pTemp->pRight == NULL)
			{
				pTemp->pRight = pNode;
				return;
			}
			pTemp = pTemp->pRight;
		}
		else if(nValue < pTemp->nValue)
		{
			if(pTemp->pLeft == NULL)
			{
				pTemp->pLeft = pNode;
				return;
			}
			pTemp = pTemp->pLeft;
		}
		else
		{
			exit(1);
		}
	}
}

BinaryTree *FindBinaryTree(BinaryTree *pRoot, int nKey,BinaryTree **ppFather)
{
	if(pRoot == NULL)return NULL;
	while(pRoot)
	{
		if(nKey > pRoot->nValue)
		{
			*ppFather = pRoot;
			pRoot = pRoot->pRight;
		}
		else if(nKey < pRoot->nValue)
		{
			*ppFather = pRoot;
			pRoot = pRoot->pLeft;
		}
		else
		{
			return pRoot;
		}
	}
	return NULL;
}

void DeleteBinaryTree(BinaryTree **ppRoot, int nKey)
{
	BinaryTree *pDel = NULL;
	BinaryTree *pFather = NULL;
	BinaryTree *pTemp = NULL;
	if(*ppRoot == NULL)return;
	pDel = FindBinaryTree(*ppRoot, nKey, &pFather);
	if(pDel == NULL)return;
	pTemp = pDel;
	if(pDel->pLeft != NULL && pDel->pRight != NULL)
	{
		pFather = pTemp;
		pTemp = pTemp->pLeft;
		while(pTemp->pRight)
		{
			pFather = pTemp;
			pTemp = pTemp->pRight;
		}
		pDel->nValue = pTemp->nValue;
		pDel = pTemp;
	}
	if(pFather == NULL)
	{
		*ppRoot = pDel->pLeft != NULL ? pDel->pLeft : pDel->pRight;
	}
	else
	{
		if(pFather->pLeft == pDel)
			pFather->pLeft = pDel->pLeft != NULL ? pDel->pLeft : pDel->pRight;
		else
			pFather->pRight = pDel->pLeft != NULL ? pDel->pLeft : pDel->pRight;
	}
}

void InorderTraversal(BinaryTree *pRoot)
{
	if(pRoot == NULL)return;
	InorderTraversal(pRoot->pLeft);
	printf("%d ", pRoot->nValue);
	InorderTraversal(pRoot->pRight);
}

int main()
{
	int arr[] = {2,4,1,3,5,7};
	BinaryTree *pRoot = CreateBinaryTree(arr,sizeof(arr)/sizeof(arr[0]));
	InorderTraversal(pRoot);
	printf("\n");

	DeleteBinaryTree(&pRoot,3);
	InorderTraversal(pRoot);
	printf("\n");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值