BST与AVL的C++模板实现

这篇博客介绍了如何使用C++实现BSTree和AVLTree,强调了在实现过程中需要注意的细节,并遵循《算法导论》中的思想,在树节点中增加了父节点。作者参考了其他资源并提供了一份经过测试的完整代码,欢迎读者反馈改进方案。
摘要由CSDN通过智能技术生成

C++实现BSTree与AVLTree

回顾树结构时,本打算写个小程序实现一下练练手。

而作为常见的树结构,BSTree与AVLTree 应该是最容易被提到的。关于这连个树结构,这里不负责讲解。

但是在实现的时候却发现有许多细节上处理需要注意。思想很简单,实现起来还是有一定难度的。像能轻松知道破解原理和步骤,但是实际破解却费时费力。

遵从 算法导论的思想 喜欢在 树节点中增加父节点。所以与其他实现可能有些不同。

本代码实现许多地方用了 一步一步写平衡二叉树 博文中的内容。文章写的蛮清晰,推荐以此为参考

网上有很多的思想介绍和伪码,但是具体能用的倒不多,下面给出自己编写的代码,测试且单步过,完全可用(可花了好几天...)

下面贴出源码

(源码可能有些冗余,如果有改进后更好的方式,可给我反馈一份 :-D )

//BST
//参考博客:http://www.cppblog.com/cxiaojia/archive/2014/03/02/187776.html

#ifndef _BSTREE_H
#define _BSTREE_H

#include <stdio.h>
#define  _CRT_RAND_S
#include <stdlib.h>
#include <iostream>
using namespace std;

//二叉树节点
template<class T>
class TreeNode
{
public:
	TreeNode():lson(NULL),rson(NULL),parrent(NULL),freq(1),hg(0){}
public:
	T data;								//数据
	int freq;							//频率,默认=1
	int hg;								//高度,默认=0
	TreeNode* lson;		//指向左儿子的地址
	TreeNode* rson;		//指向右儿子的地址
	TreeNode* parrent;	//指向父节点的地址
};

//BST树类的属性和方法声明
template<class T>
class BSTree
{
public:
	TreeNode<T>* root ;	//根

public:
	BSTree(TreeNode<T>* p=NULL){
		root = p;
	}
	TreeNode<T>* Search(T x);										//查找 data == x 的节点
	TreeNode<T>* Min(TreeNode<T>* x);						//返回最小节点(最左子节点)
	TreeNode<T>* Max(TreeNode<T>* x);					//返回最大节点(最右子节点)
	TreeNode<T>* Successor(TreeNode<T>* x);			//返回节点x的后继
	TreeNode<T>* Predecessor(TreeNode<T>* x);		//返回x的前趋
	TreeNode<T>* Insert(T x);					//插入,返回插入点
	void Insert2(T x);					//递归插入
	void InsertPt(TreeNode<T>* &node, T &x);	//在node下面插
	bool Delete(T x);					//删除
	void TraverseTree();				//遍历
	void InTraverNode(TreeNode<T>* node);		//中序遍历节点node
};


//AVL树属性和方法声明
template<class T>
class AVLTree:public BSTree<T>
{
//private:
//	TreeNode<T>* root;									//根节点

private:
//	void insertpri(TreeNode<T>* &node,T x);//插入
//	TreeNode<T>* findpri(TreeNode<T>* node,T x);//查找
//	void insubtree(TreeNode<T>* node);//中序遍历
//	void Deletepri(TreeNode<T>* &node,T x);//删除
	int height(TreeNode<T>* node);//求树的高度
	void SingRotateLeft(TreeNode<T>* &k2);//左左情况下的旋转
	void SingRotateRight(TreeNode<T>* &k2);//右右情况下的旋转
	void DoubleRotateLR(TreeNode<T>* &k3);//左右情况下的旋转
	void DoubleRotateRL(TreeNode<T>* &k3);//右左情况下的旋转

public:
	AVLTree(TreeNode<T>* p=NULL):BSTree(p){}
	void Insert2(T x);					//递归插入
	void InsertPt(TreeNode<T>* &node, T &x);	//在node节点下插入
	void Delete(T x);					//删除操作
	void DeletePt(TreeNode<T>* &node, T &x);	//在node节点下删除
	TreeNode<T>* Search(T x);		//查找接口
	void TraverseTree();				//遍历
	void InTraverNode(TreeNode<T>* node);		//中序遍历节点node

};

/
//					BST 树实现					
/
//在树中中查找 data为 x 的节点
template<class T>
TreeNode<T>* BSTree<T>::Search(T x)
{
	TreeNode<T>* tmp = root;
	while( tmp && tmp->data != x )
	{
		if( x < tmp->data )
			tmp = tmp->lson;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
AVL树的插入和删除操作都需要对树进行旋转操作来保持AVL树的平衡性。下面是C语言实现AVL树插入和删除操作: AVL树插入操作: ```c // AVL树节点定义 struct AVLNode { int key; int height; struct AVLNode* left; struct AVLNode* right; }; // 计算节点高度 int height(struct AVLNode* node) { if (node == NULL) { return 0; } return node->height; } // 右旋操作 struct AVLNode* rotate_right(struct AVLNode* y) { struct AVLNode* x = y->left; struct AVLNode* t2 = x->right; // 执行旋转 x->right = y; y->left = t2; // 更新高度 y->height = max(height(y->left), height(y->right)) + 1; x->height = max(height(x->left), height(x->right)) + 1; return x; } // 左旋操作 struct AVLNode* rotate_left(struct AVLNode* x) { struct AVLNode* y = x->right; struct AVLNode* t2 = y->left; // 执行旋转 y->left = x; x->right = t2; // 更新高度 x->height = max(height(x->left), height(x->right)) + 1; y->height = max(height(y->left), height(y->right)) + 1; return y; } // 计算平衡因子 int balance_factor(struct AVLNode* node) { if (node == NULL) { return 0; } return height(node->left) - height(node->right); } // 插入节点 struct AVLNode* avl_insert(struct AVLNode* node, int key) { // 执行BST插入 if (node == NULL) { struct AVLNode* new_node = (struct AVLNode*)malloc(sizeof(struct AVLNode)); new_node->key = key; new_node->height = 1; new_node->left = NULL; new_node->right = NULL; return new_node; } if (key < node->key) { node->left = avl_insert(node->left, key); } else if (key > node->key) { node->right = avl_insert(node->right, key); } else { // key已经存在,不需要插入 return node; } // 更新高度 node->height = max(height(node->left), height(node->right)) + 1; // 计算平衡因子 int bf = balance_factor(node); // 如果平衡因子大于1,需要进行旋转操作 if (bf > 1) { if (key < node->left->key) { // 左左情况,执行右旋操作 return rotate_right(node); } else { // 左右情况,先对左子树进行左旋操作,再对根节点进行右旋操作 node->left = rotate_left(node->left); return rotate_right(node); } } else if (bf < -1) { if (key > node->right->key) { // 右右情况,执行左旋操作 return rotate_left(node); } else { // 右左情况,先对右子树进行右旋操作,再对根节点进行左旋操作 node->right = rotate_right(node->right); return rotate_left(node); } } return node; } ``` AVL树删除操作: ```c // 查找最小值节点 struct AVLNode* find_min(struct AVLNode* node) { if (node == NULL) { return NULL; } if (node->left == NULL) { return node; } return find_min(node->left); } // 删除节点 struct AVLNode* avl_delete(struct AVLNode* node, int key) { // 执行BST删除 if (node == NULL) { return NULL; } if (key < node->key) { node->left = avl_delete(node->left, key); } else if (key > node->key) { node->right = avl_delete(node->right, key); } else { if (node->left == NULL || node->right == NULL) { // 被删除节点只有一个子节点或者没有子节点 struct AVLNode* temp = node->left ? node->left : node->right; if (temp == NULL) { // 没有子节点,直接删除 temp = node; node = NULL; } else { // 有一个子节点,用子节点替换被删除节点 *node = *temp; } free(temp); } else { // 被删除节点有两个子节点,找到右子树的最小值节点替换被删除节点 struct AVLNode* temp = find_min(node->right); node->key = temp->key; node->right = avl_delete(node->right, temp->key); } } if (node == NULL) { return NULL; } // 更新高度 node->height = max(height(node->left), height(node->right)) + 1; // 计算平衡因子 int bf = balance_factor(node); // 如果平衡因子大于1,需要进行旋转操作 if (bf > 1) { if (balance_factor(node->left) >= 0) { // 左左情况,执行右旋操作 return rotate_right(node); } else { // 左右情况,先对左子树进行左旋操作,再对根节点进行右旋操作 node->left = rotate_left(node->left); return rotate_right(node); } } else if (bf < -1) { if (balance_factor(node->right) <= 0) { // 右右情况,执行左旋操作 return rotate_left(node); } else { // 右左情况,先对右子树进行右旋操作,再对根节点进行左旋操作 node->right = rotate_right(node->right); return rotate_left(node); } } return node; } ``` 以上是AVL树的插入和删除操作的C语言实现。需要注意的是,AVL树的插入和删除操作都需要对树进行旋转操作来保持平衡,因此这些操作的时间复杂度是O(log n)。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值