C数据结构与算法-基础整理-树-08:二叉排序树

二叉排序树的多种操作

0x01.二叉排序树概念

二叉排序树(Binary Sort Tree),又称二叉查找树(Binary Search Tree),亦称二叉搜索树。它可以是一棵空树。

二叉排序树必须满足以下条件:

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

0x02.二叉排序树的结构

其实就是普通的二叉树结构,只不过对里面的数据有一定的约束。

typedef struct TreeNode
{
	int data;
	struct TreeNode* Left;
	struct TreeNode* Right;
}TreeNode,BinTree;

0x03.二叉排序树的查找操作

//递归实现查找
//指针f指向父结点,初始化为NULL
//查找成功返回true,p指向查找到的结点
//查找失败返回false,p指向最后一个访问的结点
int SearchBST(BinTree BT, int key, BinTree f, BinTree* p)
{
	if (!BT)//若找到尽头,一定是查找失败了
	{
		*p = f;
		return false;
	}
	else if (key == BT->data)//查找成功
	{
		*p = BT;
		return true;
	}
	else if (key < BT->data)//若key要小于结点数值,则往左子树找
	{
		return SearchBST(BT->Left, key, BT, p);
	}
	else//大于结点值,往右子树找
	{
		return SearchBST(BT->Right, key, BT, p);
	}
}

0x04.插入操作

在依靠查找函数的时候:

//当二叉排序树中不存在关键字等于key的元素时,插入k,返回true,否则返回false
int InsertBST(BinTree* BT, int key)
{
	BinTree p1, p2;
	if (!SearchBST(*BT, key, NULL, &p1))//查找失败
	{
		p2 = (BinTree)malloc(sizeof(TreeNode));
		p2->data = key;
		p2->Left = p2->Right = NULL;
		if (!p1)//若p1不存在,说明是空树
		{
			*BT = p2;//将p2插入
		}
		else if (key < p1->data)//小于插入左树
		{
			p1->Left = p2;
		}
		else//大于插入右树
		{
			p1->Right = p2;
		}
		return true;
	}
	else
	{
		return false;
	}
}

在不依赖于查找函数的时候:

//返回头节点
BinTree Insert( BinTree BST, int X )
{
    if(!BST)//插入头
    {
        BinTree p=(BinTree)malloc(sizeof(TreeNode));
        p->data=X;
        p->Left=p->Right=NULL;
        BST=p;
    }
    else
    {
        if(X<BST->data)//寻找插入位置,若已存在,则不需要插入操作
        {
            BST->Left=Insert(BST->Left,X);
        }
        else
        {
           BST->Right=Insert(BST->Right,X);
        }
    }
    return BST;
}

0x05.通过数组建立一棵二叉树

void CreateBST()
{
	int i, n;
	BinTree BT;
	printf("请输入数据数:\n");
	scanf("%d", &n);
	int* a = (int*)malloc(sizeof(int));
	for (i = 0; i < n; i++)
	{
		scanf("%d", &a[i]);
		InsertBST(&BT, a[i]);
	}
}

0x06.删除操作

要删除二叉树中的结点,有三种情况:

  • 该结点的左子树为空,只需要重接右子树。
  • 该结点的右子树为空,只需要重接左子树。
  • 该结点左右子树都不为空,需要找到这个要删除的结点的前驱或直接后继,把该前驱,换到该结点处。(因为这个结点替换后,仍满足原来二叉排序树的顺序)

代码:

直接传二级指针改变:

int DeleteBST(BinTree* BT, int key)
{
	if (!*BT)//不存在关键字等于key的元素
	{
		return false;
	}
	else
	{
		if (key < (*BT)->data)
		{
			DeleteBST(&(* BT)->Left,key);
		}
		else if (key > (*BT)->data)
		{
			DeleteBST(&(*BT)->Right, key);
		}
		else//找到,开始删除操作
		{
			BinTree *p = BT;
			BinTree q;
			if ((*p)->Left == NULL)//左孩子为空,重接右孩子
			{
				q = *p;
				*p = (*p)->Right;
				free(q);
			}
			else if ((*p)->Right == NULL)//右孩子为空,重接左孩子
			{
				q = *p;
				*p = (*p)->Left;
				free(q);
			}
			else//左右孩子都不为空
			{
				q = *p;
				BinTree s=(*p)->Left;
				while (s->Right)//寻找前驱
				{
					q = s;
					s = s->Right;
				}
				(*p)->data = s->data;
				//此时的s是前驱,此时的p是要删除的那个结点,此时的q是s的父结点
				//此时若删除s,还需考虑的s的左孩子情况
				//若s的父结点等于要删除的结点,说明s就是要删除的那个结点的左孩子,此时就要把s的左孩子接到q的左孩子上
				//若不等于,则将s的左孩子接到q的右孩子上
				if (q != *p)
				{
					q->Right = s->Left;
				}
				else
				{
					q->Left = s->Right;
				}
				free(s);
			}
		}
	}

传一级指针,返回删除后的根结点:

BinTree Delete(BinTree BST,int X)
{
	BinTree tmp;
	if (!BST) puts("Not Found");
	else
	{
		if (X < BST->data)
			BST->Left = Delete(BST->Left, X); // 左子树递归删除
		else if (X > BST->data)
			BST->Right = Delete(BST->Right, X); // 右子树递归删除
		else // 找到需要删除的结点
		{
			if (BST->Left && BST->Right) // 被删除的结点有左、右子结点
			{
				BinTree q = BST->Right;
				if (!q)
				{
					tmp = q;
				}
				else
				{
					while (q->Left)// 在右子树种找到最小结点填充删除结点
					{
						q = q->Left;
					}
					tmp = q;
				}
				BST->data = tmp->data;
				BST->Right = Delete(BST->Right, BST->data); // 递归删除要删除结点的右子树种最小元素
			}
			else // 被删除结点有一个或没有子结点
			{
				tmp = BST;
				if (!BST->Left) BST = BST->Right; // 有右孩子或者没孩子
				else if (!BST->Right) BST = BST->Left; 
			}
		}
	}
	return BST;
}

0x07.最大最小值操作

寻找最小值的结点,并返回该结点:

BinTree FindMin(BinTree BST)
{
	if (BST)
	{
		while (BST->Left)
		{
			BST = BST->Left;
		}
	}
	return BST;
}

寻找最大值结点,并返回该结点:

BinTree FindMax(BinTree BST)
{
	if (BST)
	{
		while (BST->Right)
		{
			BST = BST->Right;
		}
	}
	return BST;
}

本章结束。

发布了50 篇原创文章 · 获赞 35 · 访问量 1311

猜你喜欢

转载自blog.csdn.net/ATFWUS/article/details/104410919
今日推荐