(一)二叉搜索树(BST)

【前言】上一篇中的二叉树是用直接赋值创建的,数据量很小,一但数据量变大,那个方法肯定不适用。
所以,为了高效的创建一个二叉树,就有了插入法创建二叉树;

二叉搜索树(BST):Binary Search Tree的首字母大写构成。
【特点】:它是一个特殊的二叉树,树中的结点必须满足:根节点的值大于左子树的值且小于右子树的值。即:根>左,根<右。
下面,我们来看二叉树的建立:

1.使用结构体变量构建树

我们知道,二叉树的结点不仅包括数据,还包含指向子节点的指针。所以,每个结点就应该用结构体实现。

typedef struct node
{
	int data;		//结点的数据
	struct node* left;		//此结点的左子结点的结构体指针
	struct node* right;		
}Node

2.打包整颗树

上一篇中的树很散乱,为了看起来方便,我们将整个树形结构打包成一棵树。

typedef struct
{
	Node* root;
}Tree;

3.插入法创建树(重点)

可以将这一步分为以下几个小步来实现:

3.1 将一个数据打包成一个结点

树是又结点组成的。所以,我们需要将一个数据打包成一个结点,以便于下面的操作。

使用malloc函数开辟一个Node类型的新结点,将它的左右子树都置空;注:malloc函数在头文件#include<cstdlib>

Node* node = (Node*)malloc(sizeof(Node));		//创建一个新的结点;
	node->data = value;
	node->left = NULL;
	node->right = NULL;

3.2 创建第一个根节点

将第一个数据作为一个根节点;

	if (tree->root == NULL)			//如果此时这个树的根节点为空的话,就让它做根节点;
	{
		tree->root = node;
	}

3.3 创建后续结点

与根节点比较,如果比它小,就放进左边,如果左边还有数据,就把左边的数据当做根节点继续比较。如果比它大,就放进右边,如果右边还有数据,就把右边的数据当做根节点继续比较。
可以看到,这是一个while的过程。为了不使他的根节点发生变化,我们可以定义一个临时的Node类型的变量代替执行操作;

	else
	{
		Node* temp = tree->root;			//定义一个临时结构体变量指向此时结点的根节点,用这个临时指针进行接下来的插入操作;
		while (temp != NULL)
		{
			if (value < temp->data)		//插入到左边;
			{
				if (temp->left == NULL)		//如果左边为空,直接插入;
				{
					temp->left = node;
					return;					//终止;
				}
				else
				{
					temp = temp->left;			//如果左边不为空,继续往下找;
				}
			}
			else
			{									//插入到右边;
				if (temp->right == NULL)			//如果右边为空,直接插入;
				{
					temp->right = node;
					return;
				}
				else
				{
					temp = temp->right;				//如果右边不为空,继续往下找;
				}
			}
		}
	}

3.4 二叉搜索树的高度

树的高度=max(左子树高度,右子树高度)+1;

可以通过递归求其高度。

int get_hight(Node* node)//求树的高度;
{
	if (node == NULL)	//递归出口,如果它的结点为空,则高度为0;
	{
		return 0;
	}
	else
	{
		int left = get_hight(node->left);	//递归求左子树高度
		int right = get_hight(node->right);	//递归求右子树高度
		int max = left;				//判断左右子树高度的最大值
		if (right > max)
		{
			max = right;
		}
		return max + 1;//树的高度=max(左子树高度,右子树高度)+1;
	}
}

3.5 二叉搜索树中的最大值

在二叉搜索树中求最大值,可以直接找叶子结点的最右边的值,它就是最大的数。

一般的树中,求最大值。可以求左子树的最大值,右子树的最大值,和根节点值比较,三者最大者即为树的最大值,这种方法也适应于二叉搜索树。
用递归实现;

int max(Node* node)	//普通树求最大值,也适应与二叉搜索树,二叉搜索树也可以直接找最右边的值,它就是最大值;
{
	int maxleft;	//假设所有结点都是正数;
	int maxright;
	int maxroot;
	if (node == NULL)
	{
		return -1;
	}
	else
	{
		maxleft = max(node->left);
		maxright = max(node->right);
		maxroot = node->data;
		int max1;
		max1 = maxleft;
		if (max1< maxright)
		{
			max1 = maxright;
		}
		if (max1<maxroot)
		{
			max1 = maxroot;
		}
		return max1;
	}
}

到此,一个树形结构就创建完成了;
可以用前序遍历,中序遍历,后序遍历进行输出。
注意::二叉搜索树的中序遍历是从小大一个有序的数据列;
完整代码实现如下:

#include<iostream>
#include<cstdlib>
using namespace std;
typedef struct node
{
	int data;		//结点的数据
	struct node* left;		//此结点的左子结点的结构体指针
	struct node* right;		
}Node;
typedef struct
{
	Node* root;
}Tree;
void insert(Tree* tree, int value)
{
	Node* node = (Node*)malloc(sizeof(Node));		//创建一个新的结点;
	node->data = value;
	node->left = NULL;
	node->right = NULL;
if (tree->root == NULL)			//如果此时这个树的根节点为空的话,就让它做根节点;
{
	tree->root = node;
}
	else
	{
		Node* temp = tree->root;			//定义一个临时结构体变量指向此时结点的根节点,用这个临时指针进行接下来的插入操作;
		while (temp != NULL)
		{
			if (value < temp->data)		//插入到左边;
			{
				if (temp->left == NULL)		//如果左边为空,直接插入;
				{
					temp->left = node;
					return;					//终止;
				}
				else
				{
					temp = temp->left;			//如果左边不为空,继续往下找;
				}
			}
			else
			{									//插入到右边;
				if (temp->right == NULL)			//如果右边为空,直接插入;
				{
					temp->right = node;
					return;
				}
				else
				{
					temp = temp->right;				//如果右边不为空,继续往下找;
				}
			}
		}
	}
}
void preorder(Node* p1)		//前序遍历;
{
	if (p1 != NULL)
	{
		printf("%d\n", p1->data);
		preorder(p1->left);
		preorder(p1->right);
	}
}
void inorder(Node* p2)		//中序遍历,从小到大排序
{
	if (p2 != NULL)
	{
		inorder(p2->left);
		printf("%d\n", p2->data);
		inorder(p2->right);
	}
}
void postorder(Node* p3)//后序遍历;
{
	if (p3 != NULL)
	{
		postorder(p3->left);
		postorder(p3->right);
		printf("%d\n", p3->data);
	}
}
int get_hight(Node* node)//求树的高度;
{
	if (node == NULL)	//递归出口,如果它的结点为空,则高度为0;
	{
		return 0;
	}
	else
	{
		int left = get_hight(node->left);	//递归求左子树高度
		int right = get_hight(node->right);	//递归求右子树高度
		int max = left;				//判断左右子树高度的最大值
		if (right > max)
		{
			max = right;
		}
		return max + 1;//树的高度=max(左子树高度,右子树高度)+1;
	}
}
int max(Node* node)	//普通树求最大值,也适应与二叉搜索树,二叉搜索树也可以直接找最右边的值,它就是最大值;
{
	int maxleft;	//假设所有结点都是正数;
	int maxright;
	int maxroot;
	if (node == NULL)
	{
		return -1;
	}
	else
	{
		maxleft = max(node->left);
		maxright = max(node->right);
		maxroot = node->data;
		int max1;
		max1 = maxleft;
		if (max1< maxright)
		{
			max1 = maxright;
		}
		if (max1<maxroot)
		{
			max1 = maxroot;
		}
		return max1;
	}
}
int main()
{
	int a[7] = { 6,3,8,2,5,1,7 };
	Tree tree;	//定义一个树形变量;
	tree.root = NULL;	//开始时,它的根节点初始为空;
	for (int i = 0; i<7; i++)
	{
		insert(&tree, a[i]);
	}
	cout << "先序遍历:" << endl;
	preorder(tree.root);
	cout << "中序遍历:" << endl;
	inorder(tree.root);
	cout << "树的高度:";
	cout << get_hight(tree.root) << endl;
	cout << "树的最大值:";
	cout << max(tree.root) << endl;

	return 0;
}

二叉树学习笔记2
二叉树的操作还有:
【插入】
【删除】
【查找】
这一篇中树中的数据都假设没有重复的且没有负值。
待更。。。。。。。。

相关文章: