二叉搜索树(C语言)详解

二叉搜索树(Binary Search Tree,简称BST),也称为二叉查找树 、有序二叉树(Ordered Binary Tree)或排序二叉树(Sorted Binary Tree),是指一棵空树或者具有下列性质的二叉树:

若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值;
若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值;
任意节点的左、右子树也分别为二叉查找树;
没有键值相等的节点。

在这里插入图片描述比如要把 { 6,3,8,2,5,1,7 }插入二叉树中,

把6放在根节点处。
3<6,往左走,6的左子节点为空,则放在6的左边子节点。
8>6,往右走,6的右子节点为空,则放在6的右边子节点。
2<6,往左走,2<3,往左走,3的左子节点为空,则把2插入…

它是一种结合了二分查找策略的链接结构。其中,每个节点包含其中的数据以及两个指针,分别指向子节点中的左节点和右节点。
那么,我们创建节点:

1、创建节点,创建树

#include <stdio.h>
#include <stdlib.h>

typedef int Data;

//定义一个节点
typedef struct Node
{
	Data data;
	struct Node* pleft;
	struct Node* pright;
}Node;

//创建节点
Node* CreatNode(int val)
{
	Node* pnode =(Node*) malloc(sizeof(Node));
	if (pnode == NULL)
	{
		return NULL;
	}
	pnode->data = val;
	pnode->pleft = pnode->pright = NULL;
	return pnode;
}
//二叉搜索树:左>根>右
typedef struct Tree
{
	Node* root;
}Tree;


Tree* CreatTree()
{
	Tree* tree = calloc(1, sizeof(Tree));
	if (tree == NULL)
		return NULL;
	tree->root = NULL;
	
	return tree;
}

2、遍历

递归法遍历
//看根在哪里,根在前面,前序遍历,
//根在中间,中序遍历,
//根在最后,后序遍历
//递归遍历
void preOrder(Node*root)//先序遍历,递归
{
	if (root == NULL)//出口
	{
		return;
	}
	else
	{
		printf("%d ", root->data);//根、左、右
		preOrder(root->pleft);
		preOrder(root->pright);
	}
}
void midOrder(Node* root)//中序遍历,递归
{
	if (root == NULL)//出口
	{
		return;
	}
	else//左、根、右
	{
		midOrder(root->pleft);
		printf("%d ", root->data);
		midOrder(root->pright);
	}
}
void lastOrder(Node* root)//后序遍历,递归
{
	if (root == NULL)//
	{
		return;
	}
	else//左、右、根
	{
		lastOrder(root->pleft);
		lastOrder(root->pright);
		printf("%d ", root->data);
	}
}
迭代法遍历
//非递归遍历——迭代
/*
1、定义一个移动指针指向根部
2、沿着左走走到空的位置(边走边打印,并记录指针)——入栈
3、回退——出栈

*/
void preOrderBy_stack(Node*root)
{
	if (root == NULL)
	{
		return;
	}
	Node* stack[100];//栈
	int top = -1;
	Node* pnode = root;//1、
	while (pnode!=NULL||top!=-1)
	{
		while(pnode)//2、
		{
			printf("%d ", pnode->data);
			top++;
			stack[top] = pnode;
			pnode = pnode->pleft;
		}
		//3、回退
		if (top != -1)
		{
			pnode = stack[top];
			top--;
			pnode = pnode->pright;
		}
	}

}




/*

1、定义一个移动指针指向根部
2、沿着左走走到空的位置(记录指针)——入栈
3、回退——出栈,打印数据

*/
void midOrderBy_stack(Node* root)
{
	if (root == NULL)
	{
		return;
	}
	Node* stack[100];//栈
	int top = -1;
	Node* pnode = root;//1、
	while (pnode != NULL || top != -1)
	{
		while (pnode)//2、
		{
			top++;
			stack[top] = pnode;
			pnode = pnode->pleft;
		}
		//3、回退
		if (top != -1)
		{
			pnode = stack[top];
			top--;
			printf("%d ", pnode->data);
			pnode = pnode->pright;
		}
	}

}
/*
1、定义一个移动指针指向根部
2、沿着左走走到空的位置(记录指针)——入栈
3、判断当前节点是否存在右节点,不存在则打印,打印完要标识当前位置,存在则重复2
*/
void lastOrderBy_stack(Node* root)
{
	if (root == NULL)
	{
		return;
	}
	Node* stack[100]; // 栈
	int top = -1;
	Node* pnode = root; // 1、

	// 第一阶段:遍历到最左下角
	while (pnode)
	{
		top++;
		stack[top] = pnode;
		pnode = pnode->pleft;
	}

	Node* last = NULL; // 记录上次遍历的节点

	// 第二阶段:回退并输出节点
	while (top != -1)
	{
		pnode = stack[top];
		top--;

		// 判断右子树是否为空或者已经被遍历
		if (pnode->pright == NULL || pnode->pright == last)
		{
			printf("%d ", pnode->data);
			last = pnode;
		}
		else
		{
			// 进入右子树
			top++;
			stack[top] = pnode;
			pnode = pnode->pright;

			// 重复第一阶段,遍历到右子树的最左下角
			while (pnode != NULL)
			{
				top++;
				stack[top] = pnode;
				pnode = pnode->pleft;
			}
		}
	}
}

层次遍历
//层次遍历——队列
/*
1、根节点入队,遍历根节点
2、出队,如果出队节点存在左边,左边入队
存在右边,右边入队
3、打印队列
*/
void layerOrder(Node* root)
{
	Node* pnode = root;
	Node* queue[100];
	int front = 0;
	int tail = 0;
	queue[tail++] = pnode;
	printf("%d ", pnode->data);

	// 遍历队列
	while (front != tail)
	{
		pnode = queue[front++];

		// 遍历左子树
		if (pnode->pleft != NULL)
		{
			queue[tail++] = pnode->pleft;
			printf("%d ", pnode->pleft->data);
		}

		// 遍历右子树
		if (pnode->pright != NULL)
		{
			queue[tail++] = pnode->pright;
			printf("%d ", pnode->pright->data);
		}
	}
}

3、插入

迭代插入
//迭代插入
void Inset(Tree* tree, int val)//左>根>右
{
	Node* newnode = CreatNode(val);
	if (newnode == NULL)
		return;
	if (tree->root == NULL)
	{
		tree->root = newnode;
	}
	else
	{
		Node* Temp=tree->root;
		while (Temp)
		{
			if (val < Temp->data)
			{
				if (Temp->pleft == NULL)
				{
					Temp->pleft=newnode;
					return;
				}
				else
				{
					Temp = Temp->pleft;
				}
			}
			else
			{
				if (Temp->pright == NULL)
				{
					Temp->pright = newnode;
					return;
				}
				else
				{
					Temp = Temp->pright;
				}
			}
		}
	}
}

递归插入
//递归插入
Node* insert_digui(Node* root, int val)
{
	// 创建新节点
	Node* newNode = CreatNode(val);
	if(newNode==NULL)
		return NULL;
	if (root == NULL)
	{
		root = newNode;
		return root;
	}
	else if (val < root->data)//小于根节点,左插
	{
		root->pleft = insert_digui(root->pleft, val);
	}
	else if (val > root->data)//大于根节点,右插
	{
		root->pright = insert_digui(root->pright, val);
	}
	
	return root;
}

4、递归获取高度

//递归获取高度
int get_hight(Node* node)
{
	if (node == NULL)
		return 0;
	else
	{
		int hight_l=get_hight(node->pleft);
		int hight_r = get_hight(node->pright);
		int max = hight_l;
		if (hight_r > max)
			max = hight_r;
		return max + 1;
	}

}

5、递归找最值

//递归找最大值
#include <limits.h>
int find_max(Node* node)
{
	if (node == NULL)
	{
		return INT_MIN;  // 初始最小值为负无穷
	}
	else
	{
		int left_max = find_max(node->pleft);
		int right_max = find_max(node->pright);

		int max_so_far = (left_max > right_max) ? left_max : right_max;

		return (node->data > max_so_far) ? node->data : max_so_far;
	}
}
//找到最小值
int find_min(Node* node)
{
	if (node == NULL)
	{
		return INT_MAX;  // 初始最小值为负无穷
	}
	else
	{
		int left_min = find_min(node->pleft);
		int right_min = find_min(node->pright);

		int min_so_far = (left_min < right_min) ? left_min : right_min;

		return (node->data < min_so_far) ? node->data : min_so_far;
	}
}
//找到最小值的所在节点
Node* Find_min(Node* root)
{
	if (root == NULL) 
	{
		return NULL;
	}
	else if(root->pleft == NULL)
	{
		return root;
	}
	else {
		return Find_min(root->pleft);
	}
}

//找到最大值所在节点
Node* Find_max(Node* root)
{
	if (root == NULL)
	{
		return NULL;
	}
	else if (root->pright == NULL)
	{
		return root;
	}
	else
	{
		return Find_max(root->pright);
	}
}

6、递归查找元素

//查找元素
Node* Reasearch(Node* root, int val)
{
	// 如果树为空,返回空指针
	if (root == NULL)
	{
		return root;
	}
	// 如果要查找的值小于当前节点的值,递归调用左子树
	else if (val < root->data)
	{
		return Reasearch(root->pleft, val);
	}
	// 如果要查找的值大于当前节点的值,递归调用右子树
	else if (val > root->data)
	{
		return Reasearch(root->pright, val);
	}
	// 如果找到了要查找的值,返回当前节点
	else
	{
		return root;
	}
}

7、主函数测试结果

int main()
{
	int arr[7] = { 6,3,8,2,5,1,7 };
	Tree* tree = CreatTree();
	for (int i = 0; i < 7; i++)
	{
		Inset(tree, arr[i]);
		
	}
	puts("递归法先序遍历:");
	preOrder(tree->root);
	putchar('\n');
	puts("迭代法先序遍历:");
	preOrderBy_stack(tree->root);
	putchar('\n');
	puts("递归法中序遍历:");
	midOrder(tree->root);
	putchar('\n');
	puts("迭代法中序遍历:");
	midOrderBy_stack(tree->root);
	putchar('\n');
	puts("递归法后序遍历:");
	lastOrder(tree->root);
	putchar('\n');
	puts("迭代法后序遍历:");
	lastOrderBy_stack(tree->root);
	printf("\nhight=%d", get_hight(tree->root));
	printf("\nmax=%d", find_max(tree->root));
	printf("\nmin=%d\n", find_min(tree->root));
	Node*search_node=Reasearch(tree->root, 7);
	if(search_node)
	{
		printf("找到了数字 7 了\n");
	}
	else
	{
		printf("未找到数字 7\n");
	}
	return 0;
}

在这里插入图片描述

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值