AVL树 (旋转平衡树 | BST | 可持久化结构 | 结构化编程)

导入和宏架构

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <stdbool.h>
#include <utility>

#if _STDC_VERSION_ >= 201710L
# define _STDC18_ 1
#else
# define _STDC18 0
#endif

#if __has_include(<stddef>) == 0
# include <stddef>
# if _STDC18_ == 0
#  ifndef nullptr_t
#  define nullptr_t NULL
#  endif
# endif
#endif

#define max(x,y)({\
    typeof(x) _x = x; \
    typeof(y) _y = y; \
    (void) ( &_x == &_y ); \
    _x>_y?_x:_y;\
})

#define del_r \
	std::pair<node *,_Bool>
#define fir \
	first
#define sec \
	second

结构体定义

typedef 
	struct _node
	{
		int _v,//value
			_h,//height
			_c,//capacity
			_s;//size
		struct _node *_left,
					 *_right;
	}node;

enum TAGS{
	INS = 1,
	DEL = 0,
};	

函数

static
	node *_new(int v)
	{
		node *_n = (node *)malloc(sizeof(node));
		_n->_v = v;
		_n->_h = 1;
		_n->_c = 1;
		_n->_s = 1;
		_n->_left = nullptr_t;
		_n->_right = nullptr_t;
		return _n;
	}	
static 
	inline int _height(node *_n){ return !(_n == nullptr_t)? _n->_h:0;}
static 
	inline int _size(node *_r){return !(_r == nullptr_t)?_r->_s:0;}
static
	node *_leftRotat(node **_r)
	{
		node *_nr = (*_r)->_right,
			 *_t = _nr->_left;
		(*_r)->_s = _size(_t->_right)
				 	+_size((*_r)->_right)
				 	+1;
		_t->_s = _size(_t->_left)
				+_size((*_r))
				+1;
		_nr->_left = (*_r);
		(*_r)->_right = _t;
		
		
		(*_r)->_h = 1+max(_height( (*_r)->_left),
					     +_height( (*_r)->_right) );
		return _nr;
	}
static 
	node *_rightRotat(node **_r)
	{
		node *_nr = (*_r)->_left,
			 *_t = _nr->_right;
		(*_r)->_s = _size(_t->_left)
				 	+_size((*_r)->_left)
				 	+1;
		_t->_s = _size(_t->_right)
				+_size((*_r))
				+1;
		_nr->_right = (*_r);
		(*_r)->_left = _t;
		
		(*_r)->_h = 1+max(_height( (*_r)->_left),
					     +_height( (*_r)->_right) );
		return _nr;
	}
static
	inline int _bal(node *_r){return _height(_r->_left) - _height(_r->_right);}
static
	inline node *_adj(node **_r,int TAG)
	{
		node *_nr = *_r;
		int bal = _bal(*_r);
		if(bal > 1)
		{
			if(TAG?_bal((*_r)->_left) > 0:_bal((*_r)->_left) >= 0)
				_nr = _rightRotat(_r);
			else
			{
				(*_r)->_left = _leftRotat(&((*_r)->_left));
				_nr = _rightRotat(_r);
			}	
		}
		else if(bal < -1)
		{
			if(TAG?_bal((*_r)->_right) < 0:_bal((*_r)->_right) <= 0)
				_nr = _leftRotat(_r);
			else
			{
				(*_r)->_right = _rightRotat(&((*_r)->_right));
				_nr = _leftRotat(_r);
			}
		}
		return _nr;
	}
static
	node *_ins(node **_r,int v)
	{
		if(_r == nullptr_t)
			return _new(v);
		++((*_r)->_s);
		if(v < (*_r)->_v)
			(*_r)->_left = _ins(&((*_r)->_left),v);
		else if(v > (*_r)->_v)
			(*_r)->_right = _ins(&((*_r)->_right),v);
		else ++((*_r)->_c);
		(*_r)->_h = 1+max(_height( (*_r)->_left),
					     +_height( (*_r)->_right) );
		_adj(_r,INS);
		return (*_r);
	}
	
static
	node *_fnd(node *_r,int v)
	{
		if(_r == nullptr_t)return nullptr_t;
		if(v < _r->_v)return _fnd(_r->_left,v);
		if(v > _r->_v)return _fnd(_r->_right,v);
		else return _r;
	}
static
	node *__del(node **_r,int v);
static 
	_Bool _del(node **_r,int v)
	{
		_Bool ret = 0;
		node *pret = nullptr_t;
		if(!(nullptr_t == (pret = _fnd((*_r),v))))
		{
			ret = 1;
			__del(_r,v);
		}
		return ret;
	}
static
	node *__del(node **_r,int v)
	{
		
		if(v < (*_r)->_v)
		{
			--((*_r)->_s);
			(*_r)->_left = __del(&((*_r)->_left),v);
		}
		else if(v > (*_r)->_v)
		{
			
			--((*_r)->_s);
			(*_r)->_right = __del(&((*_r)->_right),v);
		}
		else
		{
			if((*_r)->_left == nullptr_t
			&& (*_r)->_right == nullptr_t)
			{
				node *_t = *_r;
				*_r = nullptr_t;
				_r = nullptr_t;
				free(_t);
			}
			else if((*_r)->_left == nullptr_t
			&& !((*_r)->_right == nullptr_t))
			{
				node *_t = *_r;
				*_r = (*_r)->_right;
				free(_t);
			}
			else if((*_r)->_right == nullptr_t
			&& !((*_r)->_left == nullptr_t))
			{
				node *_t = *_r;
				*_r = (*_r)->_left;
				free(_t);
			}
			else
			{
				node *_cur = (*_r)->_right;
				while(!(_cur->_left == nullptr_t))
					_cur = _cur->_left;
				(*_r)->_v = _cur->_v;
				(*_r)->_c = _cur->_c;
				--((*_r)->_s);
				(*_r)->_right = __del(&((*_r)->_right),_cur->_v);
			}
		}
		_adj(_r,DEL);
		return (*_r);
	}

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
### 回答1: 山东大学数据结构课程设计要求实现AVLAVL是一种自平衡二叉搜索,具有良好的平衡性。在AVL中,每个节点的左子和右子的高度差不超过1。这种平衡性使得AVL的查找、插入和删除操作的时间复杂度都为O(logn),相较于其他平衡二叉搜索如红黑而言,AVL的查找性能更好。 实现AVL主要包括以下几个步骤: 1. 定义AVL的节点结构,包含数据域和左右子节点指针。 2. 实现AVL的插入操作。插入操作首先按照二叉搜索的规则找到要插入的位置,然后进行平衡调整。插入操作的平衡调整包括修改各个节点的平衡因子,根据不同的情况进行旋转操作,以保证平衡性。 3. 实现AVL的删除操作。删除操作首先按照二叉搜索的规则找到要删除的节点,然后进行平衡调整。删除操作的平衡调整包括修改各个节点的平衡因子,并根据不同的情况进行旋转操作,以保证平衡性。 4. 实现AVL的查找操作。查找操作按照二叉搜索的规则进行,即根据节点的大小关系不断在左子或右子中查找,直到找到目标节点或者为空节点。 在实现AVL的过程中,需要注意保持平衡性,并根据旋转操作的具体情况进行适当的调整。此外,还可以实现一些辅助函数,如计算节点的高度、更新节点的平衡因子等,以提高代码的可读性和维护性。 总之,山东大学数据结构课程设计要求实现AVL,通过定义节点结构和实现插入、删除和查找操作,可以实现一个具有良好平衡性和高效性能的AVL。 ### 回答2: 山东大学的数据结构课程设计中,我实现了AVLAVL是一种平衡二叉搜索,它的目的是保持平衡,以避免在搜索、插入和删除操作中产生较高的时间复杂度。AVL通过在每个节点上维护一个平衡因子(即左子高度减去右子高度),来确保平衡。 在我的实现中,首先我定义了一个AVLNode结构体,它包含了存储在节点中的数据以及两个指向左右子节点的指针。然后,我实现了一些基本操作函数,包括实现了插入函数、删除函数、查找函数等等。 在插入函数中,我通过递归地将新节点插入到中,并在插入完成后更新每个节点的平衡因子。这样,如果平衡因子超过了允许的范围(例如-1到1之外),我就需要进行相应的旋转操作来恢复平衡。 在删除函数中,我首先找到要删除的节点,并按照BST的规则进行删除操作。删除后,我还需要更新其父节点及其祖先节点的平衡因子,并通过旋转操作来保持平衡性。 除了插入和删除操作,我还实现了一些其他的功能,例如查找最小值、查找最大值、查找后继节点、查找前驱节点等。 在整个实现过程中,我注重了代码的可读性和效率。我使用了递归来处理的节点,利用平衡因子来判断平衡性,采用适当的旋转操作来维持平衡。通过测试样例,我验证了实现的正确性和性能。 ### 回答3: AVL是一种自平衡的二叉搜索,它的设计旨在解决二叉搜索在插入、删除等操作过程中可能导致不平衡的问题。 在山东大学数据结构课程设计中,我们可以采用以下步骤实现AVL: 1. 首先,我们需要定义AVL的节点结构,该结构包括左右孩子指针、平衡因子和关键字等信息。可以使用结构体来表示节点。 2. 接着,我们实现插入操作。当插入一个新的节点时,我们需要按照二叉搜索的规则找到插入位置,并将节点插入到相应的位置。插入完成后,我们需要逐级向上更新每个节点的平衡因子,并检查是否需要进行旋转操作。 3. 为了保持平衡性,我们需要定义旋转操作。主要有四种旋转操作:左单旋、右单旋、左-右双旋和右-左双旋。这些旋转操作能够通过改变节点之间的链接关系,使重新平衡。 4. 我们还需要实现删除操作。删除节点时,我们首先找到要删除的节点,并根据二叉搜索的规则调整结构。删除完成后,同样需要逐级向上更新每个节点的平衡因子,并检查是否需要进行旋转操作。 5. 最后,我们需要实现一些辅助函数,如计算的高度、查找最小值和最大值等。 在实现AVL时,需要注意维护平衡性,并确保插入和删除操作的正确性。此外,可在实现过程中添加必要的错误处理、输入验证和合理的注释,以提高代码的稳定性和可读性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XNB's Not a Beginner

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值