数据结构与算法——二叉排序树(二叉查找树)

二叉排序树

二叉排序树(Binary Sort Tree),又称为二叉查找树;它是一棵空树或着是具有下列性质的二叉树:

  • 若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
  • 若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
  • 左、右子树也分别为二叉排序树。
  • 不允许有键值相同结点

当我们对上图的二叉排序树进行中序遍历时,便可以得到有序的序列;但构造一个排序二叉树的目的,其实并不是为了排序,而是为了提高查找和插入删除关键字的速度。

二叉排序树的操作

首先提供下二叉树的结构:

typedef struct BTNode 
{
    int data;
    BTNode* lchild;
    BTNode* rchild;
}BTNode,*BiTree;

节点查找

二叉排序树的节点查找,就是利用左右孩子和父结点的大小关系来确定查找的方向。

#include <iostream>

typedef struct BTNode 
{
	int data;
	BTNode* lchild;
	BTNode* rchild;
}BTNode,*BiTree;

//递归查找
BTNode* SearchBST(BiTree T,int x) 
{
	if (!T)  return NULL;
	if (T->data == x) return T;
	if (x < T->data)  return SearchBST(T->lchild,x);
	if (x > T->data)  return SearchBST(T->rchild,x);
	
}

//非递归查找
BTNode* BSTSearch(BiTree T,int x) 
{
	BiTree p = T;
	while (p) 
	{
		if (p->data == x) return p;

		p = x > p->data ? p->rchild : p->lchild;
	}

	return NULL;
}

插入操作

对于一颗二叉排序树来说,如果查找某个元素成功,说明该结点存在;如果查找失败,则查找失败的地方一定就是该结点应该插入的地方。

1. 递归的实现方式:

BiTree InsertBST(BiTree T,int key) 
{
	if (T == NULL) //T为null时,设置新创建的结点为root结点
	{
		T = (BiTree)malloc(sizeof(BTNode));
		T->data = key;
		T->lchild = T->rchild = NULL;
		return T;
	}

	if (key < T->data)
		T->lchild = InsertBST(T->lchild,key);
	else 
		T->rchild = InsertBST(T->rchild, key);

	return T;

}

2. 非递归的实现方式:

bool BSTInsert(BiTree T, int x) 
{
	BiTree p = T;
	BiTree pre = NULL,s = NULL;
	while (p)
	{
		if (p->data == x) break;

		pre = p;
		p = x > p->data ? p->rchild : p->lchild;
	}

	if (p) 
	{
		return false;//结点存在,直接返回
	}
	else
	{

		s = (BiTree)malloc(sizeof(BTNode));
		s->data = x;
		s->lchild = T->rchild = NULL;

		if (pre == NULL) 
		{
			T = s;
		}
		else if (pre->data > x) 
		{
			pre->lchild = s;
		}
		else
		{
			pre->rchild = s;
		}
	}

	return true;

}

删除结点操作

对删除结点的分析:

1. 删除的结点为叶子结点:直接删除

2. 删除的结点仅有左或右子树:将左或右子树移动到删除结点位置即可

3. 删除结点既有左子树又有右子树:用比当前结点小的最大结点 或 用比当前结点大的最小结点替换删除结点

bool BSTInsert(BiTree T, int x) 
{
	BiTree p = T;
	BiTree pre = NULL,s = NULL;
	while (p)
	{
		if (p->data == x) break;

		pre = p;
		p = x > p->data ? p->rchild : p->lchild;
	}

	if (p) 
	{
		return false;//结点存在,直接返回
	}
	else
	{

		s = (BiTree)malloc(sizeof(BTNode));
		s->data = x;
		s->lchild = T->rchild = NULL;

		if (pre == NULL) 
		{
			T = s;
		}
		else if (pre->data > x) 
		{
			pre->lchild = s;
		}
		else
		{
			pre->rchild = s;
		}
	}

	return true;

}

bool Delete(BiTree *p) 
{
	BiTree q, s;
	if ((*p)->rchild == NULL) 
	{
		q = *p;
		*p = (*p)->lchild;
		free(q);
	}
	else if( (*p)->lchild == NULL )
	{
		q = *p;
		*p = (*p)->rchild;
		free(q);
	}
	else 
	{
		q = *p;//记录删除结点
		s = (*p)->lchild;
		//获取小于删除结点的最大值
		while (s->rchild) 
		{
			q = s;
			s = s->rchild;
		}

		(*p)->data = s->data;//替换

		if (q != *p) 
		{
			q->rchild = s->lchild;
		}
		else 当删除结点的左子树的根结点只有左子树时执行
		{
			q->lchild = s->lchild;
		}

		free(s);


	}

	return;

}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值