数据结构(7.3_1)——二叉排序树

发布于:2024-09-17 ⋅ 阅读:(77) ⋅ 点赞:(0)

二叉排序树,又称二叉查找树(BST,Binary Search Tree)

一棵二叉树或者是空二叉树,或者是具有如下性质的二叉树:

  • 左子树上所有结点的关键字均小于根结点的关键字;
  • 右子树上所有结点的关键字均大于根结点的关键字;
  • 左子树和右子树又各是一棵二叉排序树;

左子树结点值<根结点值<右子树结点值

进行中序遍历,可以得到一个递增的有序序列

二叉排序树可用于元素的有序组织,搜索 

二叉排序树的查找

  • 若树非空,则目标值与根结点的值比较;
  • 若相等,则查找成功;
  • 若小于根结点,则在左子树上查找,否则在右子树查找;
  • 查找成功,返回结点指针;查找失败返回NULL

例:查找关键字为30的结点

代码:

 最坏空间复杂度O(1)


//二叉排序树结点
typedef struct BSTNode {
	int key;
	struct BSTNode* lchild, * rchild;
}BSTNode,*BSTree;

//在二叉排序树中查找值为key的结点
BSTNode* BST_Search(BSTree T, int key) {
	while (T != NULL && key != T->key) { //若树空或等于根结点值,则接受循环
		if (key < T->key)
			T = T->lchild;//小于,则在左子树上查找
		else
			T = T->rchild;//大于,则在右子树上查找
	}
	return T;
}

查找失败的情况 :

 

在二叉排序树中查找值为key的结点(递归实现)

 最坏空间复杂度O(h)

//在二叉排序树中查找值为key的结点(递归实现)
BSTNode* BSTSearch(BSTree T, int key) {
	if(T==NULL)
		return NULL;//查找失败
	if (key == T->key)
		return T;//查找成功
	else if (key < T->key)
		return BSTSearch(T->lchild, key);//在左子树中找
	else
		return BSTSearch(T->rchild, key);//在右子树中找
}

二叉排序树的插入 

若原二叉排序树为空,则直接插入结点;否则,若关键字k小于根结点值,则插入到左子树,若关键字k大于根结点值,则插入到右子树

//在二叉排序树中插入关键字为k的新结点(递归实现)
int BST_Insert(BSTree &T, int k) {
	if (T == NULL) {//原树为空,新插入的结点为根结点
		T = (BSTree)malloc(sizeof(BSTNode));
		T->key = k;
		T->lchild = T->rchild = NULL;
		return 1;//返回1,插入成功
	}
	else if (k == T->key)//树中存在相同关键字的结点,插入失败
		return 0;
	else if (k < T->key)//插入到T的左子树
		return BST_Insert(T->lchild, k);
	else//插入到T的左子树
		return BST_Insert(T->rchild, k);
}

注意:新插入的结点一定是叶子结点 

最坏空间复杂度O(h)

非递归插入

int BST_Insert(BSTree& T, int k) {
	while (T!= NULL) { // 当找到空位置时停止循环
		if (k < T->key) {
			T = T->lchild; // 移动到左孩子
		}
		else if (k > T->key) {
			T = T->rchild; // 移动到右孩子
		}
		else {
			// 如果键值已存在,不插入,返回0
			return 0;
		}
	}
	// 创建新节点并插入到找到的位置
	T = (BSTree)malloc(sizeof(BSTNode));
	if (T== NULL) { // 内存分配失败
		return 0;
	}
	T->key = k;
	T->lchild = T->rchild = NULL;
	return 1; // 插入成功

 

二叉排序树的构造

例题:

//按照str[]中的关键字序列建立二叉排序树
void Creat_BST(BSTree& T, int str[], int n) {
	T = NULL;//初始T为空树
	int i = 0;
	while (i < n) {//依次将每个关键字插入到二叉排序树中
		BST_Insert(T, str[i]);
		i++;
	}
}

 

二叉排序树的删除 

先搜索找到目标结点:

1:若被删除结点z是叶结点,则直接删除,不会破坏二叉排序树的性质

2:若结点z只有一棵左子树或右子树,则让z的子树成为z父结点的子树,替代z的位置

3:若结点z有左、右两棵子树,则令z的直接后继(或直接前驱)替代z,然后从二叉排序树中删去这个直接后继(或直接前驱),这样就转换成了第一或第二种情况。

直接后继:

直接前驱:

 

查找效率分析

查找长度——在查找运算中,需要对比关键字的次数称为查找长度,反映了查找操作时间复杂度

查找成功: 

查找失败:

总结:


网站公告

今日签到

点亮在社区的每一天
去签到