1、二叉排序树
参考书:《数据结构(C语言)》–严蔚敏等编著,清华大学出版社。
二叉排序树的特征:
--二叉排序树是一棵空树或者具有以下特性的二叉树:
--若它的左子树不为空,则左子树上所有节点的值均小于它的根节点的值;
--若它的右子树不为空,则右子树上所有节点的值均大于等于它的根节点的值;
--它的左右子树也分别为一棵二叉排序树;
二叉排序树的存储结构与二叉树类似,加入了关键字存储结构,如下:
typedef struct {
KeyType key; //关键字域
InfoType otherinfo; //其他关键字域
}ElemType;
typedef struct BSTNode{
ElemType data; //数据域
struct BSTNode *lchold, *rchild; //左右孩子指针
}BSTNode, *BSTree;
2、二叉排序树的构建过程
二叉排序树是一种动态树表,树的结构通常不是一次性构成的,它是在查找的过程中,当树中不存在其关键字的时候,便向树中插入,使其满足二叉排序树的特点。新插入的节点一定是一个新添加的叶子结点
,并且此节点是在查找不成功时的路径的最后一个节点的左孩子或者右孩子上。二叉排序树的构建过程如下:
给定查找的关键字序列为;注:每次的插入操作都会看成是一次二叉排序树的查找,有就不再插入,没有就插入
(1)、当前树为NULL,首先从第一个关键字开始进行构建
;
(2)、插入24关键字,24 < 45,所以为45的左孩子,在插入构建的过程中一定注意二叉排序树的特点:左孩子 < 根节点 < 右孩子
;
(3)、依次插入到45节点后;
每次的插入操作都会看成试一次二叉排序树的查找
,当对第二个45关键字进行插入时会发现此时的二叉排序树的根节点的值与此关键字相等,就不在进行插入;
(4)、插入12关键字,顺着45 -> 24查找(12<45 且12<24),没有就进行插入;
24关键字也是一样,在树中45关键字的左孩子上查找到就不在进行插入;
(5)、插入90关键字,竖着45 -> 53 查找(90>45 且 90>53),没有就进行插入;
这样就构建完成,对于给定的一个关键字也是一样,若存在就此返回,若不存在就进行插入。
由此可以看出二叉排序树具有以下重要的两点性质:
二叉排序树的左-根-右遍历 (中序遍历) 是一个递增序列,如上图:12,24,45,53,90
二叉排序树的右-根-左遍历是一个递减序列,如上图:90,53,45,45,24,12
也就是说,一个无序序列可以通过构造一棵二叉排序树变成一个有序序列,即为排序;
二叉排序树的操作有查找、删除、插入,如何删除下期见;
3、二叉排序树的查找ASL
二叉排序树的ASL是根据它的形态决定的,也就是无序序列的顺序决定
,比如以下两棵树的ASL不一:
二叉排序树的总根节点永远是第一个关键字作为树的总根节点;
含有n个节点的二叉排序树的平均查找长度ASL和树的形态有关。
最好情况下:ASL=
log
2
\log_2
log2(n+1) -1 (形态比较均衡) O(
log
2
n
\log_2^n
log2n);
最坏情况下:ASL= n + 1 2 \frac{n+1}{2} 2n+1 (单支树的形态,与顺序表效率相同) O(n);
相关代码:
#include "stdio.h"
#include "stdlib.h"
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;
typedef int KeyType;
typedef struct {
KeyType key; //关键字域
} ElemType;
typedef struct BSTNode {
ElemType data; //数据域
struct BSTNode *lchild, *rchild; //左右孩子指针
} BSTNode, *BSTree;
Status InsertBST(BSTree &T,KeyType key);
Status InsertBST(BSTree &T,KeyType key) {
if(T == NULL) {
T = new BSTNode;
T->data.key = key; //插入节点
T->lchild = T->rchild = NULL; //插入后的节点的左右孩子均为NULL
return OK;
}
else if(key == T->data.key) return ERROR; //说明次二叉排序树中有此关键字
else if(key > T->data.key) return InsertBST(T->rchild,key); //递归插入右边
else return InsertBST(T->lchild,key); //递归插入左边
}
Status CreateBST(BSTree &T);
Status CreateBST(BSTree &T) {
T = NULL;
int key;
while(1) {
scanf("%d",&key);
if(key == -1) break; //-1 作为输入结束标志
InsertBST(T,key);
}
return OK;
}
Status RightOrderTraverse(BSTree T);
//右-->根-->左
Status RightOrderTraverse(BSTree T) {
if(T == NULL) return OK;
else {
RightOrderTraverse(T->rchild);
printf("%d ",T->data.key);
RightOrderTraverse(T->lchild);
}
return OK;
}
int main(void) {
BSTree T;
printf("请输入二叉排序树的数据:");
CreateBST(T);
printf("二叉排序树的大到小遍历(右-左)为:");
RightOrderTraverse(T);
return 0;
}
/*
构建二叉排序树,并对该二叉排序树按“右-根-左”顺序进行遍历,并输出该序列。
测试输入:10 44 8 22 77 6 99 10 -1 (-1作为输入结束标志)
预期输出:99 77 44 22 10 8 6
*/