17黑马笔记之二叉树的拷贝与释放
1 二叉树的拷贝思想: 先传进二叉树的根节点,然后先遍历其左子树,令其执行到左子树的最后节点;再遍历其右子树,递归遍历左右子树都要接收返回值(malloc出的新节点地址)。然后malloc创建新的节点并赋值,返回新的节点便可。递归条件:传进的节点不为空(绝大多数都是这个)。
2 二叉树的释放: 同样的,先遍历左子树,使其先执行左子树的最后一个节点,再遍历右子树。然后释放该节点内存便可。递归条件:传进的节点不为空。
3 代码实现:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//定义二叉树节点
typedef struct BINARYNODE{
char ch;
struct BINARYNODE *lchild;
struct BINARYNODE *rchild;
}BinaryNode;
//拷贝二叉树 ok 懂了
BinaryNode *CopyBinaryTree(BinaryNode *root){
if(root==NULL){
return NULL;
}
//先拷贝左子树
BinaryNode *lchild=CopyBinaryTree(root->lchild);
//再拷贝右子树
BinaryNode *rchild=CopyBinaryTree(root->rchild);
//最后依次拷贝每个节点
BinaryNode *newnode=(BinaryNode*)malloc(sizeof(BinaryNode));
newnode->ch=root->ch;
newnode->lchild=lchild; //这里出错了!!!,而且不能用root->lchild的原因是:不能使堆开辟
newnode->rchild=rchild;//出来的newnode->lchild指向栈开辟的内容,否则当指向完释放内存后,newnode->lchild
//所指的栈内容也释放,结果CreateBinartTree函数结束在释放一次就会类似浅拷贝问题
return newnode; //所以必须要用返回值赋值(画图就可以了)
}
//遍历二叉树 ok 懂了
void RecursionBinaryTree(BinaryNode *root){
if(root==NULL){
return ;
}
//前序遍历 --根左右
printf("%c",root->ch);
RecursionBinaryTree(root->lchild);
RecursionBinaryTree(root->rchild);
return ;
}
//释放二叉树 ok
void DestroyBinaryTree(BinaryNode *root){
if(root==NULL){
return ;
}
//free(root); //我写的没问题,用他的出错了--但是只是free了一个根节点啊,所以这个是不对的
//他写的--实际上这种释放可以说是后序释放
//先释放左子树
DestroyBinaryTree(root->lchild);
//右子树
DestroyBinaryTree(root->rchild);
//释放当前根节点
free(root);
return ;
}
void CreateBinartTree(){
//创建数据节点
BinaryNode node1={'A',NULL,NULL};
BinaryNode node2={'B',NULL,NULL};
BinaryNode node3={'C',NULL,NULL};
BinaryNode node4={'D',NULL,NULL};
BinaryNode node5={'E',NULL,NULL};
BinaryNode node6={'F',NULL,NULL};
BinaryNode node7={'G',NULL,NULL};
BinaryNode node8={'H',NULL,NULL};
//建立节点关系 A-F-G-H
// \B
// \C-E
// \D
node1.lchild=&node2;
node1.rchild=&node6;
node2.rchild=&node3;
node3.lchild=&node4;
node3.rchild=&node5;
node6.rchild=&node7;
node7.rchild=&node8;
//拷贝二叉树
BinaryNode *root=CopyBinaryTree(&node1);
//遍历二叉树
RecursionBinaryTree(root);
//释放二叉树
DestroyBinaryTree(root);
}
int main(){
CreateBinartTree();
return 0;
}
//总结:这个项目有问题再释放内存那里,但是我分析过了代码应该没有问题才对啊!!!
//懂了,在拷贝时出问题!不能用原来的树的内容给他指向,导致两个二叉树的两个指针指向同一片区域,
//必须新建变量给他新的指向