二叉排序树是一种典型的动态查找表构造算法,动态要满足的特性就是要边查找边插入或删除。其解决了有序表的插入性能差以及顺序表的查找性能差问题。
二叉排序树的特性:
- 若左子树不空,左子树上所有结点的值均小于它的根结点值。
- 若右子树不空,右子树上所有结点的值均大于它的根结点值。
- 左右子树分别为二叉排序树。
其他函数的实现比较简单,重点是删除算法,因为情况比较多,考虑需要全面。
删除算法:
- 被删除的结点是叶子结点。
- 被删除的结点只有左子树或有右子树。
- 被删除的结点既有左子树又有右子树。
对于第三种我们选择删除结点的左子树的最右结点。
// 删除关键字key
int DeleteBST(BSTree &BST, KeyType key)
{
if (!BST)
{
return false;
}
else
{
if (BST->data == key)
{
return Delete(BST);
}
else if (BST->data > key)
{
return DeleteBST(BST->lchild, key);
}
else
{
return DeleteBST(BST->rchild, key);
}
}
}
// 删除指向p的结点
int Delete(BSTree &p)
{
BSTree q = nullptr;
if (!p->lchild)
{
q = p;
p = p -> rchild;
delete q;
}
else if (!p->rchild)
{
q = p;
p = p -> lchild;
delete q;
}
else
{
BSTree s = p -> lchild;
if (!s->rchild)
{
p->data = s->data;
p->lchild = s->lchild;
delete s;
}
else
{
while (s->rchild)
{
q = s;
s = s->rchild;
}
p->data = s->data;
q->rchild = s->lchild;
delete s;
}
}
return true;
}
完整代码:
- 头文件
//
// BinarySortTree.hpp
// BST
//
// Created by peiyu wang on 2019/3/21.
// Copyright © 2019 peiyu wang. All rights reserved.
//
#ifndef BinarySortTree_hpp
#define BinarySortTree_hpp
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
/*类型定义*/
typedef int KeyType;
struct BSTNode
{
KeyType data;
BSTNode* lchild;
BSTNode* rchild;
};
typedef BSTNode* BSTree;
/*BST函数列表*/
int CreateBSTree(BSTree &BST);
// 查找返回指向key的指针,若不存在则返回NULL
BSTree SearchBST_1(BSTree BST, KeyType key);
// 查找,若不存在key,则插入到正确的位置
int SearchBST_2(BSTree BST, KeyType key, BSTree f, BSTree *p);
// 插入
int InsertBST(BSTree &BST, KeyType key);
// 中序遍历二叉排序树,生成关键字序列
void InOrderTraverse_BST(BSTree BST);
// 删除关键字key
int DeleteBST(BSTree &BST, KeyType key);
// 删除指向p的结点
int Delete(BSTree &p);
#endif /* BinarySortTree_hpp */
- cpp实现文件
//
// BinarySortTree.cpp
// BST
//
// Created by peiyu wang on 2019/3/21.
// Copyright © 2019 peiyu wang. All rights reserved.
//
#include "BinarySortTree.hpp"
#include <vector>
/*BST函数列表*/
int CreateBSTree(BSTree &BST)
{
int N = 5;
vector<KeyType> keys;
cout << "输入你想要组成查找表中元素的个数(上限为100):" << endl;
cin.clear();//重置错误输入
cin.sync();//清空缓冲区
cin >> N;
cout << "----------------" << endl;
cout << "输入你想要组成查找表中的元素:" << endl;
cout << "----------------" << endl;
for (int i = 0; i < N; i++)
{
KeyType key;
key = i;
cin.clear();//重置错误输入
cin.sync();//清空缓冲区
cin >> key;
keys.push_back(key);
}
for (int i = 0; i < keys.size(); i++)
{
InsertBST(BST, keys[i]);
}
return true;
}
// 查找返回指向key的指针,若不存在则返回NULL
BSTree SearchBST_1(BSTree BST, KeyType key)
{
if (!BST)
{
return NULL;
}
else
{
if (BST->data == key)
{
return BST;
}
else if (BST->data > key)
{
return SearchBST_1(BST->lchild, key);
}
else
{
return SearchBST_1(BST->rchild, key);
}
}
}
// 查找,若不存在key,则返回到应该插入到正确的位置结点
int SearchBST_2(BSTree BST, KeyType key, BSTree f, BSTree &p)
{
if (!BST)
{
p = f;
return false;
}
else
{
if (BST->data == key)
{
p = BST;
return true;
}
else if (BST->data > key)
{
return SearchBST_2(BST->lchild, key, BST, p);
}
else
{
return SearchBST_2(BST->rchild, key, BST, p);
}
}
}
// 插入
int InsertBST(BSTree &BST, KeyType key)
{
BSTree p;
if (!SearchBST_2(BST, key, NULL, p))
{
BSTNode *temp = new BSTNode;
temp->data = key;
temp->lchild = NULL;
temp->rchild = NULL;
if (!p)
{
BST = temp;
}
else if (key > p->data)
{
p -> rchild = temp;
}
else
{
p -> lchild = temp;
}
return true;
}
return false;
}
// 中序遍历二叉排序树,生成关键字序列
void InOrderTraverse_BST(BSTree BST)
{
if (!BST)
return;
else
{
InOrderTraverse_BST(BST->lchild);
cout << BST->data << endl;
InOrderTraverse_BST(BST->rchild);
}
}
// 删除关键字key
int DeleteBST(BSTree &BST, KeyType key)
{
if (!BST)
{
return false;
}
else
{
if (BST->data == key)
{
return Delete(BST);
}
else if (BST->data > key)
{
return DeleteBST(BST->lchild, key);
}
else
{
return DeleteBST(BST->rchild, key);
}
}
}
// 删除指向p的结点
int Delete(BSTree &p)
{
BSTree q = nullptr;
if (!p->lchild)
{
q = p;
p = p -> rchild;
delete q;
}
else if (!p->rchild)
{
q = p;
p = p -> lchild;
delete q;
}
else
{
BSTree s = p -> lchild;
if (!s->rchild)
{
p->data = s->data;
p->lchild = s->lchild;
delete s;
}
else
{
while (s->rchild)
{
q = s;
s = s->rchild;
}
p->data = s->data;
q->rchild = s->lchild;
delete s;
}
}
return true;
}
- 测试函数
//
// main.cpp
// BST
//
// Created by peiyu wang on 2019/3/21.
// Copyright © 2019 peiyu wang. All rights reserved.
//
#include "BinarySortTree.hpp"
int main(int argc, const char * argv[]) {
BSTree BST;
CreateBSTree(BST);
InOrderTraverse_BST(BST);
DeleteBST(BST, 45);
BSTree p;
p = SearchBST_1(BST, 53);
cout << p->rchild->data << endl;
InOrderTraverse_BST(BST);
return 0;
}
查找性能的分析:
(平均查找长度)
不同树的平均查找长度不同,即使是相同序列插入顺序不同平均查找长度也不同。
比如插入1,2,3,4,5和3,1,2,5,4。
其ASL约为logN级别,但是研究发现有40%多的情况二叉排序树的平均性能弱化为N。我们知道显然当树的深度越深查找性能就越差,所以我们引入了平衡二叉树。