AVL树

数据结构中文教材上的AVL树代码,调试过,加入了打印功能

// AVL tree implementation
#include<iostream>
using namespace std;

template <class Type>
class AVLTree{
	struct AVLNode{
		Type data;
		AVLNode* left;
		AVLNode* right;
		int height;

		AVLNode(const Type& element, AVLNode* l = NULL, AVLNode* r = NULL, int h = 0){
			data = element;
			left = l;
			right = r;
			height = h;
		}
	};

private:
	AVLNode* root;

	void insert(const Type& x, AVLNode* &t);
	bool remove(const Type& x, AVLNode* &t);
	void makeEmpty(AVLNode* &t);
	int height(AVLNode* t) const { return (t == NULL)? -1: t->height; }
	void LL(AVLNode* &t);
	void LR(AVLNode* &t);
	void RL(AVLNode* &t);
	void RR(AVLNode* &t);
	int max(int a, int b) { return (a > b)? a: b; }
	
	void print(AVLNode* root, int level);

public:
	AVLTree(AVLNode*t = NULL) { root = t; }
	~AVLTree(){ makeEmpty(root); }
	bool find(const Type& x) const;
	void insert(const Type& x) { insert(x, root); }
	void remove(const Type& x) { remove(x, root); }
	void print(){
		print(root, 0);
	}
};

template <class Type>
bool AVLTree<Type>::find(const Type& x) const {
	AVLNode* t = root;

	while (t != NULL && t->data != x){
		if (t->data > x) t = t->left;
		else t = t->right;
	}

	if (t == NULL) return false;
	else return true;
}

template <class Type>
void AVLTree<Type>::insert(const Type& x, AVLNode* &t){
	if (t == NULL) t = new AVLNode(x, NULL, NULL);
	else if (x < t->data){
		insert(x, t->left);
		if (height(t->left) - height(t->right) == 2){
			if (x < t->left->data) LL(t);
			else LR(t);
		}
	}
	else {
		insert(x, t->right);
		if (height(t->right) - height(t->left) == 2){
			if (x < t->right->data) RL(t);
			else RR(t);
		}
	}
	t->height = max(height(t->left), height(t->right)) + 1;
}

template <class Type>
void AVLTree<Type>::LL(AVLNode* &t){
	AVLNode* t1 = t->left;
	t->left = t1->right;
	t1->right = t;
	t->height = max(height(t->left), height(t->right)) + 1;
	t1->height = max(height(t1->left), height(t)) + 1;
	t = t1;
}

template <class Type>
void AVLTree<Type>::RR(AVLNode* &t){
	AVLNode* t1 = t->right;
	t->right = t1->left;
	t1->left = t;
	t->height = max(height(t->left), height(t->right)) + 1;
	t1->height = max(height(t), height(t1->right)) + 1;
	t = t1;
}

template <class Type>
void AVLTree<Type>::LR(AVLNode* &t){
	RR(t->left);
	LL(t);
}

template <class Type>
void AVLTree<Type>::RL(AVLNode* &t){
	LL(t->right);
	RR(t);
}

template <class Type>
bool AVLTree<Type>::remove(const Type& x, AVLNode* &t){
	bool stop = false;
	int subTree;

	if (t == NULL) return true;
	if (x < t->data) { stop = remove(x, t->left); subTree = 1; }
	else if (x > t->data) { stop = remove(x, t->right); subTree = 2; }
	else if (t->left != NULL && t->right != NULL){
		AVLNode* tmp = t->right;
		while(tmp->left != NULL) tmp = tmp->left;
		t->data = tmp->data;
		stop = remove(t->data, t->right);
		subTree = 2;
	}
	else {
		AVLNode* oldNode = t;
		t = (t->left != NULL)? t->left: t->right;
		delete oldNode;
		return false;
	}

	if (stop) return true;
	int bf;
	switch(subTree){
		case 1:
		bf = height(t->left) - height(t->right) + 1;
		if (bf == 0) return true;
		if (bf == 1) return false;
		if (bf == -1) {
			int bfr = height(t->right->left) - height(t->right->right);
			switch(bfr){
				case 0:
				RR(t); return true;
				case -1:
				RR(t); return false;
				default: RL(t); return false;
			}
		}
		break;
		case 2:
		bf = height(t->left) - height(t->right) - 1;
		if (bf == 0) return true;
		if (bf == -1) return false;
		if (bf == 1) {
			int bfl = height(t->left->left) - height(t->left->right);
			switch(bfl){
				case 0:
				LL(t); return true;
				case 1:
				LL(t); return false;
				default: LR(t); return false;
			}
		}
	}
}

template <class Type>
void AVLTree<Type>::print(AVLNode* root, int level){
	if (root == NULL) return;
	print(root->left, level + 1);
	cout << "Level " << level << ": " << root->data << endl;
	print(root->right, level + 1);
}

template <class Type>
void AVLTree<Type>::makeEmpty(AVLNode* &t){
	if (t == NULL) return;
	makeEmpty(t->left);
	makeEmpty(t->right);
	delete t;
}
主要的特点是在插入、删除等操作时用指针的引用做参数,以便在子树被更改时,根节点指向调整后的子树的根。AVLNode作为AVLTree的私有类,使得AVLTree可以任意使用AVLNode的成员,又保证了封装性。

利用AVL tree的思路,仿照英文教材上的bst代码另外写了一个AVL,代码见下:

// AVL tree implementation
#include<iostream>
using namespace std;

template <typename E>
class AVLNode{
private:
    E it;
    AVLNode* lc;
    AVLNode* rc;
    int height;

public:
	AVLNode(const E& e, AVLNode<E>* l = NULL, AVLNode<E>* r = NULL, int h = 0){
		it = e;
		lc = l;
		rc = r;
		height = h;
	}

	~AVLNode(){}
	E& element(){ return it; }
	void setElement(const E& e){ it = e; }
	inline AVLNode* left() const { return lc; }
	void setLeft(AVLNode<E>* b){ lc = b; }
	inline AVLNode* right() const { return rc; }
	void setRight(AVLNode<E>* b){ rc = b; }
	int& h(){ return height; }
};

template <typename E>
class AVL{
private:
	AVLNode<E>* root;

	AVLNode<E>* inserthelp(AVLNode<E>* root, const E& e);
	bool findhelp(AVLNode<E>* root, const E& e) const;
	void clearhelp(AVLNode<E>* root);
	AVLNode<E>* removehelp(AVLNode<E>* root, const E& e);
	void printhelp(AVLNode<E>*, int) const;
	int max(int x, int y){ return (x > y)? x: y; }

	AVLNode<E>* LL(AVLNode<E>* root);
	AVLNode<E>* RR(AVLNode<E>* root);
	AVLNode<E>* LR(AVLNode<E>* root);
	AVLNode<E>* RL(AVLNode<E>* root);

public:
	AVL(AVLNode<E>* r = NULL){ root = r; }
	~AVL(){ clearhelp(root); }

	void insert(const E& e){ root = inserthelp(root, e); }
	bool find(const E& e) const { return findhelp(root, e); }
	void remove(const E& e){ root = removehelp(root, e); }
	void print() const {       // Print the contents of the AVL
        if (root == NULL) cout << "The AVL is empty." << endl;
        else printhelp(root, 0);
	}
	int height(AVLNode<E>* root){
		if (root == NULL) return -1;
		else return root->h();
	}

};

template <typename E>
void AVL<E>::clearhelp(AVLNode<E>* root){
	if (root == NULL) return;
	clearhelp(root->left());
	clearhelp(root->right());
	delete root;
}

template <typename E>
bool AVL<E>::findhelp(AVLNode<E>* root, const E& e) const {
	if (root == NULL) return false;
	if (e < root->element()) return findhelp(root->left());
	else if (e > root->element()) return findhelp(root->right());
	else return true;
}

template <typename E>
AVLNode<E>* AVL<E>::LL(AVLNode<E>* root){
	AVLNode<E>* tmp = root->left();
	root->setLeft(tmp->right());
	tmp->setRight(root);
	root->h() = max(height(root->left()), height(root->right())) + 1;
	tmp->h() = max(height(tmp->left()), height(tmp->right())) + 1;
	root = tmp;
	return root;
}

template <typename E>
AVLNode<E>* AVL<E>::RR(AVLNode<E>* root){
	AVLNode<E>* tmp = root->right();
	root->setRight(tmp->left());
	tmp->setLeft(root);
	root->h() = max(height(root->left()), height(root->right())) + 1;
	tmp->h() = max(height(tmp->left()), height(tmp->right())) + 1;
	root = tmp;
	return root;
}

template <typename E>
AVLNode<E>* AVL<E>::LR(AVLNode<E>* root){
	root->setLeft(RR(root->left()));
	root = LL(root);
	return root;
}

template <typename E>
AVLNode<E>* AVL<E>::RL(AVLNode<E>* root){
	root->setRight(LL(root->right()));
	root = RR(root);
	return root;
}

template <typename E>
AVLNode<E>* AVL<E>::inserthelp(AVLNode<E>* root, const E& e){
	if (root == NULL) return new AVLNode<E>(e);
	if (e < root->element()) {
		root->setLeft(inserthelp(root->left(), e));
		if (height(root->left()) - height(root->right()) == 2){
			if (e < root->left()->element()) root = LL(root);
			else root = LR(root);
		}
	}
	else {
		root->setRight(inserthelp(root->right(), e));
		if (height(root->right()) - height(root->left()) == 2){
			if (e < root->right()->element()) root = RL(root);
			else root = RR(root);
		}
	}
	root->h() = max(height(root->left()), height(root->right())) + 1;
	return root;
}

template <typename E>
AVLNode<E>* AVL<E>::removehelp(AVLNode<E>* root, const E& e){
	if (root == NULL) return NULL;
	if (e < root->element()) {
		root->setLeft(removehelp(root->left(), e));
		if (height(root->right()) - height(root->left()) == 2){
			int dif = height(root->right()->left()) - height(root->right()->right());
			switch(dif){
				case 0: root = RR(root); break;
				case -1: root = RR(root); break;
				case 1: root = RL(root); break;
			}
		}
	}
	else if (e > root->element()) {
		root->setRight(removehelp(root->right(), e));
		if (height(root->left()) - height(root->right()) == 2){
			int dif = height(root->left()->left()) - height(root->left()->right());
			switch(dif){
				case 0: root = LL(root); break;
				case 1: root = LL(root); break;
				case -1: root = LR(root); break;
			}
		}
	}
	else {
		if (root->right() == NULL){
			AVLNode<E>* tmp = root;
			root = root->left();
			delete tmp;
		}
		else if (root->left() == NULL){
			AVLNode<E>* tmp = root;
			root = root->right();
			delete tmp;
		}
		else {
			AVLNode<E>* tmp = root->right();
			while (tmp->left() != NULL) tmp = tmp->left();
			root->setElement(tmp->element());
			root->setRight(removehelp(root->right(), root->element()));
		}
	}
	if (root != NULL) root->h() = max(height(root->left()), height(root->right())) + 1;
	return root;
}

template <typename E>
void AVL<E>::printhelp(AVLNode<E>* root, int level) const {
	if (root == NULL) return;
	printhelp(root->left(), level + 1);
	//for (int i = 0; i <= level; i++) cout << "  ";
	cout << "Level " << level << ": " << root->element() << endl;
	printhelp(root->right(), level + 1);
}
可以看到,没有将AVLNode作为AVL的内嵌类或将AVL声明为AVLNode的友元,AVL对结点的调用更加不方便,不得不在AVLNode中添加element(),setElement(),left(),setLeft()……等方法,还要考虑是否有const。在调用insert(),remove()等方法时,利用inserthelp(),removehelp()返回调整后的树根的地址,例如,root = inserthelp(root, e); root->setLeft(removehelp(root->left(), e)); 。总体上,中文教材的代码更加简洁,封装性更好。


运行环境:所有运行Windows Mobile 5.0及以上版本的PDA/手机 分辨率支持:240*320 GPS卫星地图导航专家(专业版)v0.91可以为您提供基于卫星地图的导航功能(卫星地图将根据您的网络情况实时下载),该版本为测试版(有效期至2007-12-31),如果您喜欢本软件,您可与作者联系有关正式版本的信息。如果您有任何问题或需求,也可与作者联系,作者将根据情况不断对该软件进行改进。 本软件的测试版为自由软件,您可以任意复制发布,但不能以任何方式进行修改、嵌入插件、加壳或反向工程,作者将保留对该软件的所有权利。 本软件的14大主要功能特点: 1、支持内置/外置/蓝牙GPS设备。 2、支持十条航线及10000个以上的航点设置。 3、支持航点编辑、选择功能。 4、支持手动、自动、智能、正反向导航模式。 5、支持位置、高度、速度、方向、距离、相对方向等导航功能。 6、支持罗盘动态显示方向及下一导航点的相对方向指示。 7、支持有线网络、GPRS、802.11b等网络模式,可自动选择。 8、支持卫星地图的实时按需下载,且支持地图缓存,已下载过的地图不会再次下载。 9、支持20层不同精度的卫星地图分辨率模式,且支持在地图模式下右击快速增加航点功能。 10、卫星地图支持定位导航模式和浏览模式,可使用OK键/上下左右键进行切换。 11、卫星地图导航模式下支持当前位置指示、下一航点指示、当前方向指示、导航方向指示、下一航点距离指示、下一航点的后续方向指示等功能。 12、软件适用于全球任何地点的定位/卫星地图导航功能,且定位模式下支持自动全程轨迹记录功能。 13、支持中国90个城市的POI搜索定位。 14、支持中国90个城市的路线搜索并能在卫星地图上显示全程路由。 2007-4-5 版本 0.9.1.3 1、修改由于微软软键盘控件引起的程序不稳定问题。 2、修改临时地图文件的保存方式,由一级目录保存改为两级目录保存,以解决在文件数量大时,性能下降的问题。 3、修改Internet的访问方法,使得Internet连接更为灵活稳定。 4、在航线编缉功能中,新增全选功能。 5、增加Internet连接Cache控制,下载完成后立即清除Internet Cache,以免占用系统存储空间。 2007-4-4 版本 0.9.1.2 1、修改在搜索POI位置信息时,由于部分POI位置不存在而导致的被搜索正常POI位置信息无法返回的BUG。 2、增加连接管理控制的可靠性,并增加相关提示。 3、修改卫星地图显示模块因数据处理不当,而造成的内存消耗过快,而导致的程序跳出或地图无法显示的BUG。 2007-4-3 版本0.9.1.1 一、新增功能 1、新增支持中国90个城市的POI(Point of Interest)搜索功能。 2、新增支持中国90个城市的行车路线搜索功能。 3、新增支持在卫星地图上显示全程路由功能。 二、修改BUG 1、修改当两个坐标点经度完全相同,纬度的差距小于0.00005度(约合0.18\")时,系统的导航方向判断可能不正确的问题。 2007-3-25 版本0.9.0.1 初始版本
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值