二叉树
二叉树
实现用线性结构表示非 线性结构
数---》二叉树---》满二叉树---》完全二叉树
一、二叉树的概念
二叉树也是树的一种,其存储结构及其算法都较为简单,因此二叉树显得特别重要。
二叉树:是每个节点的最多有两个子树的有序树--度最多为2的有序树
注意:在有序树中,虽然一个节点的孩子之间是有左右次序的,但是若该节点只有一个孩子,就无须区分左右次序,而在二叉树中,即使是一个孩子也有左右之分
一棵数变成二叉树:目的想去利用数组的方式保存(但是可能会存在浪费)
二、二叉树的五种表现形式
1.空树
2.只有一个根节点的二叉树
3.只有一个左子树的二叉树
4.只有一个右子树的二叉树
5.有左右子树的二叉树
三、二叉树的特性
1.二叉树的每个节点至多只有二棵子树(不存在度大于2的节点)
2.二叉树的子树哟左右之分,次序不能颠倒
3.二叉树的第n层至多有2^(n-1)个节点
4.深度为k的二叉树至多有2^(k)-1个节点
5.任意一棵二叉树中,如果度为2的节点数为n,度为0的节点数为m,m=n+1
四、满二叉树
1.二叉树中第n层上的节点数必须为2^(n-1)个节点
2.二叉树如果高度为k,这个二叉树中的节点数必须为2^(k)-1个
3.在满二叉树中不存在度为1的节点,每一个分支节点都有2棵高度一致的子树所有叶节点都在最下一层
4.一棵二叉树如果变成了满二叉树,可以利用数组且,且没有空间浪费
五、完全二叉树
1.若一棵二叉树最多只有最下面的两层其节点的度可以小于2,并且最下一层上的节点都集中在该层最左边的若干位置上,则此二叉树称为完全二叉树
2.满二叉树是完全二叉树,完全二叉树不一定是满二叉树
完全二叉树的特性
1.从一棵满二叉树的最下一层(叶节点那一层),从右往左依次删除若干(0-n)叶节点后形成的数叫完全二叉树
2.在一棵完全二叉树中,如果一个节点没有左子树,这个节点必然没有右子树,这个节点是叶节点。但是可以有左子树,没有右子树
完全二叉树中的下标规律
1.根节点下标默认为0
2.树中的任意一个节点它的下标为i,那么这个节点的父节点下标必然为(i-1)>>1
3.树中的任意一个节点它的下标为i,那么这个节点的左子树下标必然是2*i+1,右子树的下标必然为2乘i+2
4.除开根节点,左子树的下标为奇数,右子树的下标为偶数
六、二叉树的遍历
1、先序(根)
先访问根节点,然后访问左孩子,最后访问右孩子
2、中序(根)
先访问左孩子,然后访问根节点,最后访问右孩子
3、后序(根)
先访问左孩子,再访问右孩子,最后访问根节点
七、完全二叉树的代码示例
类模板--binarytree.h
#pragma once
template<class T>
class mytree
{
T* pbuff;
int len;//动态数组当前元素个数
int maxsize;//动态数组最大容量
public:
mytree();
~mytree();
void clear();//清除树
public:
bool find(T const&findval)const;//判断是否在树中找到这个数据
void appendnode(T const&data);//申请内存扩容,并插入数据
void inittree(T arr[], int length);//初始化树
void printftree();//提供接口,打印树
T getparentval(int elemval)const;//找父节点
T getleftval(int elemval)const;//找左子树
T getrightval(int elemval)const;//找右子树
T getleftbrother(int elemval)const;//找左兄弟
T getrightbrother(int elemval)const;//找右兄弟
private:
int _find(T const& findval)const;//查找数据,返回下标
void _printftree(int index);//打印树
};
template<class T>
mytree<T>::mytree()//构造函数
{
pbuff = nullptr;
len = maxsize = 0;
}
template<class T>
mytree<T>::~mytree()
{
clear();
}
template<class T>
void mytree<T>::clear()
{
if (pbuff)
delete[]pbuff;
pbuff = nullptr;
len = maxsize = 0;
}
template<class T>
bool mytree<T>::find(T const & findval) const
{
return _find(findval) != -1;
}
template<class T>
void mytree<T>::appendnode(T const & data)
{
if (len >= maxsize)
{
maxsize = maxsize + ((maxsize >> 1) ? (maxsize >> 1) : 1);
T* ptemp = new T[maxsize];
memcpy(ptemp, pbuff, sizeof(T)*len);
if (pbuff)
{
delete[]pbuff;
}
pbuff = ptemp;
}
pbuff[len++] = data;
}
template<class T>
void mytree<T>::inittree(T arr[], int length)//传一个数组进来
{
clear();//先将树中的内容清除掉
if (length > 0)
{
maxsize = len = length;
pbuff = new T[maxsize];
for (int i = 0; i < maxsize; i++)
{
pbuff[i] = arr[i];//用这个数组来初始化动态数组
}
}
}
template<class T>
void mytree<T>::printftree()
{
_printftree(0);//从根节点开始打印
}
template<class T>
T mytree<T>::getparentval(int elemval) const//打印传进来的数据的父节点
{
int index = _find(elemval);
if (index < 0)
throw "发生错误";
return pbuff[(index - 1) >> 1];
}
template<class T>
T mytree<T>::getleftval(int elemval) const//找这个数据的左子树
{
int index = _find(elemval);
if (2 * index + 1 >= len || index < 0)
{
throw "out_range";
}
return pbuff[2 * index + 1];
}
template<class T>
T mytree<T>::getrightval(int elemval) const
{
int index = _find(elemval);
if (2 * index + 2 >= len && index < 0)
{
throw "发生错误";
}
return pbuff[2 * index + 2];
}
template<class T>
T mytree<T>::getleftbrother(int elemval) const
{
int index = _find(elemval);
if (index < 0)
{
throw "发生错误";
}
if (index % 2 != 0)
{
throw "this is left";
}
return pbuff[index - 1];
}
template<class T>
T mytree<T>::getrightbrother(int elemval) const
{
int index = _find(elemval);//先找到这个元素的下标
if (index < 0)
{
throw "发生错误";
}
if (index % 2 == 0)
{
throw "this is right";
}
return pbuff[index + 1];
}
template<class T>
int mytree<T>::_find(T const & findval) const
{
for (int i = 0; i < len; i++)
{
if (findval == pbuff[i])
{
return i;
}
}
return -1;
}
template<class T>
void mytree<T>::_printftree(int index)
{
if (index < len)
{
//先序的打印方法
printf("%d\n", pbuff[index]);//打印根节点
_printftree(2 * index + 1);//打印左子树
_printftree(2 * index + 2);//打印右子树
//中序打印
//_printftree(2 * index + 1);//打印左子树
//printf("%d\n", pbuff[index]);//打印根节点
//_printftree(2 * index + 2);//打印右子树
//后序打印
// _printftree(2 * index + 1);//打印左子树
// _printftree(2 * index + 2);//打印右子树
// printf("%d\n", pbuff[index]);//打印根节点
}
}
main.cpp
#include<iostream>
#include"binarytree.h"
using namespace std;
int main()
{
mytree<int> ms;
int arr[10] = { 0,1,2,3,4,5,6,7,8,9};
ms.inittree(arr, 10);
for (int i = 0; i <5; i++)
{
ms.appendnode((i+1)*10);
}
ms.printftree();
return 0;
}