目录
1.静态查找表与动态查找表的比较
静态查找表一旦生成,所含记录在查找过程中一般是固定不变的。动态查找表不仅可以实现对数据的查找,在表生成后还经常进行插入和删除操作,所以动态查找表是一直在变化的。
2.二叉排序树(Binary Sort Tree)
2.1二叉排序树的定义
二叉排序树或者是一棵空二叉树,或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有节点的关键码(元素)值均小于根节点的关键码值;若右子树不空,则右子树上所有节点的关键码(元素)值均大于根节点的关键码值;
(2)左右子树也都是二叉排序树
2.2二叉排序树的查找算法
(1)若要查找的树为空,则查找失败
(2)若树非空,则将给定值 x 与树根节点的关键码值比较
1.若 x 等于树根节点的关键码值,查找成功,结束查找;
2.若 x 小于树根节点的关键码值,在树的左子树继续查找;
3.若 x 大于树根节点的关键码值,在树的右子树继续查找
2.3二叉排序树的插入算法
设待插入节点关键码值为 x :
(1)先在树中查找值为 x 的节点,若查找成功,说明节点已存在,无需插入;
(2)若查找失败,说明节点不存在,则将其插入到树中
因此,新插入节点一定是作为叶子节点插入的。
2.4二叉排序树的构造算法
构造二叉排序树的过程,就是从空二叉树开始,逐个向树中插入节点的过程。
设记录的关键码序列为:63,90,70,55,67,42,98,83,10,45,58
2.5二叉排序树的删除算法
设待删除节点为 *p(p为待删除节点的指针),其双亲节点为 *f:
(1)*p 为叶子节点:将 *f 的相应指针域置空即可
(2)*p 有右子树或左子树:用 p->rchild / p->lchild 替换 p 即可
(3)*p 既有左子树又有右子树:用该树中序遍历序列中的直接前驱(后继)节点值取代被删除节点值即可。具体步骤如下:
1.顺着 *p 的左孩子的右链域一直找下去,直到没有右孩子为止。*p 的直接前驱节点肯定没有右孩子
2.用 *p 前驱节点的关键码值取代 *p 的关键码值
3.删除 *p 前驱节点
3.源代码示例
#include <stdio.h>
#include <stdlib.h>
typedef int KeyType; /* 定义节点关键码的类型为整型 */
typedef struct node /* 二叉排序树的结构体 */
{
KeyType key; /* 树节点的关键码 */
struct node * lchild, * rchild; /* 左右孩子指针 */
}node, * BiSortTree;
void CreateBST(BiSortTree * T); /* 构造二叉排序树 */
void InsertBST(BiSortTree * T, KeyType x); /* 向T中插入关键码值为 x 的节点 */
void DeleteBST(BiSortTree * T, KeyType x); /* 删除T中关键码值为 x 的节点 */
void TraverseBST(BiSortTree T); /* 中序遍历BST */
int SearchBST(BiSortTree T, KeyType x, BiSortTree * p, BiSortTree * f);
int SearchBST_Recursive(BiSortTree T, KeyType x, BiSortTree * p, BiSortTree * f);
/* 在T中查找关键码值为 x 的节点,若找到则返回1,p指向该节点,f指向该节点双亲节点;否则返回0*/
int main(void)
{
BiSortTree T, p, f;
p = f = NULL;
CreateBST(&T);
printf("遍历:");
TraverseBST(T);
printf("\n");
printf("查找 98 :");
int flag = SearchBST(T, 98, &p, &f);
if (flag) printf("查找成功!\n");
else printf("查找失败!\n");
printf("递归查找 100 :");
flag = SearchBST_Recursive(T, 100, &p, &f);
if (flag) printf("查找成功!\n");
else printf("查找失败!\n");
printf("插入 77 :");
InsertBST(&T, 77);
TraverseBST(T);
printf("\n");
printf("删除 77 :");
DeleteBST(&T, 77);
TraverseBST(T);
printf("\n");
return 0;
}
void CreateBST(BiSortTree * T) /* 构造二叉排序树 */
{
KeyType x;
printf("请输入若干整数构建BST,以 -1 结束:");
*T = NULL;
scanf("%d", &x);
while (x != -1)
{
InsertBST(T, x);
scanf("%d", &x);
}
}
/* 在T中查找关键码值为 x 的节点,若找到则返回1,*p指向该节点,*f为*p双亲节点;否则返回0*/
int SearchBST(BiSortTree T, KeyType x, BiSortTree * p, BiSortTree * f)
{
*p = T;
while (*p)
{
if ((*p)->key == x) return 1; /* 查找成功 */
else
{
if (x < (*p)->key) /* 在左子树继续查找 */
{ *f = *p; *p = (*p)->lchild; }
else /* 在右子树继续查找 */
{ *f = *p; *p = (*p)->rchild; }
}
}
return 0; /* 查找失败 */
}
int SearchBST_Recursive(BiSortTree T, KeyType x, BiSortTree * p, BiSortTree * f)
{
if (!T) /* 树空时,查找失败 */
return 0;
else if (x == T->key) /* 查找成功 */
{ *p = T; return 1; }
else if (x < T->key) /* 在左子树继续查找 */
SearchBST_Recursive(T->lchild, x, p, &T);
else /* 在右子树继续查找 */
SearchBST_Recursive(T->lchild, x, p, &T);
}
void InsertBST(BiSortTree * T, KeyType x) /* 向T中插入关键码值为 x 的节点 */
{
BiSortTree p, f, s;
f = p = NULL;
if (!SearchBST(*T, x, &p, &f)) /* 若树中不存在关键码值为 x 的节点,则插入 */
{
s = (node *)malloc(sizeof(node)); /* 申请节点并赋值 */
s->key = x;
s->lchild = NULL;
s->rchild = NULL;
if (!*T) *T = s; /* 若树为空,将新申请的节点作为根节点 */
else
{
if (x < f->key) /* 插入节点为f的左孩子 */
f->lchild = s;
else /* 插入节点为f的右孩子 */
f->rchild = s;
}
}
}
void DeleteBST(BiSortTree *T, KeyType x) /* 删除T中关键码值为 x 的节点 */
{
BiSortTree p, f, s, s_parent;
/**
* p:要删除的节点
* f:p的双亲结点
* s:p的中序前驱节点
* s_parent:s的双亲结点
*/
p = f = NULL;
if (SearchBST(*T, x, &p, &f)) /* 若树中存在关键码值为 x 的节点,则删除 */
{
if (!p->lchild && !p->rchild) /* 被删除节点无左右孩子 */
{
if (p == *T) /* 若删除的是根节点 */
{
*T = NULL;
free(p);
}
else /* 若删除的不是根节点 */
{
if (p->key < f->key)
f->lchild = NULL;
else
f->rchild = NULL;
free(p);
}
}
else if (!p->lchild && p->rchild) /* 被删除节点有右孩子无左孩子 */
{
if (p == *T) /* 若删除的是根节点 */
{
*T = p->rchild;
free(p);
}
else /* 若删除的不是根节点 */
{
if (p->key < f->key)
f->lchild = p->rchild;
else
f->rchild = p->rchild;
free(p);
}
}
else if (p->lchild && !p->rchild) /* 被删除节点有左孩子无右孩子 */
{
if (p == *T) /* 若删除的是根节点 */
{
*T = p->lchild;
free(p);
}
else /* 若删除的不是根节点 */
{
if (p->key < f->key)
f->lchild = p->lchild;
else
f->rchild = p->lchild;
free(p);
}
}
else /* 被删除节点有左右孩子 */
{
s_parent = p;
s = p->lchild;
while (s->rchild) /* 查找被删除节点中序前驱节点 */
{
s_parent = s;
s = s->rchild;
}
p->key = s->key;
if (s_parent == p)
s_parent->lchild = s->lchild;
else
s_parent->rchild = s->lchild;
free(s);
}
}
}
void TraverseBST(BiSortTree T) /* 中序遍历BST */
{
if (T)
{
TraverseBST(T->lchild);
printf("%d, ", T->key);
TraverseBST(T->rchild);
}
}