首页后端开发ASP.NET代码详解AVL树的插入

代码详解AVL树的插入

时间2024-01-30 20:16:02发布访客分类ASP.NET浏览826
导读:收集整理的这篇文章主要介绍了代码详解AVL树的插入,觉得挺不错的,现在分享给大家,也给大家做个参考。AVL树被称为高度平衡的二叉搜索树,尽量降低二叉树的高度,来保持二叉树的平衡,减少树的平均搜索长度。AVL树的性质:1、左子树和右子树的高度...
收集整理的这篇文章主要介绍了代码详解AVL树的插入,觉得挺不错的,现在分享给大家,也给大家做个参考。AVL树被称为高度平衡的二叉搜索树,尽量降低二叉树的高度,来保持二叉树的平衡,减少树的平均搜索长度。

AVL树的性质:1、左子树和右子树的高度之差(绝对值)不超过1

2、树中的每棵子树都是AVL树,

3、每个节点都有一个平衡因子,取值为(-1,0,1),通过平衡因子来判断树的平衡。

AVL树的插入需要考虑以下的几种情况:(箭头表示要插入的方向和节点)

第一种情况:插入的节点在20的右边,但是这样导致10的平衡因子大于1所以需要进行旋转才能改变平衡因子

第二种情况:在左边插入,导致平衡因子也不满足条件,需要旋转

第三种情况:插入的节点可能不构成单旋,所以需要双旋来解决

第四种情况:与第三种情况相反的双旋

如此通过旋转就可以达到在插入的时候让此二叉树达到平衡。

实现代码如下:

//main函数#define _CRT_SECURE_NO_WARNINGS 1#includeiostream>
    #includeassert.h>
    using namespace std;
#include"AVLTree.h"int main(){
    	testAVLTree();
    	System("pause");
    	return 0;
}
    


//AVLTree  ---->
      被称为高度平衡的二叉搜索树//使用三叉链来实现此二叉平衡搜索树//性质:左右高度差不超过1 &
    &
     该树的左右子树都为二叉平衡树templateclass K,class V>
struct AVLTreeNode{
    	AVLTreeNodeK, V>
    * _left;
       	AVLTreeNodeK, V>
    * _right;
    	AVLTreeNodeK, V>
    * _parent;
    	K _key;
    	V _value;
    	int _bf;
     // 平衡因子	//构造函数	AVLTreeNode(const K&
     key,const V&
 value) :_left(NULL), _right(NULL), _parent(NULL)		, _key(key), _value(value), _bf(0)	{
}
}
    ;
    templateclass K,class V>
class AVLTree{
    	tyPEdef AVLTreeNodeK,V>
     Node;
public:	AVLTree() :_root(NULL)	{
}
    	//使用非递归的插入	bool Insert(const K&
     key, const V&
 value)	{
		//如果根节点不存在说明插入的节点是第一个节点,直接new 一个即可		if (_root == NULL){
    			_root = new Node(key, value);
    			return true;
		}
    		Node* cur = _root;
    		Node* parent = NULL;
		while (cur)		{
    			if (cur->
_key  key){
    				parent = cur;
    				cur = cur->
    _right;
			}
    			else if (cur->
    _key>
key){
    				parent = cur;
    				cur = cur->
    _left;
			}
			else{
    				return false;
			}
		}
    			//走到这里,说明这个节点不存在,先new			cur = new Node(key, value);
    			//比较插入节点的值与父节点的值,再考虑链上左还是右			if (parent->
_key  key){
    				parent->
    _right = cur;
    				cur->
    _parent = parent;
			}
    			else if (parent->
    _key>
key){
    				parent->
    _left = cur;
    				cur->
    _parent = parent;
			}
			else{
				while (parent)				{
    					//判断cur是插在了parent的左边还是右边,再判断平衡因子是++还是--					if (cur == parent->
_left){
    						parent->
    _bf--;
					}
					else{
    						parent->
    _bf++;
					}
    					//++或--之后,判断平衡因子是否等于2或等于-2					if (parent->
_bf == 0)    //等于0说明没有变,则跳出循环					{
    						break;
					}
    					else if (parent->
    _bf == 1 || parent->
_bf == -1)					{
    						cur = parent;
    						parent = cur->
    _parent;
					}
    					else if (parent->
    _bf == 2 || parent->
_bf == -2)//如果等于2或者等于-2则不再插入,先调节为二叉平衡树再插入					{
    						//根据平衡因子来判断需要调整的树是哪种类型,再选择单旋还是双旋						//如果父节点的平衡因子等于2,说明右子树比左子树高,再判断右子树的子树是在它的左边还是右边						if (parent->
_bf == 2)						{
    							if (cur->
_bf == 1){
    								RotateL(parent);
							}
							else{
    								RotateRL(parent);
							}
						}
						else						{
    							if (cur->
    _bf == -1)								RotateR(parent);
    							else								RotateLR(parent);
						}
					}
				}
			}
    			return true;
		}
    		//cur = parent;
	//右单旋	void RotateR(Node* parent)	{
    		//需要记录parent上面是否还有父亲节点		Node* ppNode = parent->
    _parent;
    		Node* subL = parent->
    _left;
    		Node* subLR = subL->
    _right;
    		parent->
    _left = subLR;
    		//如果subLR存在  就将它的父亲置为parent		if (subLR)			subLR->
    _parent = parent;
    		subL->
    _right = parent;
    		parent->
    _parent = subL;
		//如果parent等于根节点,说明已经到第一个节点,不需要调整,直接将subL作为根即可		if (parent == _root)		{
    			_root = subL;
    			subL->
    _parent = NULL;
		}
		else   //如果还没有到根节点还需要判断parent是左还是右		{
    			if (ppNode->
    _left == parent)				ppNode->
    _left = subL;
			else{
    				ppNode->
    _right = subL;
			}
    			subL->
    _parent = ppNode;
		}
	}
	//左单旋	void RotateL(Node* parent)	{
    		Node* ppNode = parent->
    _parent;
    		Node* subR = parent->
    _right;
    		Node* subRL = subR->
    _left;
    		parent->
    _right = subRL;
		//判断subRL是否存在		if (subRL){
    			subRL->
    _parent = parent;
					}
    		subR->
    _left = parent;
    		parent->
    _parent = subRL;
		if (_root == parent)		{
    			_root = subR;
    			subR->
    _parent = NULL;
		}
		else		{
    			if (ppNode->
    _left == parent)				ppNode->
    _left = subR;
    			else				ppNode->
    _right = subR;
    			subR->
    _parent = ppNode;
		}
	}
	//左右单旋	void RotateLR(Node* parent)	{
    		RotateL(parent->
    _right);
    		RotateR(parent);
	}
	//右左单旋	void RotateRL(Node* parent)	{
    		RotateR(parent->
    _left);
    		RotateL(parent);
	}
	void InOrder()	{
    		_InOrder(_root);
    		cout  endl;
	}
		void _InOrder(Node* root)	{
    		if (root == NULL)			return;
    		_InOrder(root->
    _left);
    		cout  root->
    _key  " ";
    		_InOrder(root->
    _right);
	}
	bool IsBalance()	{
    		return _IsBalance(_root);
	}
	bool _IsBalance(Node* root)	{
    		if (root == NULL)			return;
    		int leftheight = _Height(root->
    _left);
    		int rightheight = _Height(root->
    _right);
    		return abs(rightheight - leftheight)  2 &
    &
     _IsBalance(root->
    _left) &
    &
     _IsBalance(root->
    _right);
	}
	size_t _Height(Node* root)	{
    		if (root == NULL)			return 0;
    		size_t left = _Height(root->
    _left);
    		size_t right = _Height(root->
    _right);
    		return left >
     right ? left + 1 : right + 1;
	}
    PRivate:	Node* _root;
}
    ;
void testAVLTree(){
    	AVLTreeint, int>
     t;
	int a[] = {
 16,3,7,11,9,26,18,14,15}
    ;
    	for (int i = 0;
     i  (sizeof(a) / sizeof(a[0]));
 i++)	{
    		coutt.Insert(a[i], 0)endl;
	}
    	t.InOrder();
}
    

以上就是代码详解AVL树的插入的详细内容,更多请关注其它相关文章!

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!

插入详解

若转载请注明出处: 代码详解AVL树的插入
本文地址: https://pptw.com/jishu/592988.html
jquery怎么删除元素但保留子元素 实例详解sort()函数的原理和使用方法

游客 回复需填写必要信息