简介
仔细观察BST会发现,虽然它有良好的“搜索”特性,也就是可以利用其节点之前的大小关系,很容易地从根节点开始往下走找到我们所要的节点,但它无法保证这种搜索所需要的时间长短,因为建立BST时节点的随机性可能会导致它极其“不平衡”。
如上图所示是一棵二叉树,显然左轻右重,事实上这棵树已经退化成了一条链表,在这棵树中搜索某一个节点的时间复杂度和链表是一样的。
这种左轻右重或者左重右轻的长短腿的情形,就是所谓的不平衡;一棵树不平衡,那么他的搜索性能将会受到影响。具体来讲,当树保持平衡时,其搜索时间复杂度是O(log2n);当树退化成链表时,其搜索时间复杂度是O(n),其他情况下树的平均搜索时间复杂度就介于这两者之间。现在的目标就是要升级我们的BST,使之带有自平衡的特性,当它发现自己的左腿长或右腿长时,会及时调整,保持平衡。
要达到此目的,首先需要量化所谓的“平衡”,其严格数学定义是:在一棵树中,如果其任意一个节点的左右子树的高度差绝对值小于或等于1,那么它就是平衡的。
下面是AVL树的算法实现,包括了节点的创建、插入、删除、旋转等算法。
算法实现
head4tree.h
//
// Description: 本文件为二叉树核心头文件。
// 任何使用本二叉树结构算法的程序,在包含本头文件之前
// 都需要将如下宏定义成二叉树节点需要表达的数据类型:
//
// TREE_NODE_DATATYPE
//
// 否则二叉树的节点数据类型一律默认为 int
//
#ifndef _HEAD4TREE_H_
#define _HEAD4TREE_H_
/*
* Any application applying this linked-tree data structure should
* define the macro "TREE_NODE_DATATYPE" before include this head
* file, otherwise, the macro will be defined to 'int' as follow.
*
*/
#ifndef TREE_NODE_DATATYPE
#define TREE_NODE_DATATYPE int
#endif
#include "commonheader.h"
#define MAX(a, b) ({
\
typeof(a) _a = a; \
typeof(b) _b = b; \
(void)(&_a == &_b);\
_a > _b? _a : _b; \
})
typedef TREE_NODE_DATATYPE tn_datatype;
typedef struct _tree_node
{
tn_datatype data;
struct _tree_node *lchild;
struct _tree_node *rchild;
#ifdef AVL
int height;
#endif
}treenode, *linktree;
void pre_travel(linktree, void (*handler)(linktree));
void mid_travel(linktree, void (*handler)(linktree));
void post_travel(linktree, void (*handler)(linktree));
void level_travel(linktree, void (*handler)(linktree));
linktree bst_insert(linktree root, linktree new);
linktree