AVL树实现(插入删除)
2017-07-25 10:08
501 查看
在计算机科学中,AVL树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树。查找、插入和删除在平均和最坏情况下都是O(log n)。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。AVL树得名于它的发明者 G.M. Adelson-Velsky 和 E.M. Landis,他们在 1962 年的论文 “An algorithm for the organization of information” 中发表了它
好的,废话不多说了,有关AVL树的插入和删除详细介绍点击这里,直接上代码吧。
github地址:点击这里
测试文件
希望有错误能够指出
好的,废话不多说了,有关AVL树的插入和删除详细介绍点击这里,直接上代码吧。
github地址:点击这里
1 #ifndef _AVLTREE_H 2 #define _AVLTREE_H 3 4 #include<iostream> 5 #include<stack> 6 using namespace std; 7 8 template<class E,class K> 9 class AVLTree; 10 11 template<class E,class K> 12 class AVLNode //AVLNode结点的类定义 13 { 14 friend AVLTree<E,K>; 15 private: 16 E data; //平衡因子 17 AVLNode<E,K> *left,*right; 18 int bf; 19 public: 20 AVLNode():left(NULL),right(NULL),bf(0) 21 {} 22 AVLNode(E d,AVLNode<E,K> *l = NULL,AVLNode<E,K> *r = NULL):data(d),left(l),right(r),bf(0) 23 {} 24 }; 25 26 template<class E,class K> //平衡二叉搜索树的类定义 27 class AVLTree 28 { 29 private: 30 AVLNode<E,K> *root; //根结点 31 K RefValue; //结束标志 32 protected: 33 AVLNode<E,K>* Search(K x,AVLNode<E,K> *& ptr)const; 34 bool Insert(AVLNode<E,K> *& ptr,E& el); 35 bool Remove(AVLNode<E,K> *& ptr,E k); 36 void RotateL(AVLNode<E,K> *& ptr); //左单旋 37 void RotateR(AVLNode<E,K> *& ptr); //右单旋 38 void RotateLR(AVLNode<E,K> *& ptr); //先左后右单旋 39 void RotateRL(AVLNode<E,K> *& ptr); //先右后左单旋 40 int Height(AVLNode<E,K> *ptr)const; //求高度 41 public: 42 AVLTree():root(NULL) //构造空二叉树 43 {} 44 AVLTree(K Ref):RefValue(Ref),root(NULL) //构造函数 构造非空二叉树 45 {} 46 bool Insert(E& el) 47 { 48 return Insert(root,el); 49 } 50 bool Remove(E el) 51 { 52 return Remove(root,el); 53 } 54 friend istream& operator >> (istream& in,AVLTree<E,K>& Tree); 55 friend ostream& operator >> (ostream* out,AVLTree<E,K>& Tree); 56 int Height()const; 57 }; 58 59 template<class E,class K> 60 void AVLTree<E,K>::RotateL(AVLNode<E,K> *& ptr) //左单旋转算法 61 { 62 AVLNode<E,K> *subL = ptr; //要左旋的结点 63 ptr = subL->right; //原根的右子女 64 subL->right = ptr->left; //ptr成为新根前卸掉其左边负载 65 ptr->left = subL; //左单旋转,ptr为新根 66 ptr->bf = subL->bf = 0; //新的平衡因子 67 } 68 69 template<class E,class K> 70 void AVLTree<E,K>::RotateR(AVLNode<E,K> *& ptr) //右单旋转算法 71 { 72 AVLNode<E,K> *subR = ptr; //要右旋转的结点 73 ptr = subR->left; //原根的左子女 74 subR->left = ptr->right; //ptr成为新根前卸掉其右边负载 75 ptr->right = subR; //右单旋转,ptr为新根 76 ptr->bf = subR->bf = 0; //改变平衡因子 77 } 78 79 template<class E,class K> 80 void AVLTree<E,K>::RotateLR(AVLNode<E,K> *& ptr) //先左后右双旋转 81 { 82 AVLNode<E,K> *subL,*subR; // 83 subL = ptr->left; 84 subR = ptr; 85 ptr = subL->right; 86 subL->right = ptr->left; //ptr成为新根前甩掉它左边的负载 87 ptr->left = subL; //左单旋转,ptr成为新根 88 if(ptr->bf <= 0) //说明新增结点在左边给了subL 89 subL->bf = 0; 90 else //说明新增结点在右边给了subR 91 subL->bf = -1; 92 subR->left = ptr->right; //ptr成为新根前甩掉它右边的负载 93 ptr->right = subR; //右单旋转,ptr成为新根 94 if(ptr->bf <= 0) //说明新增结点在左边给了subL 95 subR->bf = 1; 96 else 97 subR->bf = 0; //说明新增结点在右边给了subR 98 ptr->bf = 0; 99 } 100 101 template<class E,class K> 102 void AVLTree<E,K>::RotateRL(AVLNode<E,K> *& ptr) //先右旋后左旋 103 { 104 AVLNode<E,K> *subR,*subL; 105 subR = ptr->right; 106 subL = ptr; 107 ptr = subR->left; 108 subR->left = ptr->right; //ptr成为新根前卸掉它右边的负载 109 ptr->right = subR; //右单旋转,ptr成为新根 110 if(ptr->bf >= 0) 111 subR->bf = 0; 112 else 113 subR->bf = 1; 114 subL->right = ptr->left; //ptr成为新根前卸掉它的左边的负载 115 ptr->left = subL; //左单旋转,ptr成为新根 116 if(ptr->bf >= 0) 117 subL->bf = -1; 118 else 119 subL->bf = 0; 120 ptr->bf = 0; 121 } 122 template<class E,class K> 123 bool AVLTree<E,K>::Insert(AVLNode<E,K> *& ptr,E& el) //在以ptr为根的的树中插入新元素,如果插入成功> ,函数返回true否则返回false 124 { 125 AVLNode<E,K> *pr = NULL,*p = ptr,*q; 126 int d; 127 stack<AVLNode<E,K> * > st; 128 while(p != NULL) //寻找插入位置 129 { 130 if(el == p->data) //找到等于el的结点,不插入 131 return false; 132 pr = p; //pr是待插入结点的父结点 133 st.push(pr); //否则用栈记忆查找路径 134 if(el < p->data) 135 p = p->left; 136 else 137 p = p->right; 138 } 139 p = new AVLNode<E,K>(el); //创建要插入的新结点 140 if(p == NULL) 141 { 142 cerr<<"out of memory"<<endl; 143 exit(1); 144 } 145 if(pr == NULL) //空树 146 { 147 ptr = p; 148 return true; 149 } 150 if(el < pr->data) 151 pr->left = p; //左结点插入 152 else 153 pr->right = p; //右结点插入 154 while(st.empty() == false) 155 { 156 pr = st.top(); //重新平衡化 157 st.pop(); //从栈中退出父结点 158 if(p == pr->left) //调整父结点的平衡因子 159 pr->bf--; 160 else 161 pr->bf++; 162 if(pr->bf == 0) //第一种情况,平衡退出 163 break; 164 if(pr->bf == 1 || pr->bf == -1) //第二种情况,|bf| = 1 165 p = pr; //回朔父结点是否存在 166 else //第三种情况,|bf| = 2 167 { 168 if(pr->bf == 2) 169 { 170 if(pr->right->bf > 0) 171 RotateL(pr); // \ 172 else 173 RotateRL(pr); // > 174 } 175 else 176 { 177 if(pr->left->bf < 0) 178 RotateR(pr); // / 179 else 180 RotateLR(pr); // < 181 } 182 break; 183 } 184 } 185 if(st.empty() == true) //调整到树的根结点 186 ptr = pr; 187 else 188 { //中间重新链接 189 q = st.top(); 190 if(q->data > pr->data) 191 q->left = pr; 192 else 193 q->right = pr; 194 } 195 return true; 196 } 197 198 199 template<class E,class K> 200 bool AVLTree<E,K>::Remove(AVLNode<E,K> *& ptr, E k) //在以ptr为根的AVL树中删除关键码为x的结点。如果删> 除成功,函数返回true,同时通过参数el返回被删结点元素,如果删除失败则函数返回false 201 { 202 if(ptr == NULL) 203 return false; 204 AVLNode<E,K> *pr = NULL,*p = ptr,*q; 205 int d,dd = 0; 206 stack<AVLNode<E,K> * > st; 207 while(p != NULL) //寻找删除位置 208 { 209 if(k == p->data) //找到等于k的结点,停止搜索 210 break; 211 pr = p; //pr始终是指向父结点 212 st.push(pr); //用栈来存储查找的路径 213 if(k < p->data) 214 p = p->left; 215 else 216 p = p->right; 217 } 218 if(p == NULL) 219 return false; 220 if(p->left != NULL && p->right != NULL) 221 { 222 pr = p; 223 st.push(pr); 224 q = p->left; 225 while(q->right != NULL) 226 { 227 pr = q; //pr是要删除的结点的父结点 228 229 q = q->right; 230 } 231 p->data = q->data; 232 p = q; //转换要删除的结点 233 } 234 235 if(p->left != NULL) 236 q = p->left; 237 else 238 q = p->right; 239 240 if(pr == NULL) //要删除的结点为根结点 241 ptr = q; 242 else 243 { 244 if(pr->left == p) //要删除的结点是父结点的左子树 245 pr->left = q; 246 else 247 pr->right = q; 248 while(!st.empty() ) 249 { 250 pr = st.top(); 251 st.pop(); 252 253 if(pr->left == q) 254 pr->bf++; 255 else 256 pr->bf--; 257 258 if(pr->bf == 1 || pr->bf == -1) 259 break; 260 else if(pr->bf == 0) 261 continue; 262 else 263 { 264 if(pr->bf > 0) 265 q = pr->right; 266 else 267 q = pr->left; 268 if(q->bf == 0) //单旋转 269 { 270 if(pr->bf > 0) 271 { 272 RotateL(pr); // \ 273 //bf 274 pr->left->bf = 1; 275 pr->bf = -1; 276 } 277 else 278 { 279 RotateR(pr); // / 280 pr->right->bf = -1; 281 pr->bf = 1; 282 } 283 } 284 else if(q->bf > 0) 285 { 286 if(pr->bf > 0) // \ // 287 RotateL(pr); 288 else // < 289 RotateLR(pr); 290 } 291 else 292 { 293 if(pr->bf < 0) // / 294 { 295 RotateR(pr); 296 } 297 else // > 298 { 299 RotateRL(pr); 300 } 301 } 302 break; 303 } 304 } 305 AVLNode<E,K> *ppr = st.top(); 306 if(ppr->data > pr->data) 307 ppr->left = pr; 308 else 309 ppr->right = pr; 310 } 311 //2 调整平衡因子 312 delete p; 313 return true; 314 } 315 316 #endif
测试文件
1 #include"./AVLTree.h" 2 3 int main() 4 { 5 AVLTree<int,int> avl(0); 6 int ar[] = {16,3,7,11,9,26,18,14,15}; 7 int n = sizeof(ar)/sizeof(int); 8 for(int i = 0; i < n; ++i) 9 { 10 avl.Insert(ar[i]); 11 } 12 13 avl.Remove(11); 14 15 return 0; 16 }
希望有错误能够指出
相关文章推荐
- AVL树的旋转、插入、删除及遍历C语言实现
- AVL树的插入删除查找算法实现和分析-1
- 纯C语言实现的AVL树(插入&删除&前序遍历输出)
- AVL树的插入与删除---Java实现
- AVL树的插入删除查找算法实现和分析-1(平衡因子法)
- AVL树的插入删除查找算法实现和分析-1(平衡因子法)
- AVL树非递归实现插入和删除例程
- AVL树插入、删除的分析与实现
- AVL树的插入_删除操作实现~
- AVL树的插入删除查找算法实现和分析-2(树高度法)
- AVL树的插入删除查找算法实现和分析-2(树高度法)
- AVL树的插入与删除(均为递归实现)
- AVL树插入删除算法详解(有图) -- C++语言实现
- 动态链表的创建、插入、查找、删除的C++实现
- 平衡二叉树(AVL)--查找、删除、插入(Java实现)
- 实现链表的初始化,按值查找,插入,删除
- C语言单向动态链表程序,实现链表的建立,合并,重新排序,链表元素的插入与删除,以及根据元素成员的值进行元素删除。
- 学习笔记——C语言实现单链表的基本操作:创建、输出、插入结点、删除结点、逆序链表
- 循环链表的插入删除实现
- 大顶堆的实现:插入insert和删除pop(C++)