当前位置: 首页 > news >正文

AVL树相关操作

#include <iostream>

using namespace std;

//AVL树的节点
template<typename T>
class TreeNode
{
public:
    TreeNode() :lson(NULL), rson(NULL), freq(1), hgt(0){}
    T data;//
    int hgt;//以这个结点为根的树的高度
    int freq;//相同点的频率,我是不知道
    TreeNode* lson, *rson;//左右儿子的地址
};

template<typename T>
class AVLTree
{//AVLTree的类属性和方法声明
private:
    TreeNode<T>*root;//根节点
    void insertpri(TreeNode<T>*&node, T x);//插入
    TreeNode<T>* findpri(TreeNode<T>* node, T x);//查找
    void traversalpri(TreeNode<T>* node);//遍历
    void delpri(TreeNode<T>* &node, T x);//删除
    int height(TreeNode<T>* node);//辅助操作:高度
    void singLeft(TreeNode<T>* &k2);//左左操作
    void singRight(TreeNode<T>* &k2);//右右操作
    void doubleLeft(TreeNode<T>* &k3);//左右操作
    void doubleRight(TreeNode<T>* &k3);//右左操作
    int max(int cmpa, int cmpb);
public:
    AVLTree() :root(NULL){};
    void insert(T x);//插入接口
    void del(T x);//删除接口
    TreeNode<T>* find(T x);//查找接口
    void traversal();//遍历接口
};

//辅助操作:高度
template<typename T>
int AVLTree<T>::height(TreeNode<T>* node)
{
    if (node!=NULL)
        return node->hgt;
    return -1;
}

//辅助操作:比较高度
template<typename T>
int AVLTree<T>::max(int cmpa, int cmpb)
{
    return cmpa > cmpb ? cmpa : cmpb;
}

template<typename T>
void AVLTree<T>::singLeft(TreeNode<T>* &k2)
{//左左情况下旋转
    TreeNode<T>* k1;
    k1 = k2->lson;
    k2->lson = k1->rson;
    k1->rson = k2;
    k2 = k1;
    k2->hgt = max(height(k2->lson), height(k2->rson))+1;
    k1->hgt = max(height(k1->lson), height(k1->rson))+1;
}

template<typename T>
void AVLTree<T>::singRight(TreeNode<T>* &k2)
{//左左情况下旋转
    TreeNode<T>* k1;
    k1 = k2->rson;
    k2->rson = k1->lson;
    k1->lson = k2;
    k2 = k1;
    k2->hgt = max(height(k2->lson), height(k2->rson))+1;
    k1->hgt = max(height(k1->lson), height(k1->rson))+1;
}

template<typename T>
void AVLTree<T>::doubleLeft(TreeNode<T>* &k3)
{//左右的情况
    singRight(k3->lson);
    singLeft(k3);
}

//右左的情况
template<typename T>
void AVLTree<T>::doubleRight(TreeNode<T>* &k3)
{
    singLeft(k3->rson);
    singRight(k3);
}

//插入
template<typename T>
void AVLTree<T>::insertpri(TreeNode<T>* &node, T x)
{
    if (node == NULL)
    {
        node = new TreeNode<T>();
        node->data = x;
        return;
    }
    if (node->data>x)
    {
        insertpri(node->lson, x);//递归插入
        //插入后自我调整
        if (2 == height(node->lson) - height(node->rson))
        if (node->lson->data < x)
            doubleRight(node);
        else
            singLeft(node);
    }
    else if (node->data < x)
    {
        insertpri(node->rson, x);
        if (2 == height(node->rson) - height(node->lson))
        if (node->rson->data < x)
            singRight(node);
        else
            doubleRight(node);
    }
    else ++(node->freq);
    //取新的高度值,后面的+1很重要,作者都忘记了加
    node->hgt = max(height(node->lson), height(node->rson)) + 1;
}

//插入接口
template<typename T>
void AVLTree<T>::insert(T x)
{
    insertpri(root, x);
}

//查找
template<typename T>
TreeNode<T>* AVLTree<T>::findpri(TreeNode<T>* node, T x)
{
    if (node == NULL)
        return NULL;
    if (node->data > x)
        return findpri(node->lson, x);
    else if (node->data < x)
        return findpri(node->rson, x);
    else return node;
}

//查找
template<typename T>
TreeNode<T>* AVLTree<T>::find(T x)
{
    findpri(root, x);
}

//删除
template<typename T>
void AVLTree<T>::delpri(TreeNode<T>* &node,T x)
{
    if (node == NULL)
        return;
    if (x < node->data)
    {
        delpri(node->lson, x);
        //删除后的调整
        if (2 == height(node->rson) - height(node->lson))
        if (node->rson->lson&&height(node->rson->lson) > height(node->rson->rson))
            doubleRight(node);
        else
            singRight(node);
    }
    else if (x > node->data)
    {
        delpri(node->rson, x);
        if (2 == height(node->lson) - height(node->rson))
        if (node->lson->rson&&height(node->lson->rson) > height(node->lson->lson))
            doubleLeft(node);
        else
            singLeft(node);
    }
    else//找到后的操作
    {//先是有两个儿子的情况
        if (node->lson&&node->rson)
        {
            TreeNode<T>* t = node->lson;
            for (; t->rson; t = t->rson);
            node->data = t->data;
            node->freq = t->freq;
            //递归到一个儿子或没有儿子的情况
            delpri(node->lson, t->data);
            if (2 == height(node->rson) - height(node->lson))
            {//下面的if自己不会写
                if (node->rson->lson&&height(node->rson->lson) > height(node->rson->rson))
                    doubleRight(node);
                else
                    singRight(node);
            }
        }
        else
        {
            TreeNode<T>* t = node;
            if (node->lson == NULL)
                node = node->rson;
            else if (node->rson == NULL)
                node = node->lson;
            delete(t);
            t = NULL;
        }
    }
    if (node == NULL)return;//表示只有根节点,删了之后就没有了
    node->hgt = max(height(node->lson), height(node->rson));
    return;
}

template<typename T>
void AVLTree<T>::del(T x)
{
    delpri(root, x);
}

//中序遍历函数
template<class T>
void AVLTree<T>::traversalpri(TreeNode<T>* node)
{
    if (node == NULL) return;
    traversalpri(node->lson);//先遍历左子树
    cout << node->data << " ";//输出根节点
    traversalpri(node->rson);//再遍历右子树
}
//中序遍历接口
template<class T>
void AVLTree<T>::traversal()
{
    traversalpri(root);
}

int main()
{
    AVLTree<int> t;
    t.insert(3);
    t.insert(2);
    t.insert(1);
    t.insert(4);
    t.insert(5);
    t.insert(0);
    t.del(2);
    t.insert(2);
    t.traversal();
}

 

转载于:https://www.cnblogs.com/vhyc/p/5624871.html

相关文章:

  • Linux有问必答:Linux上如何查看某个进程的线程
  • C#动态调用WCF
  • ora_01810:格式代码出现两次
  • 前段
  • 用Redis存储Tomcat集群的Session
  • XForms - 更强大的Form
  • Git学习总结(6)——作为一名程序员这些代码托管工具你都知道吗?
  • PHP SPL笔记
  • 三十六计阅读手记
  • PAT (Advanced Level) 1112. Stucked Keyboard (20)
  • SVN代码丢失惊魂
  • 【jacob word】使用jacob,合并多个word为一个word文件
  • string、wstring、cstring、 char、 tchar、int、dword转换方法(转)
  • 对动画对概念和动画实现的思想的理解
  • pomelo连接redis
  • AzureCon上微软宣布了哪些容器相关的重磅消息
  • docker容器内的网络抓包
  • Fundebug计费标准解释:事件数是如何定义的?
  • Git初体验
  • LeetCode541. Reverse String II -- 按步长反转字符串
  • linux学习笔记
  • mysql 数据库四种事务隔离级别
  • PHP变量
  • Python学习笔记 字符串拼接
  • React的组件模式
  • Spring Security中异常上抛机制及对于转型处理的一些感悟
  • thinkphp5.1 easywechat4 微信第三方开放平台
  • ucore操作系统实验笔记 - 重新理解中断
  • 从0到1:PostCSS 插件开发最佳实践
  • 后端_MYSQL
  • 前端代码风格自动化系列(二)之Commitlint
  • 区块链分支循环
  • 删除表内多余的重复数据
  • 微信小程序填坑清单
  • 1.Ext JS 建立web开发工程
  • ​Python 3 新特性:类型注解
  • #大学#套接字
  • (2021|NIPS,扩散,无条件分数估计,条件分数估计)无分类器引导扩散
  • (二)斐波那契Fabonacci函数
  • (仿QQ聊天消息列表加载)wp7 listbox 列表项逐一加载的一种实现方式,以及加入渐显动画...
  • (附源码)springboot学生选课系统 毕业设计 612555
  • (十六)串口UART
  • (续)使用Django搭建一个完整的项目(Centos7+Nginx)
  • (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
  • (转)Sql Server 保留几位小数的两种做法
  • (转)德国人的记事本
  • (总结)Linux下的暴力密码在线破解工具Hydra详解
  • .form文件_一篇文章学会文件上传
  • .NET 6 在已知拓扑路径的情况下使用 Dijkstra,A*算法搜索最短路径
  • .net core开源商城系统源码,支持可视化布局小程序
  • .NET DevOps 接入指南 | 1. GitLab 安装
  • .NET Project Open Day(2011.11.13)
  • .NET Remoting Basic(10)-创建不同宿主的客户端与服务器端
  • .NET 程序如何获取图片的宽高(框架自带多种方法的不同性能)
  • .NET框架设计—常被忽视的C#设计技巧