文章目录
前言
相较于线性结构,树型结构由一个根节点和多个叶子节点所组成,数据元素有一个前驱多个后继。
1、二叉树的基本概念及其性质
1、二叉树的特点:
- 每个结点最多只有两棵子树,不存在节点度大于2的结点
- 子树有左右之分,不能颠倒
2、两类特殊的二叉树:
- 满二叉树:除最后一层无子结点外,其他所有结点都含有左右两个子结点。
- 完全二叉树:特殊的满二叉树,设二叉树深度为n,则(n-1)为满二叉树,n层所有的子树不是一队的,就是单个的左子树,没有单个的右子树。
3、二叉树的遍历:
- 前序遍历:根—>左—>右
- 中序遍历:左—>根—>右
- 后序遍历:左—>右—>根
2、基础文本二叉树
最基础的二叉树结构,没有太多的特点。只是相较于链表有所强化。
3、几种特殊的二叉树:
1. 二叉排序树(BST)
- 如果根结点左子树不为空,左子树上的所有值都小于根节点,如果右子树不为空,右子树上所有结点 值都大于根结点。
- 如果对BST进行中序遍历,可以得到一个有序由小到大的数列。
tempalte< class T>
class BSTNODE {
T data;
BSTNODE<T>*leftchild;
BSTNODE<T>*rightchild;
}
tempalte<class T>
class BST{
public:
BSTNODE<T>::MakeEmpty(BSTNODE<T>* p) {
if (!P == NULL)
{
MakeEmpty(p->leftchild);
MakeEmpty(p->righchild);
free(T);
}
retrun NULL;
}
void findX(BSTNODE<T>* root,T x);
void InsertX(BSTNODE<T>* root, T x);
BSTNODE DeleteBST(BSTNODE<T>* p, T x);
BSTNODE deleteX(BSTNODE<T>* p);
}
二叉排序树的查找
template <class T>
void BST<T>::findX(BSTNODE<T>* root, T x) {
BSTNODE<T>* current;
current = root;
if (current->data > x) {
findX(current->leftchild);
return true;
}
else {
findX(current->rightchild);
return true;
}
return false;
}
二叉排序树的插入
template<class T>
void BST<T>::InsertX(BSTNODE<T>* root, T x) {
BSTNODE<T>* current;
if (!findX(BSTNODE<T>* root, element x)) {
current = new BSTNODE<T>()
current->data = x;
current->leftchild = cru->rightchild = NULL;
if (!root) {
root = current;
}
else if (x < current->data){
current->leftchild = current;
}
else {
current->rightchild = current;
}
}
}
二叉排序树的删除
- 被删除的结点是叶子
- 被删除的结点只有左子树或只有右子树
- 被删除的结点既有左子树也有右子树
template<class T>
void BST<T>::DeleteBST(BSTNODE<T>* p, T x) {
if (p== NULL) {
return false;
}
else {
if (x =p->data) {
deleteX(p);
return true;
}
else if (x < p->data) {
DeleteBST(p->leftchild, T x);
}
else if (x > p->data) {
DeleteBST(p->rightchild, T x);
}
}
}
template<class T>
void BST<T>::deleteX(BSTNODE<T>* p) {
BSTNODE<T>* current;
BSTNODE<T>* aux;
current = p;
if (!current->leftchild) {
aux = current;
current = current->leftchild;
}
else if (!current->rightchild) {
aux = current;
current = current->rightchild;
}
else if (current->leftchild && current->rightchild) {
aux = p->leftchild;
while (aux->rightchild){
current = aux;
aux = aux->rightchild;
}
p->data = aux->data;
if (current!=p){
current->rightchild = aux->leftchild;
}
else{
current->leftchild = aux->leftchild;
}
}
free(aux);
}
2. 平衡二叉树(AVL)
首先是一个二叉排序树,左右子树都是平衡二叉树,左右子树深度之差不超过1.
- 构造平衡二叉树的方法:在插入的过程中不断地进行平衡旋转技术。
1)单向右旋RR
2)单向左旋LL
3)先左后右旋转LR
4)先右后左旋转RL
二叉排序树声明
template<class T>
class AVLNode {
T data;
AVLNode<T>* leftchild;
AVLNode<T>* rightchild;
int height;
};
template<class T>
class AVL {
public:
AVLNode *AVL_make_empty(AVLNode<T>* p);
static int height(AVLNode<T>* p);
void AVL_Find(AVLNode<T>* p, T x);
void AVL_FindMin(AVLNode<T>* root);
void AVL_FindMax(AVLNode<T>* root);
AVLNode<T> *AVL_Insert(AVLNode<T>* p, T x);
AVLNode<T> *AVL_Delete(AVLNode<T>*p, T x);
AVLNode<T>* sLeftRotation(AVLNode<T>* p);
AVLNode<T>* sRightRotation(AVLNode<T>* p);
AVLNode<T>* LeftRightRotation(AVLNode<T>* p);
AVLNode<T>* RightLeftRotation(AVLNode<T>* p);
};
template<class T>
AVLNode<T>* AVL<T>::AVL_make_empty(AVLNode<T>* p) {
if (!p==NULL)
{
AVL_make_empty(p->leftchild);
AVL_make_empty(p->rightchild);
free(p);
}
}
Find、Findmin、Findmax的操作与BST一致,不多叙述。
平衡二叉树的插入
插入时要注意height,利用旋转保持平衡二叉树。
//高度计算
template<class T>
static int AVL<T>::height(AVLNode<T>* p) {
if (p==NULL)
{
return -1;
}
else
{
return p->height;
}
}
插入例程
template<class T>
AVLNode<T> *AVL<T>::AVL_Insert(AVLNode<T>* p, T x) {
if (p==NULL)
{
p = new AVLNode<T>();
if (p==NULL)
{
return false;
}
else
{
p->data = x;
p->height = 0;
p->leftchild = p->rightchild = NULL;
}
}
else if (x<p->data)
{
p->leftchild=AVL_Insert(p->leftchild,T x);
if (height(p->leftchild)-height(p->rightchild)==2)
{
if (x<p->leftchild->data)
{
p = sLeftRotation(AVLNode<T> * p);
}
else
{
p = LeftRightRotation(AVLNode<T> * p);
}
}
}
else if (x > p->data)
{
p->rightchild=AVL_Insert(p->rightchild, T x);
if (height(p->rightchild)-height(p->leftchild)==2)
{
if (x > p->leftchild->data)
{
p = sRightRotation(AVLNode<T> * p);
}
else
{
p = RightLeftRotation(AVLNode<T> * p);
}
}
}
p->height = max(height(p->leftchild), height(p->rightchild)) + 1;
retrun p;
}
template<class T>//static?
AVLNode<T>* AVL<T>::sLeftRotation(AVLNode<T>* p) {
AVLNode<T>* q;
q = p->leftchild;
p->leftchild = q->rightchild;
q->rightchild = p;
p->height = max(height(p->leftchild), height(p->rightchild)) + 1;
q->height = max(height(q->leftchild, p->rightchild)) + 1;
return q;
}
template<class T>
AVLNode<T>* AVL<T>::LeftRightRotation(AVLNode<T>* p) {
p->rightchild = sLeftRotation(p->rightchild);
return sRightRotation(p);
}
template<class T>
AVLNode<T>* AVL<T>::sRightRotation(AVLNode<T>* p){
AVLNode<T>* q;
q = p->rightchild;
p->rightchild = q->leftchild;
q->leftchild = p;
p->height = max(height(p->leftchild), height(p->rightchild)) + 1;
q->height = max(height(q->leftchild, p->rightchild)) + 1;
return q;
}
template<class T>
AVLNode<T>* AVL<T>::RightLeftRotation(AVLNode<T>* p) {
p->leftchild = sRightRotation(p->leftchild);
return sLeftRotation(p);
}
3. 哈夫曼树及哈夫曼编码
待补全
4. 堆(优先队列ADT)
小顶堆、大顶堆。 利用二叉树层次排序来确定是否为小顶堆或大顶堆。
https://blog.csdn.net/weixin_46650209/article/details/113614723
4、树与二叉树的转换
待补全