静态查找
不涉及插入和删除操作的查找
例:线性表 (顺序查找 折半查找)
动态查找
设计插入和删除操作的查找
例:树表(二叉排序树的查找技术)
静态查找和动态查找均适用 :散列表
二叉排序树
(也称为二叉查找树):或者是一颗空二叉树,或者是具有下列性质的二叉树;
(1):若它的左子树不空,则左子树上所有节点的值均小于根节点的值;
(2):若它的右子树不空,则右子树上所有节点的值均大于根节点的值;
(3):它的左右子树也都是二叉排序树
想要得到一个按关键码有序的序列只需要中序遍历这个二叉排序树
二叉排序树的插入:若二叉排序树为空树,则新插入的节点为新的根节点,否则,新插入的节点必为一个新的叶子节点,其插入位置由查找过程得到。
一个无序序列可以通过构造一颗二叉排序树编程一个有序序列;
每次插入新的节点都是二叉排序树上新的叶子节点;
找到插入位置后,不必移动其他节点,仅需修改某个结点的指针;
在左子树/右子树的查找过程与在整棵树上查找过程相同;
新插入的节点没有破坏原有节点之间的关系。
二叉排序树的查找
早二叉排序树中查找给定值K的过程:
(1)如果root是空树,则查找失败;
(2)若k = root->data,则查找成功;
(3)若k<root ->data,则查找成功,则在root的左子树上查找
(4)在root的右子树上查找
上述过程一直持续到k被找到或者待查找的子树为空,如果待查找的子树为NULL,则查找失败
二叉排序树查找效率在于只需查找两个子树之一
平均查找长度(ASL)体现了查找算法的关键码的比较次数,
为了提高二叉排序树的搜索效率,将二叉排序树进行平衡化变成二叉平衡树
二叉排序树的删除:在二叉排序树上删除某个结点后,仍然保持二叉排序树的特性。
(1):被删除的节点是叶子节点;
(2):被删除的节点只有左子树或者只有右子树
(3):被删除的节点既有左子树也有右子树
最简单的一种:
情况1:被删除的节点是叶子节点
操作:将双亲节点中相应指针域的值改为空
情况2:被删除的节点只有左子树或者只有右子树
操作:
将双亲节点的相应指针域的值指向被删除节点的左子树(或者右子树)。
情况3:被删除的节点既有左子树也有右子树
操作:以其左子树中最大的节点(或者右子树中最小值的节点)替代之,然后再删除该节点。
来看源码:
#define _CRT_SECURE_NO_WARNINGS
#define DataType int
#include<iostream>
#define N 10
using namespace std;
struct BiNode
{
DataType data;
BiNode* lchild, *rchild;
};
class BiSortTree {
private:
BiNode* root;
private:
void insertBST(BiNode* &bt, DataType key);
void release(BiNode* bt);
bool deleteBST(BiNode* &bt, DataType key);
void deleteNode(BiNode* &bt);
BiNode *searchBST(BiNode *bt, DataType key);
public:
BiSortTree(DataType array[], int arrayLength);
~BiSortTree() { release(root); }
BiNode* searchBST(int key)
{
searchBST(root, key);
}
bool deleteBST(int key)
{
return deleteBST(root, key);
}
void inOrder() {
inOrder(root);
}
void inOrder(BiNode *bt);
BiNode* getRoot()
{
return this->root;
}
};
void BiSortTree::insertBST(BiNode* &bt, DataType key)
{
if (bt == NULL)
{
bt = new BiNode;
bt->data = key;
bt->lchild = NULL;
bt->rchild = NULL;
}
else
{
if (key < bt->data)
insertBST(bt->lchild, key);
else
insertBST(bt->rchild, key);
}
}
BiSortTree::BiSortTree(DataType array[], int arrayLength)
{
root = NULL;
for (int i = 0; i < arrayLength; ++i)
{
insertBST(root, array[i]);
}
}
BiNode* BiSortTree::searchBST(BiNode *bt, DataType key)
{
if (bt == NULL)
{
return NULL;
}
else
{
if (key == bt->data)
return bt;
else if (key < bt->data)
return searchBST(bt->lchild,key);
else
return searchBST(bt->rchild, key);
}
}
bool BiSortTree::deleteBST(BiNode* &bt, DataType key)
{
if (bt == NULL)
return false;
else
{
if (bt->data == key)
{
deleteNode(bt);
}
else if (key < bt->data)
{
return deleteBST(bt->rchild, key);
}
else
{
return deleteBST(bt->rchild, key);
}
return true;
}
}
void BiSortTree::deleteNode(BiNode* &bt)
{
BiNode *p,*parent,*pre;
if (bt->lchild == NULL && bt->rchild == NULL) //叶子节点
{
p = bt;
bt = NULL; //预防野指针
delete p;
}
else if (bt->rchild == NULL)
{
p = bt;
bt = bt->lchild;
delete p;
}
else if (bt->lchild == NULL)
{
p = bt;
bt = bt->rchild;
delete p;
}
else //左右子树均不为空
{
parent = bt;
pre = bt->lchild;
while (pre->rchild) //转左,然后向右到尽头(找到右子树中最大节点)
{
parent = pre;
pre = pre->rchild;
}
bt->data = pre->data;
if (parent != bt) //判断是否只有一层
{
parent->lchild = pre->lchild;
}
else
{
parent->lchild = pre->lchild;
}
delete pre;
}
}
void BiSortTree::release(BiNode *bt)
{
if (bt == NULL)
return;
else
{
release(bt->lchild);
release(bt->rchild);
free(bt);
}
}
void BiSortTree::inOrder(BiNode *bt)
{
if (bt == NULL)
return;
else
{
inOrder(bt->lchild);
cout << bt->data << " ";
inOrder(bt->rchild);
}
}
int main()
{
int arr[N];
for (int i = 0;i < 10;++i)
{
arr[i] = rand() % 10;
}
BiSortTree res(arr, N);
res.inOrder(res.getRoot());
system("pause");
return 0;
}