树的定义与性质
由若干结点和若干条边组成的数据结构。
常用性质:
- 树可以没有结点,这种情况把树称为空树。
- 树的层次从根结点开始算起,即根结点为第一层,根结点子树的根结点为第二层,以此类推。
- 把结点的子树棵数称为结点的度,树中结点的最大的度称为树的度。
- 由于一条边连接两个结点,且树中不存在环,因此对有n个结点的树,边数一定是n-1.
满足连通、边数等于顶点数-1的结构一定是一棵树。 - 叶子结点被定义为度为0的结点,因此当树中只有一个结点(即只有根结点)时,根结点也算作叶子结点。
- 结点的深度是指从根结点(深度为1)开始自顶向下逐层累加至该结点的深度值。
结点的高度是指从最底层叶子结点开始自底向上逐层累加至该结点时的高度值。
树的深度是指树中结点的最大深度,树的高度是指树中结点的最大高度。对树而言,深度与高度相等。 - 多棵树组合在一起称为森林,即森林是若干树的集合。
二叉树的递归定义(用自身定义自身)
- 二叉树要么没有根结点,是一棵空树。
- 二叉树要么由根结点、左子树。右子树组成,且左子树和右子树都是二叉树。
- 两种特殊二叉树
- 满二叉树: 每一层的结点个数都达到了当层能达到的最大结点数
- 完全二叉树: 除了最下面一层之外,其余层的结点个数都达到了当层能达到的最大结点数,
且最下面一层只从左到右连续存在若干结点,而这些结点右边的结点全部不存在。
- 树的其他概念
- 层次:层次类似于家谱中的辈分关系
- 孩子结点、父亲结点、兄弟结点、祖先结点、子孙结点:一个结点的子树的根结点称为它的孩子结点,
而它称为孩子节点的父亲结点。与该结点同父亲的结点称为该结点的兄弟结点。
二叉树的存储结构与基本操作
- 二叉树的存储结构
与链表类似,只是指针域改为两个——指向左子树的根结点地址和右子树的根结点地址。
如果某个子树不存在,则指向NULL
struct node{
typename data;//数据域
node* lchild;//指向左子树根结点的指针
node* rchild;//指向右子树根结点的指针
};
//根结点初始化
node* root=NULL;
//往二叉树中插入结点
node* newNode(int v){
node* Node = new node;//申请一个node型变量的地址空间
Node->data=v;//结点权值
Node-lchild=Node->rchild=NULL;
return Node;//返回新建结点的地址
}
- 二叉树的查找、修改
查找操作是指在给定数据域的条件下,在二叉树中找到所有数据域为给定数据域的结点
void search(node* root,int x,int newdata){
if(root==NULL){
return ;//空树(递归边界)
}
if(root->data==x){//找到数据域为x的结点,把它修改为newdata
root->data=newdata;
}
search(root->lchild,x,newdata);//往左子树搜索x(递归式)
search(root->rchild,x,newdata);//往右子树搜索x(递归式)
}
- 二叉树结点的插入
结点的插入位置一般取决于数据域需要在二叉树中存放的位置,且对給定结点来说,它在二叉树中的插入位置只会有一个。
即二叉树结点的插入位置就是数据域在二叉树中查找失败的位置
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使用了&引用,即在函数中修改root会直接修改原变量,如果不用引用,就无法将
新结点接到二叉树上面,而search函数中修改的是指针root指向的内容,而不是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的区别
即结点不存在与结点存在但没有内容的区别 - 完全二叉树存储结构
对完全二叉树的任一结点x,其左孩子编号一定为2x,右孩子编号为2x+1.
完全二叉树可以通过建立一个大小为2^k的数组来存放所有结点的信息,其中k为完全二叉树的最大高度
且1号位必须存放根结点,该数组中元素存放的顺序恰好为该完全二叉树的层序遍历序列
判断某个结点是否为叶结点的标志为:该结点(下标记为t)的左子结点的编号2*t大于结点总个数n
判断某个结点是否为空结点的标志:该结点下标t大于结点总个数n。