数据结构与算法分析C语言描述版----4.3二叉查找树

VS2015可直接运行 

//因为二叉查找树的平均深度为O(logN),所以一般不用担心栈空间被用尽
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;

//二叉树查找结构(有序):
//*SearchTree根节点用来表示整个二叉查找树
//*Position用来表示某一个结点
typedef struct TreeNode
{
	int Element;
	TreeNode* Left;
	TreeNode* Right;
}*SearchTree, *Position;

SearchTree makeEmpty(SearchTree T);//讲树置为空树
Position find(int x, SearchTree T);
Position findMin(SearchTree T);
Position findMax(SearchTree T);
SearchTree insert(int x, SearchTree T);
SearchTree deleteTreeEle(int x, SearchTree T);

SearchTree creatSearchTree(int* arr, int len);
void preOrderTraverse(SearchTree T);

void inOrderTraverse(SearchTree T);

/*
创建一颗空树
使用递归的方式由下到上将树中的每一个点释放空间,
返回NULL。可以初始化一个单节点,这里使用递归更遵循树的定义。
*/
SearchTree makeEmpty(SearchTree T)
{
	if (T != NULL)
	{
		if (T->Left != NULL)
			makeEmpty(T);//一直在对T操作,无需return!
		if (T->Right != NULL)
			makeEmpty(T);
	}
	return NULL;
}

//利用查找树的特点
/*
二叉查找树的find操作
使用递归的方式查找元素x,若树T为空,则返回NULL,
若元素x比当前元素小,则递归向该元素节点的左子树查找,
若元素x比当前元素大,则递归向该元素节点的右子树查找,
最后返回查找到的元素x位置。
*/
Position find(int x, SearchTree T)
{
	if (T == NULL)
		return T;
	else
	{
		if (x == T->Element)
			return T;
		else if (x < T->Element)
			return find(x, T->Left);
		else
			return find(x, T->Right);
	}
}

/*
二叉查找树的find_min操作
因为二叉排序树是有序的,所以只需要递归的查找左子树,
如果树为空,返回NULL,如果树根不为空,根的左子树为空,返回根T,
否则递归的在根的左子树中查找,返回递归到最后的根元素。
*/
//只需看三个节点,父和左右儿子,其他的遍历
Position findMin(SearchTree T)
{
	if (T == NULL)
		return NULL;
	if (T->Left == NULL)
		return T;
	else
		return findMin(T);
}

/*
二叉查找树的find_max操作,
使用非递归的方式进行查找。
*/
Position findMax(SearchTree T)
{
	if (NULL != T)
	{
		while (NULL != T->Right)
			T = T->Right;
	}

	return T;
}

/*
插入元素到二叉查找树中
返回为根节点,因为如果树根为空的话需要插入创建一个节点并返回,
可以把插入想象为find操作,发现不做或做些更新,否则插入路径上最后一点。
*/
SearchTree insert(int x, SearchTree T)
{
	if (T == NULL)//若树为空树,需要分配节点空间并初始化,递归基准
	{
		T = new TreeNode;
		T->Element = x;
		T->Left = NULL, T->Right = NULL;
	}
	else
	{
		if (x < T->Element)//若插入元素x比当前节点小,则递归的在其左子树查找
			T->Left = insert(x, T->Left);//最后一点
		else if (x > T->Element)
			T->Right = insert(x, T->Right);
	}
	return T;
}

/*
二叉查找树的删除例程,查找到元素x的节点
若要删除节点是一片树叶,则立即删除,若要删除节点有一个儿子可以在其父节点调整指针删除,
若要删除有两个二个儿子,则用其右子树最小的节点代替该节点并将右子树删除。
*/
SearchTree deleteTreeEle(int x, SearchTree T)
{
	if (T == NULL)
	{
		cout << "空树不能删除,退出程序" << endl;
		exit(-1);
	}
	else if (x < T->Element)
	{	//若该树不为空且当前节点元素比元素x大
		//则递归到该节点的左子树中进行删除
		T->Left = deleteTreeEle(x, T->Left);
	}
	else if (x > T->Element)
	{
		T->Right = deleteTreeEle(x, T->Right);
	}

	else if (T->Left && T->Right)//暗含了x == T->Element
	{	//若找到要删除的节点且该节点有两个孩子
		//则将该节点右子树元素值最小的节点赋值给该节点
		//同时将右子树最小的节点删除释放空间
		Position rightMin = findMin(T->Right);
		T->Element = rightMin->Element;
		T->Right = deleteTreeEle(T->Element, T->Right);
	}
	else//暗含了x == T->Element
	{	//若找到要删除的节点且该节点有一个个孩子或者没有孩子
		//则移动该节点指针到左右节点相当于父节点指向了该节点,释放该节点空间
		SearchTree tempCell = T;
		if (T->Left == NULL)
			T = T->Right;
		else if (T->Right == NULL)
			T = T->Left;
		delete tempCell;
	}

	return T;
}

SearchTree creatSearchTree(int * arr, int len)
{
	SearchTree T = nullptr;//0x00000000,这个地址不存内容
	for (int i = 0; i < len; i++)
	{
		cout << *(arr + i) << " ";
		T = insert(*(arr + i), T);

	}
	return T;
}

//中序遍历:左根右
void inOrderTraverse(SearchTree T)
{
	if (T != NULL)
	{	
		inOrderTraverse(T->Left);
		cout << T->Element << " ";
		inOrderTraverse(T->Right);

	}
}

//先序遍历:根左右
void preOrderTraverse(SearchTree T)
{
	if (T != NULL)
	{
		cout << T->Element << "";
		preOrderTraverse(T->Left);
		preOrderTraverse(T->Right);
	}
}

//使用数组初始化构造一棵树,利用中序遍历和先序遍历验证是否是二叉排序树
int main()
{
	int num = 0;
	cout << "输入查找树结点个的数:";
	cin >> num;

	int *arr = new int[num*sizeof(int)];
	for (int i = 0; i < num; i++)
	{
		arr[i] = (rand()%(num*2));//随机生成0-num*2之间的数字
	}

	SearchTree T = creatSearchTree(arr, num);
	cout << "中序遍历该二叉排序树的结果:" << endl;
	inOrderTraverse(T);
	int key = 0;
	cout << "输入要查找的整数:";
	cin >> key;
	Position p = find(key, T);
	if (p)
		cout << "查找成功" << endl;
	else
		cout << "查找失败" << endl;

	cout << "输入要插入的整数:";
	cin >> key;
	T = insert(key, T);
	if (T)
	{
		cout << "插入成功,插入后的中序遍历结果:";
		inOrderTraverse(T);
		cout << endl;
	}
	else 
		cout << "插入失败,该二叉排序树中不存在整数" << key << endl;

	cout << "输入要删除的整数:";
	cin >> key;
	T = deleteTreeEle(key, T);
	if (T)
	{
		cout << "删除成功,删除后的中序遍历结果:";
		inOrderTraverse(T);
		cout << endl;
	}
	else
		cout << "删除失败,该二叉排序树中不存在整数" << key << endl;
	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/vict_wang/article/details/82820134