C++模板实现二叉树(五 树的平衡之dsw算法)
2017-04-04 08:56
821 查看
二叉树的高效查找算法依赖于树的平衡.如果树高度不平衡,二叉树将退化成类似链表的效率,则二叉树的优势就不存在了.平衡二叉树的dsw算法提供了一种将二叉树转化成平衡二叉树的方法.
算法的核心思想是利用旋转.
1.通过右旋转生成主链.
2.通过左旋转生成平衡二叉树.
核心代码分析:
1.旋转过程中,拆链建链的顺序很重要,如果顺序不对,很容易造成自己指向自己从而导致死循环.
右旋转可参考如下顺序 a)将祖父节点的右指针指向孩子节点. b)将父节点的左指针指向孩子节点的右子树. c)将孩子节点的右指针指向父亲节点. 特别的,如果祖父节点为空,说明当前的转换点在根节点,此时,旋转之后,孩子节点将成为新的根节点a)中的操作不需要执行(因为没有祖父节点).
左旋转的前提是主链已经形成,即每个节点初始时只有右子树. 左旋转可参考如下顺序 a)保存孩子节点的左节点. b)将孩子节点的左节点指向父亲节点. c)父亲节点的右节点指向前面a)中保存的节点. d)祖父节点的右节点指向孩子节点(父节点被向下旋转). 特别的,如果祖父节点为空,说明当前转换点在根节点,此时旋转之后,孩子节点成为新的根节点.d)中的操作不需要执行(因为没有祖父节点).
2.创建主链过程中,观察点一直为父亲节点.如果父亲节点有左节点,则左节点就是孩子节点,以此进行右旋转.旋转完成后,孩子节点变成新的父亲节点.继续循环.如果不存在左节点,则祖父节点与父亲节点均向右下移一个位置,继续循环.特别的,如果父亲节点为根节点,下移的时候,将祖父节点设置为根节点.
3.创建平衡树的过程中,首先对主链进行预处理,进行n-m次左旋转.左旋转完成一次后,孩子节点变成新的祖父节点,再进行下一次左旋转.之后,如果m>1,则m/2. 从头开始进行m次左旋转,直到m<=1为止.
特别注意,由于左右旋转会改变节点的位置与指向,所以在创建主链与创建平衡树的过程中,要找准判断条件.比如左旋转时,下一次左旋转比上一次左旋转相比,从原主链上看,是向下了2个节点.但是使用
实现代码如下:
头文件中添加如下方法:
源文件中实现如下:
算法的核心思想是利用旋转.
1.通过右旋转生成主链.
2.通过左旋转生成平衡二叉树.
核心代码分析:
1.旋转过程中,拆链建链的顺序很重要,如果顺序不对,很容易造成自己指向自己从而导致死循环.
右旋转可参考如下顺序 a)将祖父节点的右指针指向孩子节点. b)将父节点的左指针指向孩子节点的右子树. c)将孩子节点的右指针指向父亲节点. 特别的,如果祖父节点为空,说明当前的转换点在根节点,此时,旋转之后,孩子节点将成为新的根节点a)中的操作不需要执行(因为没有祖父节点).
左旋转的前提是主链已经形成,即每个节点初始时只有右子树. 左旋转可参考如下顺序 a)保存孩子节点的左节点. b)将孩子节点的左节点指向父亲节点. c)父亲节点的右节点指向前面a)中保存的节点. d)祖父节点的右节点指向孩子节点(父节点被向下旋转). 特别的,如果祖父节点为空,说明当前转换点在根节点,此时旋转之后,孩子节点成为新的根节点.d)中的操作不需要执行(因为没有祖父节点).
2.创建主链过程中,观察点一直为父亲节点.如果父亲节点有左节点,则左节点就是孩子节点,以此进行右旋转.旋转完成后,孩子节点变成新的父亲节点.继续循环.如果不存在左节点,则祖父节点与父亲节点均向右下移一个位置,继续循环.特别的,如果父亲节点为根节点,下移的时候,将祖父节点设置为根节点.
3.创建平衡树的过程中,首先对主链进行预处理,进行n-m次左旋转.左旋转完成一次后,孩子节点变成新的祖父节点,再进行下一次左旋转.之后,如果m>1,则m/2. 从头开始进行m次左旋转,直到m<=1为止.
特别注意,由于左右旋转会改变节点的位置与指向,所以在创建主链与创建平衡树的过程中,要找准判断条件.比如左旋转时,下一次左旋转比上一次左旋转相比,从原主链上看,是向下了2个节点.但是使用
pa = pa->right->right;进行下移会出错,因为pa->right在左旋转时被重新指向其他位置了. 此时,需要设置新的gr指向原来的ch.通过新的gr进行下移操作就不会出错了.
实现代码如下:
头文件中添加如下方法:
bool dswBalance(); void createBackBone(); void createPerfectTree(); void rotationRight(BinNode<T>* gr, BinNode<T>* pa, BinNode<T>* ch); void rotationLeft(BinNode<T>* gr, BinNode<T>* pa, BinNode<T>* ch);
源文件中实现如下:
template <class T, unsigned int capacity> void BinSearchTree<T, capacity>::rotationRight(BinNode<T>* gr, BinNode<T>* pa, BinNode<T>* ch) { if (NULL == gr) //the current pa must be root, no gr case { pa->left = ch->right; ch->right = pa; root = ch; //In this case, ch should be the new root after rotate } else { gr->right = ch; pa->left = ch->right; ch->right = pa; } return; } template <class T, unsigned int capacity> void BinSearchTree<T, capacity>::rotationLeft(BinNode<T>* gr, BinNode<T>* pa, BinNode<T>* ch) { BinNode<T>* tmp = ch->left; ch->left = pa; pa->right = tmp; if (NULL == gr) { root = ch; } else { gr->right = ch; } return; } template <class T, unsigned int capacity> void BinSearchTree<T, capacity>::createBackBone() { BinNode<T>* gr = NULL; BinNode<T>* pa = root; BinNode<T>* ch = NULL; while (NULL != pa) { if (NULL != pa->left) //if has left child, rotate right { ch = pa->left; rotationRight(gr, pa, ch); pa = ch; //After rotate, he ch should be the pa in the next time loop } else //gr, pa, tmp move downto next right { if (root == pa) //pa is root case, when move downto next right, gr should be set to root { gr = root; } else { gr = gr->right; } pa = pa->right; } } } template <class T, unsigned int capacity> void BinSearchTree<T, capacity>::createPerfectTree() { unsigned int n = treeNodeNum; if (n <= 3) { return; } unsigned int m = pow(2, floor(log(n + 1)/log(2))) - 1; BinNode<T>* gr = NULL; BinNode<T>* pa = root; BinNode<T>* ch = root->right; for (unsigned int i = 0; i < n - m; i++) { rotationLeft(gr, pa, ch); gr = ch; pa = gr->right; if (NULL != pa) { ch = pa->right; } else { break; } //if bb33 ((NULL != pa->right) && (NULL != ch->right)) //{ // pa = pa->right->right; //The pa right should be changed in rorationLeft, can not use as // ch = ch->right->right; // if ((NULL == pa) || (NULL == ch)) // { // break; // } //} //else //{ // break; //} } while (m > 1) { m = m >> 1; BinNode<T>* gr = NULL; BinNode<T>* pa = root; BinNode<T>* ch = root->right; for (unsigned int i = 0; i < m; i++) { rotationLeft(gr, pa, ch); gr = ch; pa = gr->right; if (NULL != pa) { ch = pa->right; } else { break; } } } return; } template <class T, unsigned int capacity> bool BinSearchTree<T, capacity>::dswBalance() { bool result = false; if (isEmpty()) { result = false; } else { createBackBone(); createPerfectTree(); result = true; } return result; }
相关文章推荐
- C++模板实现二叉树(五 树的平衡之dsw算法)
- C++模板实现二叉树(五 树的平衡之dsw算法)
- C++模板实现二叉树(五 树的平衡之dsw算法)
- 检查一个二叉树是否平衡的算法分析与C++实现
- 检查一个二叉树是否平衡的算法分析与C++实现
- 用C++模板实现线性表的链式存储的基本算法(数据结构C++版 北京科海)
- 【数据结构与算法】二叉树给定两个节点的最短距离(C++实现)
- C++模板实现二叉树(六 AVL树基础与旋转)
- C++模板实现二叉树(七 AVL树的删除)
- 二叉树c++模板实现
- C++模板实现二叉树(七 AVL树的删除)
- [C++] 测试硬件popcnt(位1计数)指令与各种软件算法,利用模板实现静态多态优化性能
- 实现平衡二叉排序树的各种算法(包括二叉树的递归遍历、非递归遍历)
- C++模板数组实现有序数组的排列合并算法
- 二叉树的各种遍历算法C++实现
- c++模板实现二叉树,线索化,线索化遍历,非递归遍历及一些基本操作
- [C/C++] 先序建立二叉树| 先序、中序、后序遍历二叉树| 求二叉树深度、节点数、叶节点数 算法实现
- 平衡有序二叉树(AVL Tree)的C++实现
- 摘:数据结构各种算法实现(C++模板)
- C++实现二叉树,运用模板,界面友好,操作方便 运行流畅