1)二叉树的存储结构
一般来说,二叉树使用链表来定义—和动态链表的定义一样。
struct node{
typename data;//数据域
node* lchild;//指向左子树根结点的指针
node* rchild;//指向右子树根结点的指针
};
注意的是:由于二叉树建树前根结点不存在,因此 其地址一般设为NULL。
新建结点(例如往二叉树中插入结点的时候)------实现代码如下
//生成一个新结点,v为结点的权值(数据域)
node* newNode(int v)
{
node* Node=new node;//申请一个node型变量的地址空间
Node->data=v;//结点权值为v
Node->lchild=Node->rchild=NULL;//初始状态下没有左右孩子
return Node;//返回新建结点的地址
}
2)二叉树结点的查找、修改
查找操作是指在给定数据域的条件下,在二叉树中农找到所有数据域为给定数据域的结点,并将他们的数据域修改为给定的数据域。
void search(node* root,int x,int newdata)
{
if(root==NULL)
{
return;//空树,死胡同(递归边界)
}
if(root->data==x)//找到数据域为x的结点,把它修改Wienewdata
{
root->data=newdata;
}
search(root->lchild,x,newdata);//往左子树搜索x(递归式)
search(root->rchild,x,newdata);//往右子树搜索x(递归式)
}
3)二叉树结点的插入
注意:由于二叉树的形态有多种,所以题目不说明二叉树特点时很难给出结点插入的具体方法,所以需要记住:即二叉树的插入位置就是数据域在二叉树中查找失败的位置,而且这个位置是确定的,因此子递归查找的过程中一定是根据二叉树的性质来选择左子树或右子树中农的一棵子树进行递归,且最后到达空树(死胡同)的地方就是查找失败的地方,也就是结点需要插入的地方。
node* newNode(int x){
node* Node=new node;//申请一个node型变量的地址空间
Node->data=x;
Node->lchild=Node-rchild=NULL;//初始状态下没有左右孩子
return Node;//返回新建结点的地址
}
void insert(node* &root,int x)//注意根节点需要使用引用,否则插入不会成功
{
if(root==NULL)//空树,查找失败,也就是插入的位置
{
root=newNode(x);
return;
}
if(由二叉树的性质,x应该插在左子树)
{
insert(root->lchild,x);//往左子树搜索(递归式)
}
else
{
insert(root->rchild,x);//往右子树搜索(递归式)
}
}
注意:引用的作用是:即就是在函数中修改root会直接修改原变量。
什么时候要加引用?
-------如果函数中需要新建结点,即对二叉树的结构做出修改,就需要加引用;如果只是修改当前的内容,或仅仅是遍历树,就不加引用。
4)二叉树的创建
//新建结点
node* newNode(x)
{
node* Node=new node;//申请一个node型变量的地址空间
Node->data=x;
Node->lchild=Node->rchild=NULL;//初始状态下没有左右孩子
return Node;//返回新建结点的地址
}
//二叉树结点的插入
void insert(node* &root,int x)
{
if(root==NULL)//空树,说明查找失败,也就是插入的位置
{
root=newNode(x);
return;
}
if(由二叉树的性质,x应该插在左子树)
{
insert(root->lchild,x);//往左子树搜索
}
else
{
insert(root->rchild,x)//往右子树搜索
}
}
//二叉树的创建
node* create(int data[],int n)
{
node* root=NULL;//新建根结点root
for(int i=0;i<n;i++)
{
insert(root,data[i]);//将data[0]~data[n-1]插入二叉树
}
return root;
}