数据结构之二叉平衡树

二叉平衡树(AVL树),是带有平衡条件的二叉树查找树,这个平衡条件必须要容易保持,且必须保证树的深度是O(logN).。这里的平衡条件是左右子树高度差最多差1的二叉查找树。如果插入一个节点后破坏了平衡条件,那么就要做一些操作去恢复AVL树, 这里的操作一般称为旋转。

第一种情况是插入的节点在外面,即(左-左或右-右)、另一种是节点插在里面,即(左-右或右-左), 对于第一种情况我们采用单旋转,第二种采用双旋转,如下图:



代码实现

头文件 avl.h

#ifndef AVL_H_
#define AVL_H_

struct Node;
typedef int ElementType;
typedef struct Node *ptrToNode;
typedef struct Node *AVLTree;

// 插入节点
ptrToNode insert(AVLTree T,ElementType e);
// 左单旋转
ptrToNode singleRoateWithLeft(ptrToNode ptr);
// 左右双旋转
ptrToNode doubleRoateWithLeftRight(ptrToNode ptr);
// 右单旋转
ptrToNode singleRoateWithRight(ptrToNode ptr);
// 右左双旋转
ptrToNode doubleRoateWithRightLeft(ptrToNode ptr);
// 中序遍历
void midPrint(AVLTree T);
// 返回节点的高度
int height(AVLTree T);
// 返回最大值
int max(int a, int b);
// 销毁树
void destory(AVLTree &T);

#endif /* AVL_H_ */

具体实现 avl.cpp

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "avl.h"

struct Node {
	ElementType data;
	ptrToNode left;
	ptrToNode right;
	int height;
};

/**
 * 插入数据,构建二叉树
 */
ptrToNode insert(AVLTree T, ElementType e) {

	if (T == NULL) {
		T = (ptrToNode) malloc(sizeof(struct Node));
		T->data = e;
		T->height = 0;
		T->left = NULL;
		T->right = NULL;
	} else {
		if (e < T->data) {
			T->left = insert(T->left, e);
			if (height(T->left) - height(T->right) >= 2) {
				if (e < T->left->data) // 左-左
					T = singleRoateWithLeft(T);
				else// 左-右
					T = doubleRoateWithLeftRight(T);
			}
		} else {
			T->right = insert(T->right, e);
			if (height(T->right) - height(T->left) >= 2) {
				if (e > T->right->data) // 右-右
					T = singleRoateWithRight(T);
				else // 右-左
					T = doubleRoateWithRightLeft(T);
			}
		}
	}
	//更新节点高度
	T->height = max(height(T->left), height(T->right)) + 1;
	return T;
}

/**
 * 左单旋转
 */
ptrToNode singleRoateWithLeft(ptrToNode ptr) {
	ptrToNode k1, k2;
	k2 = ptr;
	k1 = k2->left;
	k2->left = k1->right;
	k1->right = k2;

	k2->height = max(height(k2->left), height(k2->right)) + 1;
	k1->height = max(height(k1->left), height(k1->right)) + 1;
	return k1;
}

/**
 * 又单旋转
 */
ptrToNode singleRoateWithRight(ptrToNode ptr) {
	ptrToNode k1, k2;
	k2 = ptr;
	k1 = k2->right;
	k2->right = k1->left;
	k1->left = k2;

	k2->height = max(height(k2->left), height(k2->right)) + 1;
	k1->height = max(height(k1->left), height(k1->right)) + 1;
	return k1;
}

/**
 * 左右双旋转
 */
ptrToNode doubleRoateWithLeftRight(ptrToNode ptr) {
	ptr->left = singleRoateWithRight(ptr->left);
	return singleRoateWithLeft(ptr);
}

/**
 * 右左双旋转
 */
ptrToNode doubleRoateWithRightLeft(ptrToNode ptr) {
	ptr->right = singleRoateWithLeft(ptr->right);
	return singleRoateWithRight(ptr);
}

/**
 * 中序遍历
 */
void midPrint(AVLTree T) {
	if (T == NULL)
		return;
	midPrint(T->left);
	//输出节点和高度
	printf("%d %d\n", T->data, T->height);
	midPrint(T->right);
}

/**
 * 返回节点高度
 */
int height(AVLTree T) {
	if (T == NULL)
		return -1;
	else
		return T->height;
}

/**
 * 返回最大值
 */
int max(int a, int b) {
	return a > b ? a : b;
}

/**
 * 销毁二叉树
 */
void destory(AVLTree &T) {
	if(T ==NULL)
		return;
	free(T);
	T =NULL;
}

测试

#include <stdio.h>
#include "avl.h"

int main() {
	AVLTree T = NULL;

	T = insert(T, 6);
	T = insert(T, 5);
	T = insert(T, 4);
	T = insert(T, 3);
	T = insert(T, 2);
	T = insert(T, 1);

	midPrint(T);
	destory(T);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/jygqm/article/details/80710627
今日推荐