一、二叉树的递归定义
1.要么二叉树没有根节点,是一颗空树。
2.要么二叉树由根节点,左子树和右子树组成,且左子树和右子树都是二叉树。
请注意二叉树与度为2的树的区别:对树来说,结点的子树是不区分左右顺序的。度为2的树只能说明树中所有结点的子结点个数不超过2。而二叉树其左右子树是严格区分的,不能随意交换左子树和右子树位置。
二、二叉树的存储结构
此处二叉树用链表来定义。(对链表不太熟悉的可用数组定义二叉树的静态实现)
struct node{
int data; //数据域,可以是任意类型
node* lchild; //指向左子树根节点的指针
node* rchild; //指向右子树根节点的指针
};
在二叉树建树前根节点不存在,其地址一般为NULL
node* root=NULL;
新建一个结点:
node* newNode(int val){
node* Node=new node;
Node->data=val;
Node->rchild=NULL; //一定要将新创建的结点其左右子树至为NULL,表示无左右子树
Node->lchild=NULL;
return Node;
}
三、二叉树的常用操作
1、查找。在二叉树中找到所有数据域为给定数据域的结点,并将它们的数据域修改为给定的数据域。
void search(node* root,int x,int newdata){
if(root==NULL){ //递归边界,当前结点为空。
return ;
}
if(root->data==x){ //找到该结点。
root->data=newdata;
}
search(root->rchild,int x,int newdata); //依次向右子树,左子树进行搜索。
search(root->lchild,int x,int newdata);
}
2、插入。结点的插入位置取决于数据域需要在二叉树中存放的位置。(例如二叉查找树就要根据插入的数据域跟当前的结点比较大小。)但数据域要插入的地方就是在二叉树中查找失败的位置,此位置确定。
void insert(node* &root,int x){ //注意此处应是引用该树,负责插入不会成功。
if(root==NULL){ //若该树为一棵空树,插入结点为根节点。
root=newNode(x);
return;
}
if(x应该插在左子树的条件成立){
insert(root->lchild,int x);
}else{
insert(root->rchild,int x);
}
]
3、创建二叉树。创建过程也就是数据一个个插入的过程。
node* create(int data[],int n){
node* root=NULL; //创建根结点root
for(int i=0;i<n;++i){
insert(root,data[i]);
}
return root; // 返回整个创建好的树。
}
4、特殊二叉树的存储。
对完全二叉树而言,假设根结点编号为x,其左子树结点编号肯定为2*x,右子树结点编号为2*x+1,并且其根节点root编号一定从1开始。由于次性质,完全二叉树可用数组存储,用下标表示其左右子树编号。数组开到结点个数+1即可。在完全二叉树中,判断某个结点是否为叶子结点标志为:判断该结点的左孩子结点编号2*x是否大于结点总个数n。大于是叶子结点。判断是否为空结点标志为:该结点下标root大于结点总个数n。