二叉搜索树(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;
}