实现步骤:
二叉树的实现:
功能:
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;
}