一、二叉树的存储结构
1、二叉树一般使用链表来存储的,但又与一般链表不同。因为二叉树的结点有两个出边(左右子树),所以链表的指针域要有两个指针分别指向结点的左右子树的根结点的地址,把这种结构又称为二叉链表。
2、定义如下:
struct node{
typename data;//数据域
node* lchild;//指向左子树结点的指针
node* rchild;//指向右子树结点的指针
};
注:因为建树之前root并不存在,所以其地址一般设为null;
node* root=NULL;
3、新建一个结点的函数(例如往二叉树中插入新结点时)
node* newNode(int v)//要创建结点的权值为v
{
node* Node=new node;//申请一个node型变量的地址空间
Node->data=v;//结点权值为v
Node->lchild=Node->rchild=NULL;//初始状态下没有左右孩子
return Node;//返回新建结点的地址
}
二、二叉树的常用操作
1、二叉树的查找与修改
思想:先判断当前结点是否是要查找的结点,如果是则对其进行修改;如果不是,则分别往该结点的左右孩子递归,直到当前结点为NULL时为止,举例代码如下:
void search(node* root,int x,int newdata)
{
if(root==NULL)//递归边界
{
return;
}
if(root->data==v)
{
root->data=newdata;
}
search(root->lchild,x,newdata);
search(root->rchild,x,newdata);
}
2、二叉树的插入
二叉树的插入操作相对来说较为灵活,插入为止根据题目要求而定。但是一般来说插入位置只有一个,就有了这样一个结论:当查找数据域失败时的位置即为要插入的位置。
void insert(node* &root,int x)//insert修改的是root本身,而search修改的是root所指向的内容,所以insert需要添加‘&’,否则就不能把新结点插入到二叉树上
{
if(root==NULL)//空树,也就是要插入的位置
{
root=newNode(x);
return;
}
if(由二叉树的性质,x应该插在左子树)
{
insert(root->lchild,x);
}else{
insert(root->rchild,x);
}
}
3、二叉树的创建
创建其实就是一棵树从无然后一个结点一个结点插入的过程,把需要插入的数据存储在数组中,然后使用insert函数插入到二叉树中,并返回根结点的指针root;
node* create(int data[],int n)
{
node* root=NULL;
for(int i=0;i<n;i++)
{
insert(root,data[i]);
}
return root;
}
三、*root==NULL;和root==NULL;的区别:
*root是指获取地址root指向的空间的内容,因此*root是无法用来判断地址是否为空,也即无法判断结点是否存在,若为空树则root==null;说的通熟一点就是:前者是“结点存在但没有内容”后者是“结点不存在”
四、完全二叉树的存储结构:
完全二叉树进行编号之后可以用数组来进行存储,该数组中元素存放的顺序恰好为该完全二叉树的层序遍历序列。
判断某个结点是否为叶子结点:该结点的左子节点编号root*2大于结点总个数n;
判断某个结点是否为空结点:该结点的下标root大于结点总个数n;