1 二叉搜索树:
binary search tree 二叉搜索树:
简写:BST
要求:左<根<右
对于二叉搜索树最大值在最右边
构件树
下面是构件树过程:
下面序列,一次放入数,小的放左边,大的放右边
6 3 8 2 5 1 7
2 整体打包:
只需要知道根节点就知道树的整体了
先序遍历结果:6321587
中序遍历结果:1235678
生成树,通过先序遍历验证:
#include<stdio.h>
#include<windows.h>
#include<string.h>
#include<stdlib.h> // 因为需要写NULL,所以需要这个库
#include<malloc.h> // 这里用于申请内存
//本代码建立在<没有重复数字>的前提下
// 节点结构体
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;
}
}
}
}
}
// 先序遍历, 在这里node是一个指针
void preorder(Node* node) {
if (node != NULL) {
printf("%d\n", node -> data); // 在这里node是一个指针,因而使用->
preorder(node -> left);
preorder(node -> right);
}
}
// 中序遍历, 在这里node是一个指针
void inorder(Node* node) {
if (node != NULL) {
inorder(node -> left);
printf("%d\n", node -> data); // 在这里node是一个指针,因而使用->
inorder(node -> right);
}
}
// 后序遍历, 在这里node是一个指针
void postorder(Node* node) {
if (node != NULL) {
postorder(node -> left);
postorder(node -> right);
printf("%d\n", node -> data); // 在这里node是一个指针,因而使用->
}
}
int main() {
int arr[7] = {6, 3, 8, 2, 5, 1, 7};
Tree tree;
int i;
tree.root = NULL;
for (i=0; i<7; i++) {
insert(&tree, arr[i]);
}
preorder(tree.root); // 暂时还不明白为什么这里没有&tree.root???
// 通常检查一棵树是否是对的,通过检查先序遍历&中序遍历
Sleep(10000);
}
先序遍历结果:
3 生成树,通过中序遍历验证:
我们会发现中序遍历正好是从小到大排序的结果,因为我们的树就是按照这个规则建立的。
#include<stdio.h>
#include<windows.h>
#include<string.h>
#include<stdlib.h> // 因为需要写NULL,所以需要这个库
#include<malloc.h> // 这里用于申请内存
//本代码建立在<没有重复数字>的前提下
// 节点结构体
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;
}
}
}
}
}
// 先序遍历, 在这里node是一个指针
void preorder(Node* node) {
if (node != NULL) {
printf("%d\n", node -> data); // 在这里node是一个指针,因而使用->
preorder(node -> left);
preorder(node -> right);
}
}
// 中序遍历, 在这里node是一个指针
void inorder(Node* node) {
if (node != NULL) {
inorder(node -> left);
printf("%d\n", node -> data); // 在这里node是一个指针,因而使用->
inorder(node -> right);
}
}
// 后序遍历, 在这里node是一个指针
void postorder(Node* node) {
if (node != NULL) {
postorder(node -> left);
postorder(node -> right);
printf("%d\n", node -> data); // 在这里node是一个指针,因而使用->
}
}
int main() {
int arr[7] = {6, 3, 8, 2, 5, 1, 7};
Tree tree;
int i;
tree.root = NULL;
for (i=0; i<7; i++) {
insert(&tree, arr[i]);
}
inorder(tree.root); // 通常检查一棵树是否是对的,通过检查先序遍历&中序遍历
Sleep(10000);
}
中序遍历结果:
我们会发现中序遍历正好是从小到大排序的结果,因为我们的树就是按照这个规则建立的。
简单吧~
4 求树的高度:需要用到递归
关于递归,请参考我的另外的博文:
C语言--(六)递归Recursion(点灯笼)
https://blog.youkuaiyun.com/zjc910997316/article/details/88983773
此树高度是4
计算高度思路:
左边比较大,左孩子高度加一即可。
求树高完整代码;
#include<stdio.h>
#include<windows.h>
#include<string.h>
#include<stdlib.h> // 因为需要写NULL,所以需要这个库
#include<malloc.h> // 这里用于申请内存
//本代码建立在<没有重复数字>的前提下
// 节点结构体
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;
}
}
}
}
}
// 1 先序遍历, 在这里node是一个指针
void preorder(Node* node) {
if (node != NULL) {
printf("%d\n", node -> data); // 在这里node是一个指针,因而使用->
preorder(node -> left);
preorder(node -> right);
}
}
// 2 中序遍历, 在这里node是一个指针
void inorder(Node* node) {
if (node != NULL) {
inorder(node -> left);
printf("%d\n", node -> data); // 在这里node是一个指针,因而使用->
inorder(node -> right);
}
}
// 3 后序遍历, 在这里node是一个指针
void postorder(Node* node) {
if (node != NULL) {
postorder(node -> left);
postorder(node -> right);
printf("%d\n", node -> data); // 在这里node是一个指针,因而使用->
}
}
// 求树高度
int get_height (Node* node) { // 左边比较大,左孩子高度加一即是当前树的高度。
if (node == NULL) {
return 0;
}
else {
int left_h = get_height(node -> left);
int right_h = get_height(node -> right);
int max = left_h;
if (right_h > left_h) {
max = right_h;
}
return max + 1;
}
}
int main() {
int arr[7] = {6, 3, 8, 2, 5, 1, 7};
Tree tree;
int i;
int h;
tree.root = NULL;
for (i=0; i<7; i++) {
insert(&tree, arr[i]);
}
// inorder(tree.root); // 通常检查一棵树是否是对的,通过检查先序遍历&中序遍历
h = get_height(tree.root);// 求树高度
printf("h = %d", h);
Sleep(10000);
}
结果:
重点提示:
递归一定设置好递归出口
int get_height (Node* node) { // 左边比较大,左孩子高度加一即是当前树的高度。
if (node == NULL) { // 这里是递归出口,当到了子节点没有东西的时候结束
return 0;
}
else {
int left_h = get_height(node -> left);
int right_h = get_height(node -> right);
int max = left_h;
if (right_h > left_h) {
max = right_h;
}
return max + 1;
}
}
5 求最大值:
1 对于二叉搜索树最大值在最右边
2 对于任意给定的一棵树求最大值,思路如下:
取 max(m1, m2) 与 n 比较。
求整个树中的最大值max完整代码:
#include<stdio.h>
#include<windows.h>
#include<string.h>
#include<stdlib.h> // 因为需要写NULL,所以需要这个库
#include<malloc.h> // 这里用于申请内存
//本代码建立在<没有重复数字>的前提下
// 节点结构体
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;
}
}
}
}
}
// 先序遍历, 在这里node是一个指针
void preorder(Node* node) {
if (node != NULL) {
printf("%d\n", node -> data); // 在这里node是一个指针,因而使用->
preorder(node -> left);
preorder(node -> right);
}
}
// 中序遍历, 在这里node是一个指针
void inorder(Node* node) {
if (node != NULL) {
inorder(node -> left);
printf("%d\n", node -> data); // 在这里node是一个指针,因而使用->
inorder(node -> right);
}
}
// 后序遍历, 在这里node是一个指针
void postorder(Node* node) {
if (node != NULL) {
postorder(node -> left);
postorder(node -> right);
printf("%d\n", node -> data); // 在这里node是一个指针,因而使用->
}
}
// 计算树高
int get_height (Node* node) { // 左边比较大,左孩子高度加一即是当前树的高度。
if (node == NULL) {
return 0;
}
else {
int left_h = get_height(node -> left);
int right_h = get_height(node -> right);
int max = left_h;
if (right_h > left_h) {
max = right_h;
}
return max + 1;
}
}
// 计算树中的最大值
int get_maximum(Node* node) {
if (node == NULL) {
return -1; // 空节点
}
else {
int m1 = get_maximum(node -> left);
int m2 = get_maximum(node -> right);
int m3 = node ->data;
int max = m1;
if (m2 > max) { max = m2; }
if (m3 > max) { max = m3; }
return max;
}
}
int main() {
int arr[7] = {6, 3, 8, 2, 5, 1, 7};
Tree tree;
int i;
int h;
int m;
tree.root = NULL;
for (i=0; i<7; i++) {
insert(&tree, arr[i]);
}
// inorder(tree.root); // 通常检查一棵树是否是对的,通过检查先序遍历&中序遍历
// h = get_height(tree.root);
// printf("h = %d", h);
m = get_maximum(tree.root);
printf("maximum = %d", m);
Sleep(10000);
}
结果: