SDUTOJ 3374 数据结构实验之查找二:平衡二叉树
题目链接:http://acm.sdut.edu.cn/onlinejudge2/index.php/Home/Index/problemdetail/pid/3374.html
题目大意
分析
代码如下
#include <bits/stdc++.h>
using namespace std; #define INIT() ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define Rep(i,n) for (int i = 0; i < (int)(n); ++i)
#define For(i,s,t) for (int i = (int)(s); i <= (int)(t); ++i)
#define rFor(i,t,s) for (int i = (int)(t); i >= (int)(s); --i)
#define ForLL(i, s, t) for (LL i = LL(s); i <= LL(t); ++i)
#define rForLL(i, t, s) for (LL i = LL(t); i >= LL(s); --i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
#define rforeach(i,c) for (__typeof(c.rbegin()) i = c.rbegin(); i != c.rend(); ++i) #define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl #define LOWBIT(x) ((x)&(-x)) #define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define UNIQUE(x) x.erase(unique(x.begin(), x.end()), x.end())
#define REMOVE(x, c) x.erase(remove(x.begin(), x.end(), c), x.end()); // 删去 x 中所有 c
#define TOLOWER(x) transform(x.begin(), x.end(), x.begin(),::tolower);
#define TOUPPER(x) transform(x.begin(), x.end(), x.begin(),::toupper); #define ms0(a) memset(a,0,sizeof(a))
#define msI(a) memset(a,0x3f,sizeof(a))
#define msM(a) memset(a,-1,sizeof(a)) #define MP make_pair
#define PB push_back
#define ft first
#define sd second template<typename T1, typename T2>
istream &operator>>(istream &in, pair<T1, T2> &p) {
in >> p.first >> p.second;
return in;
} template<typename T>
istream &operator>>(istream &in, vector<T> &v) {
for (auto &x: v)
in >> x;
return in;
} template<typename T>
ostream &operator<<(ostream &out, vector<T> &v) {
Rep(i, v.size()) out << v[i] << " \n"[i == v.size()];
return out;
} template<typename T1, typename T2>
ostream &operator<<(ostream &out, const std::pair<T1, T2> &p) {
out << "[" << p.first << ", " << p.second << "]" << "\n";
return out;
} inline int gc(){
static const int BUF = 1e7;
static char buf[BUF], *bg = buf + BUF, *ed = bg; if(bg == ed) fread(bg = buf, , BUF, stdin);
return *bg++;
} inline int ri(){
int x = , f = , c = gc();
for(; c<||c>; f = c=='-'?-:f, c=gc());
for(; c>&&c<; x = x* + c - , c=gc());
return x*f;
} template<class T>
inline string toString(T x) {
ostringstream sout;
sout << x;
return sout.str();
} inline int toInt(string s) {
int v;
istringstream sin(s);
sin >> v;
return v;
} //min <= aim <= max
template<typename T>
inline bool BETWEEN(const T aim, const T min, const T max) {
return min <= aim && aim <= max;
} typedef long long LL;
typedef unsigned long long uLL;
typedef vector< int > VI;
typedef vector< bool > VB;
typedef vector< char > VC;
typedef vector< double > VD;
typedef vector< string > VS;
typedef vector< LL > VL;
typedef vector< VI > VVI;
typedef vector< VB > VVB;
typedef vector< VS > VVS;
typedef vector< VL > VVL;
typedef vector< VVI > VVVI;
typedef vector< VVL > VVVL;
typedef pair< int, int > PII;
typedef pair< LL, LL > PLL;
typedef pair< int, string > PIS;
typedef pair< string, int > PSI;
typedef pair< string, string > PSS;
typedef pair< double, double > PDD;
typedef vector< PII > VPII;
typedef vector< PLL > VPLL;
typedef vector< VPII > VVPII;
typedef vector< VPLL > VVPLL;
typedef vector< VS > VVS;
typedef map< int, int > MII;
typedef unordered_map< int, int > uMII;
typedef map< LL, LL > MLL;
typedef map< string, int > MSI;
typedef map< int, string > MIS;
typedef set< int > SI;
typedef stack< int > SKI;
typedef queue< int > QI;
typedef priority_queue< int > PQIMax;
typedef priority_queue< int, VI, greater< int > > PQIMin;
const double EPS = 1e-;
const LL inf = 0x7fffffff;
const LL infLL = 0x7fffffffffffffffLL;
const LL mod = 1e9 + ;
const int maxN = 1e2 + ;
const LL ONE = ;
const LL evenBits = 0xaaaaaaaaaaaaaaaa;
const LL oddBits = 0x5555555555555555; template < typename T >
struct AVLTreeNode {
T key;
int num;
int height;
AVLTreeNode< T > *lchild, *rchild; AVLTreeNode(T value, AVLTreeNode< T > *l, AVLTreeNode< T > *r) : key(value), lchild(l), rchild(r){ num = ; }
}; template < typename T >
class AVLTree {
public:
AVLTree() { root = nullptr; sz = ; } //构造函数
~AVLTree() { destory(); } //析构函数 void preOrder() { preOrder(root); } //前序遍历AVL树
void inOrder() { inOrder(root); } //中序遍历AVL树
void postOrder() { postOrder(root); } //后序遍历AVL树 void destory() { destory(root); } //销毁AVL树 void insert(T key) { insert(root, key); } //插入指定值的节点
void remove(T key) { remove(root, key); } //移除指定值的节点
void remove(AVLTreeNode< T >* pdel) { remove(root, pdel->key); } //移除指定值的节点 AVLTreeNode< T >* search_recurse(T key) { search_recurse(root, key); } //利用递归算法进行指定值的查找
AVLTreeNode< T >* search_iterator(T key) { search_iterator(root, key); } //利用迭代算法进行指定值的查找
T minimum(); //返回AVL中的最小值
T maximum(); //返回AVL中的最大值 int height() { return height(root); } //返回树的高度 bool empty() { return root == nullptr; } int size() { return sz; } //private:
AVLTreeNode< T >* root; //AVL树的根节点
int sz; private:
void preOrder(AVLTreeNode< T >* rt) const;
void inOrder(AVLTreeNode< T >* rt) const;
void postOrder(AVLTreeNode< T >* rt) const; void destory(AVLTreeNode< T >* &rt); int height(AVLTreeNode< T >* rt);
void updateHeight(AVLTreeNode< T >* rt); AVLTreeNode< T >* insert(AVLTreeNode< T >* &rt, T key);
AVLTreeNode< T >* remove(AVLTreeNode< T >* &rt, T key);
AVLTreeNode< T >* remove(AVLTreeNode< T >* &rt, AVLTreeNode< T >* pdel); //删除AVL树中节点pdel,并返回被删除的节点 AVLTreeNode< T >* minimum(AVLTreeNode< T >* rt) const;
AVLTreeNode< T >* maximum(AVLTreeNode< T >* rt) const; AVLTreeNode< T >* search_recurse(AVLTreeNode< T >* rt, T key) const;
AVLTreeNode< T >* search_iterator(AVLTreeNode< T >* rt, T key) const; AVLTreeNode< T >* L_Rotation(AVLTreeNode< T >* rt); //单旋:左旋操作
AVLTreeNode< T >* R_Rotation(AVLTreeNode< T >* rt); //单旋:右旋操作
AVLTreeNode< T >* LR_Rotation(AVLTreeNode< T >* rt); //双旋:先左旋后右旋操作
AVLTreeNode< T >* RL_Rotation(AVLTreeNode< T >* rt); //双旋:先右旋后左旋操作 }; /*返回一棵树的高度*/
template < typename T >
int AVLTree< T >::height(AVLTreeNode< T >* rt) {
if (rt != nullptr) return rt->height;
return ; //如果是空树,高度为0
}; template < typename T >
void AVLTree< T >::updateHeight(AVLTreeNode< T >* rt) {
rt->height = max(height(rt->lchild), height(rt->rchild)) + ;
} /*左旋转操作*/
/*rt为最小失衡子树的根节点*/
/*返回旋转后的根节点*/
template < typename T >
AVLTreeNode< T >* AVLTree< T >::L_Rotation(AVLTreeNode< T >* rt) {
AVLTreeNode< T >* rc = rt->rchild;
rt->rchild = rc->lchild;
rc->lchild = rt; updateHeight(rt);
updateHeight(rc); return rc;
}; /*右旋转操作*/
/*rt为最小失衡子树的根节点*/
/*返回旋转后的根节点*/
template < typename T >
AVLTreeNode< T >* AVLTree< T >::R_Rotation(AVLTreeNode< T >* rt) {
AVLTreeNode< T >* lc = rt->lchild;
rt->lchild = lc->rchild;
lc->rchild = rt; updateHeight(rt);
updateHeight(lc); return lc;
}; /*先右旋再左旋*/
/*rt为最小失衡子树的根节点*/
/*返回旋转后的根节点*/
template < typename T >
AVLTreeNode< T >* AVLTree< T >::RL_Rotation(AVLTreeNode< T >* rt) {
rt->rchild = R_Rotation(rt->rchild);
return L_Rotation(rt);
}; /*先左后右做旋转*/
/*rt为最小失衡子树的根节点*/
/*返回旋转后的根节点*/
template < typename T >
AVLTreeNode< T >* AVLTree< T >::LR_Rotation(AVLTreeNode< T >* rt) {
rt->lchild = L_Rotation(rt->lchild);
return R_Rotation(rt);
}; /*插入操作*/
/*递归地进行插入*/
/*返回插入后的根节点*/
template < typename T >
AVLTreeNode< T >* AVLTree< T >::insert(AVLTreeNode< T >* &rt, T key) {
if (rt == nullptr) { //寻找到插入的位置
rt = new AVLTreeNode< T >(key, nullptr, nullptr);
++sz;
}
else if (key > rt->key) { //插入值比当前结点值大,插入到当前结点的右子树上
rt->rchild = insert(rt->rchild, key);
if (height(rt->rchild) - height(rt->lchild) == ) { //插入后出现失衡
if (key > rt->rchild->key) rt = L_Rotation(rt); // RR型,左旋
else if (key < rt->rchild->key) rt = RL_Rotation(rt); // RL型,先右再左旋转
}
}
else if (key < rt->key) { //插入值比当前节点值小,插入到当前结点的左子树上
rt->lchild = insert(rt->lchild, key);
if (height(rt->lchild) - height(rt->rchild) == ) { //如果插入导致失衡
if (key < rt->lchild->key) rt = R_Rotation(rt); // LL型,右旋
else if (key > rt->lchild->key) rt = LR_Rotation(rt); // LR型,先左后右旋转
}
}
else {
++rt->num;
++sz;
}
updateHeight(rt);
return rt;
}; /*删除指定元素*/
template < typename T >
AVLTreeNode< T >* AVLTree< T >::remove(AVLTreeNode< T >* &rt, T key) {
if (rt != nullptr) {
if (key == rt->key) {
if(rt->num > ) {
--rt->num;
--sz;
}
//因AVL也是二叉排序树,删除节点要维护其二叉排序树的条件
else if (rt->lchild != nullptr && rt->rchild != nullptr) { //若左右都不为空
// 左子树比右子树高,在左子树上选择节点进行替换
if (height(rt->lchild) > height(rt->rchild)) {
//使用左子树最大节点来代替被删节点,而删除该最大节点
int tmp = maximum(rt->lchild)->key; //左子树最大节点值
rt->key = tmp; //将最大节点的值覆盖当前结点
rt->lchild = remove(rt->lchild, tmp); //递归地删除最大节点,因为沿途所有节点又要判断平衡性
}
else { //在右子树上选择节点进行替换
//使用最小节点来代替被删节点,而删除该最小节点
int tmp = minimum(rt->rchild)->key; //右子树的最小节点值
rt->key = tmp; //将最小节点值覆盖当前结点
rt->rchild = remove(rt->rchild, tmp); //递归地删除最小节点
}
}
else {
AVLTreeNode< T >* ptmp = rt;
if (rt->lchild != nullptr) rt = rt->lchild;
else if (rt->rchild != nullptr) rt = rt->rchild;
delete ptmp;
--sz;
return nullptr;
}
}
else if (key > rt->key) { //要删除的节点比当前节点大,则在右子树进行删除
rt->rchild = remove(rt->rchild, key);
//删除右子树节点导致不平衡:相当于情况二或情况四
if (height(rt->lchild) - height(rt->rchild) == ) {
//相当于在左子树上插入右节点造成的失衡(情况四)
if (height(rt->lchild->rchild) > height(rt->lchild->lchild)) rt = leftRightRotation(rt);
//相当于在左子树上插入左节点造成的失衡(情况二)
else rt = rightRotation(rt);
}
}
else if (key < rt->key) { //要删除的节点比当前节点小,则在左子树进行删除
rt->lchild= remove(rt->lchild, key);
//删除左子树节点导致不平衡:相当于情况三或情况一
if (height(rt->rchild) - height(rt->lchild) == ) {
//相当于在右子树上插入左节点造成的失衡(情况三)
if (height(rt->rchild->lchild) > height(rt->rchild->rchild)) rt = rightLeftRotation(rt);
//相当于在右子树上插入右节点造成的失衡(情况一)
else rt = leftRotation(rt);
}
}
return rt;
}
return nullptr;
}; /*递归查找指定元素*/
template < typename T >
AVLTreeNode< T >* AVLTree< T >::search_recurse(AVLTreeNode< T >* rt, T key) const {
if (rt != nullptr) {
if (key > rt->key) return search_recurse(rt->rchild,key);
else if(key < rt->key) return search_recurse(rt->lchild,key);
return rt;
}
return nullptr;
}; /*非递归查找指定元素*/
template < typename T >
AVLTreeNode< T >* AVLTree< T >::search_iterator(AVLTreeNode< T >* rt, T key) const {
while (rt != nullptr) {
if (key > rt->key) rt = rt->rchild;
else if (key < rt->key) rt = rt->lchild;
else return rt;
}
return nullptr;
}; /*先序遍历*/
template < typename T >
void AVLTree< T >::preOrder(AVLTreeNode< T >* rt) const {
if (rt != nullptr) {
cout << rt->key << endl;
preOrder(rt->lchild);
preOrder(rt->rchild);
}
}; /*中序遍历*/
template < typename T >
void AVLTree< T >::inOrder(AVLTreeNode< T >* rt) const {
if (rt != nullptr) {
inOrder(rt->lchild);
cout << rt->key << endl;
inOrder(rt->rchild);
}
}; /*后序遍历*/
template < typename T >
void AVLTree< T >::postOrder(AVLTreeNode< T >* rt) const {
if (rt != nullptr) {
postOrder(rt->lchild);
postOrder(rt->rchild);
cout << rt->key << endl;
}
} /*销毁AVL树*/
template < typename T >
void AVLTree< T >::destory(AVLTreeNode< T >* & rt) {
if (rt != nullptr) {
destory(rt->lchild); //递归销毁左子树
destory(rt->rchild); //递归销毁右子树
delete rt; //销毁根节点
rt = nullptr;
}
}; /*返回树中最大节点值*/
template < typename T >
AVLTreeNode< T >* AVLTree< T >::maximum(AVLTreeNode< T >* rt) const {
if (rt != nullptr) {
while (rt->rchild != nullptr) rt = rt->rchild;
return rt;
}
return nullptr;
}; template< typename T >
T AVLTree< T >::maximum() {
assert(this->empty());
AVLTreeNode< T >* presult = maximum(root);
if (presult != nullptr) return presult->key;
}; /*返回树中最小节点值*/
template < typename T >
AVLTreeNode< T >* AVLTree< T >::minimum(AVLTreeNode< T >* rt) const {
if (rt != nullptr) {
while (rt->lchild != nullptr) rt = rt->lchild;
return rt;
}
return nullptr;
}; template < typename T >
T AVLTree< T >::minimum() {
assert(this->empty());
AVLTreeNode< T >* presult = minimum(root);
if (presult != nullptr) return presult->key;
}; int N;
AVLTree< int > avl; int main(){
//freopen("MyOutput.txt","w",stdout);
//freopen("input.txt","r",stdin);
INIT();
cin >> N;
For(i, , N) {
int x;
cin >> x;
avl.insert(x);
}
cout << avl.root->key << endl;
return ;
}
SDUTOJ 3374 数据结构实验之查找二:平衡二叉树的更多相关文章
- SDUT 3374 数据结构实验之查找二:平衡二叉树
数据结构实验之查找二:平衡二叉树 Time Limit: 400MS Memory Limit: 65536KB Submit Statistic Problem Description 根据给定的输 ...
- 数据结构实验之查找二:平衡二叉树 (SDUT 3374)
#include <stdio.h> #include <string.h> #include <stdlib.h> struct node { int data; ...
- SDUT 3376 数据结构实验之查找四:二分查找
数据结构实验之查找四:二分查找 Time Limit: 20MS Memory Limit: 65536KB Submit Statistic Problem Description 在一个给定的无重 ...
- SDUT OJ 数据结构实验之二叉树二:遍历二叉树
数据结构实验之二叉树二:遍历二叉树 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Problem Descr ...
- SDUT OJ 数据结构实验之串二:字符串匹配
数据结构实验之串二:字符串匹配 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Problem Descrip ...
- SDUT OJ 数据结构实验之排序二:交换排序
数据结构实验之排序二:交换排序 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Problem Descrip ...
- SDUT OJ 数据结构实验之链表二:逆序建立链表
数据结构实验之链表二:逆序建立链表 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Problem Descr ...
- SDUT 3399 数据结构实验之排序二:交换排序
数据结构实验之排序二:交换排序 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Problem Description 冒泡排序和快 ...
- SDUT 3379 数据结构实验之查找七:线性之哈希表
数据结构实验之查找七:线性之哈希表 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Problem Description 根据给定 ...
随机推荐
- 栈Stack --- 数组实现
栈最大的一个特点就是先进后出(FILO—First-In/Last-Out). /** * 栈:后进先出 * Created by fred on 2018/7/31. */ public class ...
- 三.通过jenkins对系统的监控(2)
在这记录下,通过HTTP Request Plugin监控系统的异常.和上一篇原理差不多. 1.首先需要安装HTTP Request Plugin.插件安装好后,在系统设置下面会新增如下配置: 具体有 ...
- 61、Queueable接口
public with sharing class QueueableSample implements Queueable{ private List<String> Name{get; ...
- jquery给表格绑值
jquery给表格绑值 直接上代码了 <!DOCTYPE html> <html> <head> <meta charset="UTF-8" ...
- AutoFac控制反转 转载https://blog.csdn.net/u011301348/article/details/82256791
一.AutoFac介绍 Autofac是.NET里IOC(Inversion of Control,控制反转)容器的一种,同类的框架还有Spring.NET,Unity,Castle等.可以通过NuG ...
- Java.util包教程
java.util.ArrayDeque 类提供了可调整大小的阵列,并实现了Deque接口.以下是关于阵列双端队列的要点: 数组双端队列没有容量限制,使他们增长为必要支持使用. 它们不是线程安全的;如 ...
- python获取每日涨跌停股票统计,封闭时间和打开次数
接口:limit_list 描述:获取每日涨跌停股票统计,包括封闭时间和打开次数等数据,帮助用户快速定位近期强(弱)势股,以及研究超短线策略. 限量:单次最大1000,总量不限制 积分:用户积2000 ...
- 使用Nuget重新安装packages.config中的组件的方法
Update-Package -ProjectName 'Ko.app.web' -Reinstall 该语句作用:按照packages.config中给出的程序组件,重新下载安装一遍.
- 初探Remoting双向通信(四)
原 初探Remoting双向通信(四) 2013年06月26日 11:11:32 喜欢特别冷的冬天下着雪 阅读数 2632 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blo ...
- KiCAD层颜色修改
KiCAD层颜色修改 KiCAD的PCB各层的颜色太过于暗淡,有时可能不适合操作者的习惯,尤其是铜层(布线层),这时候就需要去修改层的颜色,具体操作如下图:选择想要修改的层,双击左边颜色框框,进入之后 ...