#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#define SIZE 10/*树的大小*/
typedef struct tronde {
struct tronde* Left;
struct tronde* Right;
int key;
}Tronde;
typedef struct tree {
Tronde* root;
int size;/*项数*/
}Tree;
static Tronde* CopyEnptm(int x);
static void CopyDelte(Tronde* root);
static bool Find(Tronde* root, int x);
static void CopyEmDelete(Tronde** root, int x);
static void CopyDelete1(Tronde** root);
bool CopySize(Tree* Ptree);
bool CopyFull(Tree* Ptree);
bool FindTree(Tree* Ptree,int x);
void BuildTree(Tronde** lefRig, Tronde* x);
void InitializeTree(Tree* Ptree);
void AddNodeTree(Tree *Ptree,int x);
void EmptyDelete (Tree* Ptree);
void Delete(Tree* Ptree,int x);
void println(Tronde* root,void (*pfun)(int));/*函数指针*/
void showarray(int x);
int main(void) {
Tree Ptree;
InitializeTree(&Ptree);
AddNodeTree(&Ptree, 10);
AddNodeTree(&Ptree, 8);
AddNodeTree(&Ptree, 7);
AddNodeTree(&Ptree, 9);
AddNodeTree(&Ptree, 12);
AddNodeTree(&Ptree,11);
AddNodeTree(&Ptree, 13);
AddNodeTree(&Ptree, 3);
AddNodeTree(&Ptree, 5);
AddNodeTree(&Ptree, 6);
if (!CopySize(&Ptree)) {/*查看树是否为空 其他操作都在这里完成*/
println(Ptree.root, showarray);
if (FindTree(&Ptree, 7))/*查找7这个数字*/
printf("已在树中查到%d这个数字\n", 4);
else
printf("%d这个数字树中没有\n",4);
Delete(&Ptree,8);
Delete(&Ptree, 10);
Delete(&Ptree, 11);
Delete(&Ptree, 13);
println(Ptree.root, showarray);
}
else
puts("树为空");
EmptyDelete(&Ptree, 4);
}
/*显示内容*/
void showarray(int x) {
printf("Tree:%d\n", x);
}
/*初始化*/
void InitializeTree(Tree* Ptree){
Ptree->root = NULL;
Ptree->size = 0;
}
/*查看树是否为空*/
bool CopySize(Tree* Ptree) {
return Ptree->size == 0;
}
/*查看树是否已满*/
bool CopyFull(Tree* Ptree) {
return Ptree->size == SIZE;
}
/*生成根*/
void AddNodeTree(Tree* Ptree, int x) {
Tronde* ps;
Tronde* pn = Ptree->root;
if (CopyFull(Ptree)) {
printf("内容已满(添加内容为%d)\n",x);
return;
}
ps = CopyEnptm(x);
if (ps==NULL)/*判断是否申请成功*/
exit(EXIT_FAILURE);
if (pn == NULL) {
Ptree->root = ps;
}
else {
BuildTree(&Ptree->root, ps);
}
Ptree->size++;
}
/*生成左子右子(树)*/
void BuildTree(Tronde** lefRig, Tronde* x) {
if (*lefRig != NULL) {
if (x->key < (*lefRig)->key)
BuildTree(&(*lefRig)->Left, x);
else if (x->key > (*lefRig)->key) {
BuildTree(&(*lefRig)->Right, x);
}
}
else {
*lefRig = x;
}
}
/*一些赋值操作*/
static Tronde* CopyEnptm(int x){
Tronde* pnew = (Tronde*)malloc(sizeof(Tronde));
if (pnew==NULL)/*申请不成功*/
return NULL;
else {
pnew->Left = NULL;
pnew->Right = NULL;
pnew->key = x;
}
return pnew;
}
/*查找*/
bool FindTree(Tree* Ptree, int x) {
if (Ptree->root) {
if (Find(Ptree->root,x))
return true;
else
return false;
}
}
/*进行查找*/
static bool Find(Tronde* root, int x) {/*这里使用循环不使用递归当然可以使用递归*/
while (root != NULL) {
if (x < root->key)
root = root->Left;
else if (x > root->key)
root = root->Right;
else
return true;
}
return false;
}
/*删除*/
void Delete(Tree* Ptree, int x) {
if (Ptree->root) {
CopyEmDelete(&Ptree->root, x);
}
}
static void CopyEmDelete(Tronde** root, int x) {/*删除操作 (指针不熟的可能不知道这里为什么用二级指针
刚开始使用的是一级指针但是程序没有按照我的想法运行最后在dev里面测试了一下不在这讨论写完放下面)*/
if (*root != NULL) {
if (x < (*root)->key) {
CopyEmDelete(&(*root)->Left, x);
}
else if (x > (*root)->key) {
CopyEmDelete(&(*root)->Right, x);
}
else {
CopyDelete1(&(*root));
}
}
}
/*删除和连接操作*/
static void CopyDelete1(Tronde** root) {
Tronde* temp;
if ((*root)->Left == NULL) {
temp = *root;
*root = (*root)->Right;
free(temp);
}
else if ((*root)->Right == NULL) {
temp = *root;
*root = (*root)->Left;
free(temp);
}
else {
for (temp = (*root)->Left; temp->Right != NULL; temp = temp->Right)
continue;
temp->Right = (*root)->Right;
temp = *root;
*root = (*root)->Left;
free(temp);
}
}
/*清空*/
void EmptyDelete(Tree* Ptree) {
if (CopySize(Ptree))
puts("树为空");
else {
if (Ptree->root) {
CopyDelte(Ptree->root);
}
}
}
/*删除全部节点*/
static void CopyDelte(Tronde* root) {
Tronde* printh;
if (root != NULL) {
printh = root->Right;
CopyDelte(root->Left);
free(root);
CopyDelte(printh);
}
}
/*查看树内容*/
void println(Tronde* root, void (*pfun)(int)) {
if (root != NULL) {
println(root->Left,(*pfun));
(*pfun)(root->key);/*作用于*/
println(root->Right, (*pfun));
}
}
在上面的代码中有这段代码:static void CopyEmDelete(Tronde** root, int x)用到了二级指针,不经常用二级指针的可能不理解,举个例子:
int main(void){
int *p;
int **q;
p=(int*)malloc(sizeof(int));
printf("%d\n",p);
q=&p;
printf("%d",*q);
free(p);
}
输出的结果一样
上面图中:temp指向p申请的空间,*q=指向temp;*q赋值为空,输出结果发现temp也变为空,而p不为空,总结也就是*q修改的是temp指向的内容,不修改p指向的内容.二级指针是操控一级指针的。
在上面递归函数调用中和这个同理,如果使用一级指针去删除那么最后在函数里面root修改的是自身指向的内容,当空间释放掉之后,我们删除的节点的父节点其中成员指向的内容将为垃圾值.说的有点麻烦理解一下.