二叉查找树简介:
1、用数组实现的二叉查找,查找效率为O(log2n),但是二叉查找的前提是数组有序,在数组中实现有序插入的效率太低 为O(n)。
2、研究二叉查找树,研究二叉查找树是在保证二叉查找效率的情况下,提高插入的效率。
3、简单的二叉查找树,如果没有策略保证其平衡性(任意叶节点到根节点的距离相差不超过1),最差情况下,会退化成链表(想象键值按升序插入一棵树,会产生一棵斜树)。插入和查找的效率都会退化成O(n)。所以,普通二叉查找树是无法保证效率的。
4、平衡二叉查找树,在构建二叉树的过程中保证了其平衡性(红黑树是一种实现方式)。
5、平衡二叉树(Balanced Binary Tree)具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
二叉查找树特点:
1、根节点左子树所有节点都小于根节点,右子树的所有节点都大于根节点(子树的逻辑关系也是如此)
2、对二叉查找树进行中序遍历,输出序列是一个递增序列
红黑树:
(2-节点:普通节点,2表示指针数量;3-节点:存储两个关键值,3个指针;具体见《算法第4版》P289)
1、红链接均为左连接(红链接:将两个普通2-节点连接起来构成一个3-节点);黑连接是普通连接。
2、每个节点都有指向自己的连接,如果指向它的连接是红的,该节点的颜色就是红的;否则是黑的。我们约定空连接(一般是叶子节点的指针)是黑色的,并非是指叶子节点是黑色的。
3、红链接均为左连接。
4、没有任何一个节点和两个红链接相连(红节点的孩子节点不能是红节点)。
5、该树是完美黑色平衡的,即任意空连接到根节点的路径上的黑连接数量相同。
构造步骤:
1、新插入的节点总是设为红节点,其与父节点的链接设置为红链接。
2、一旦违背了3、4项,就需要调整。如果是右连接则旋转,如果父节点与两个红链接相连,则将父节点的父节点的父节点(新插入节点的祖父变为红节点),新节点、父节点和爷爷节点变为黑节点。
3、2步骤会从新节点往上传递(类似将红色节点向上传递)
4、每次插入后,都会保证根节点总是黑色的,每次根节点由红变黑,黑色高度就会加1。
查找:
数组、链表、二叉查找树、平衡二叉查找树、散列表(Hash表)都可以实现查找。其中效率最高的是Hash,但是Hash底层用数组实现,有很多空节点,空间利用率不高。而且Hash无法实现有序性的相关操作。
普通二叉查找树程序,非平衡二叉树:
#include<iostream>
using namespace std;
typedef struct bnode
{
int data;
struct bnode *lchild;
struct bnode *rchild;
}bnode,*BiTree;
void insert(BiTree *T,int val) //记住这是指针的指针,在递归的时候要注意取址
{
if ((*T) == NULL)
{
(*T) = (bnode*)malloc(sizeof(bnode));
(*T)->data = val;
(*T)->lchild = NULL; //创建节点时,一定要对指针置空。对创建的变量赋初值是一个很好的习惯
(*T)->rchild = NULL;
return;
}
if (val < (*T)->data)
{
insert(&((*T)->lchild), val);
}
else
{
insert(&((*T)->rchild), val);
}
}
void midPrint(BiTree T)
{
if (T == NULL) return;
midPrint(T->lchild);
cout << T->data << " ";
midPrint(T->rchild);
}
int main()
{
BiTree T=NULL;
insert(&T,3);
insert(&T, 8);
insert(&T, 6);
insert(&T, 2);
insert(&T, 7);
midPrint(T);
system("pause");
return 0;
}