0x01数据结构——C语言实现(二叉查找树)
二叉查找树是一种特殊的二叉树,使二叉树成为二叉查找树的性质是:对于树中的每一个节点X,它的左子树中所有关键字值小于X的关键字值,而它的右子树中所有关键字值大于X的关键字值。这意味着,该树所有的元素可以用某种统一的方式排序。
二叉查找树的C语言实现:
b_search_tree.h
#ifndef B_SEARCH_TREE_H
#define B_SEARCH_TREE_H
/*
二叉树的节点用左右孩子表示法来存储。
*/
typedef enum {
false = 0,
true
} BOOL;
struct node;
typedef struct node node;
typedef node *Bstree;
typedef node *pos;
//根据先序遍历数组来创建树(先序遍历数组中用'#'来表示空节点)
Bstree create_Bstree_preorder(int v[], int begin, int end);
Bstree create_Bstree(int v[], int *begin, int end);
//将一颗树置空
Bstree make_empty(Bstree T);
//判断树是不是空的
BOOL is_empty(Bstree T);
//为节点p添加孩子节点x
BOOL add_child(node *p, int x);
//先序遍历树
void preorder_traversal(Bstree T);
//以数组形式打印
//数组规定如下:用'#'来表示空节点
void preorder_traversal1(Bstree T);
//中序遍历
void inorder_traversal(Bstree T);
//后序遍历
void postorder_traversal(Bstree T);
//寻找节点x的位置
pos search(int x, Bstree T);
//寻找最大的节点
pos find_max(Bstree T);
//寻找最小的节点
pos find_min(Bstree T);
//插入节点x
Bstree insert_node(int x, Bstree T);
//删除节点x
Bstree delete_node(int x, Bstree T);
pos find_rmin(Bstree T);
//输出二叉树的高度
int Bstree_height(Bstree T);
//输出二叉树总结点数目
int node_sum(Bstree T);
//叶子结点数目
int leaves_sum(Bstree T);
//取出节点p的值
int retrieve_p(pos p);
//以层次方式打印输出
void print_Bstree(Bstree T);
void output(Bstree T, int i);
#endif
b_search_tree.c
#include "b_search_tree.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
int val;
struct node *left;//left child
struct node *right;//right child
};
struct node;
typedef struct node node;
typedef node *Bstree;
typedef node *pos;
//根据先序遍历数组来创建树(先序遍历数组中用'#'来表示空节点)
Bstree create_Bstree_preorder(int v[], int begin, int end)
{
return create_Bstree(v, &begin, end);
}
Bstree create_Bstree(int v[], int *begin, int end)
{
if((*begin)>end || v==NULL)
return NULL;
Bstree T = NULL;
if(v[*begin]!='#') {
T=(node *)malloc(sizeof(node));
T->val = v[*begin];
(*begin)++;
if(v[*begin] == '#') {
T->left = NULL;
(*begin)++;
T->right = create_Bstree(v, begin, end);
} else {
T->left = create_Bstree(v, begin, end);
(*begin)++;
T->right = create_Bstree(v, begin, end);
}
}
return T;
}
//将一颗树置空
Bstree make_empty(Bstree T)
{
if(T!=NULL) {
make_empty(T->left);
make_empty(T->right);
printf("free node with value %d\n", T->val);
free(T);
T = NULL;
}
return T;
}
//判断树是不是空的
BOOL is_empty(Bstree T)
{
return (T == NULL);
}
//为节点p添加孩子节点x
BOOL add_child(node *p, int x)
{
if(p->left == NULL) {
p->left = (node*)malloc(sizeof(node));
p->left->val = x;
p->left->left = p->left->right = NULL;
return true;
} else if(p->right == NULL) {
p->right = (node*)malloc(sizeof(node));
p->right->val = x;
p->right->left = p->right->right = NULL;
return true;
} else {
return false;
}
}
//先序遍历树
void preorder_traversal(Bstree T)
{
if(T!=NULL) {
printf("%d", T->val);
preorder_traversal(T->left);
preorder_traversal(T->right);
}
}
//以先序遍历数组形式打印
//数组规定如下:用'#'来表示空节点
void preorder_traversal1(Bstree T)
{
if(T!=NULL) {
printf("%d", T->val);
if(T->left == NULL) {
printf("#");
if(T->right == NULL) {
printf("#");
} else {
preorder_traversal1(T->right);
}
} else {
preorder_traversal1(T->left);
if(T->right == NULL) {
printf("#");
} else {
preorder_traversal1(T->right);
}
}
}
}
//中序遍历
void inorder_traversal(Bstree T)
{
if(T!=NULL) {
inorder_traversal(T->left);
printf("%d", T->val);
inorder_traversal(T->right);
}
}
//后序遍历
void postorder_traversal(Bstree T)
{
if(T!=NULL) {
postorder_traversal(T->left);
postorder_traversal(T->right);
printf("%d", T->val);
}
}
//寻找节点x的位置
pos search(int x, Bstree T)
{
if(T!=NULL) {
if(T->val == x) {
return T;
} else if(x<T->val) {
return search(x, T->left);
} else {
return search(x, T->right);
}
} else {
return NULL;
}
}
//寻找最大的节点
pos find_max(Bstree T)
{
if(T!=NULL) {
while(T->right!=NULL) {
T = T->right;
}
}
return T;
}
//寻找最小的节点
pos find_min(Bstree T)
{
if(T != NULL) {
while(T->left != NULL) {
T = T->left;
}
}
return T;
}
//插入节点x
Bstree insert_node(int x, Bstree T)
{
if(T == NULL) {
T = (node *)malloc(sizeof(node));
T->val = x;
T->left = T->right = NULL;
} else {
if(x>T->val) {
T->right = insert_node(x, T->right);
} else if(x<T->val) {
T->left = insert_node(x, T->left);
}
}
return T;
}
//删除节点x
Bstree delete_node(int x, Bstree T)
{
/* 对于删除节点,需要考虑集中情况
* 如果节点是叶子节点,那么它可以被立即删除
* 如果节点有一个孩子,则该节点可以在其父节点调整指针跳过该节点后被删除
* 如果节点有两个孩子,一般的删除策略是用其右子树的最小的数据代替该节点的数据并递归地删除
* 那个节点。
*/
if(T!=NULL) {
if(x<T->val) {
T->left = delete_node(x,T->left);
} else if(x>T->val) {
T->right = delete_node(x,T->right);
} else {
if(T->left!=NULL && T->right!=NULL) {
/*两个孩子的节点*/
/*寻找右子树最小节点*/
/*递归方式*/
pos tmp = find_min(T->right);
T->val = tmp->val;
T->right = delete_node(T->val, T->right);
/*非递归方式*/
// pos tmp = find_rmin(T);
// if(tmp == T) {
// T->val = tmp->right->val;
// tmp->right = tmp->right->right;
// free(tmp->right);
// } else {
// T->val = tmp->left->val;
// free(tmp->left);
// tmp->left = tmp->left->right;
// }
} else {
pos tmp = T;
if(T->left == NULL) {
T = T->right;
} else if(T->right == NULL) {
T = T->left;
}
free(tmp);
}
}
}
return T;
}
pos find_rmin(Bstree T)
{
/*
* 寻找数T右子树最小节点
* 返回其父节点
*/
if(T != NULL) {
pos tmp = T;
T = T->right;
while(T!=NULL && T->left!=NULL) {
tmp = T;
T = T->left;
}
return tmp;
} else {
return T;
}
}
//输出二叉树中某个节点的高度
//对任意节点n_i,n_i的深度(depth)为从根到n_i的唯一路径的长。因此,根的深度为0。
//n_i的高(height)是从n_i到一片树叶的最长路径的长。
//因此所有树叶的高度都是0。一棵树的高等于它的根的高。
//一棵树的深度等于它的最深的树叶的深度,该深度总是等于这棵树的高。
int Bstree_height(Bstree T)
{
if(T!=NULL) {
int h;
if(T->left==NULL && T->right==NULL) {
h=0;
}else {
int h1, h2;
h1 = Bstree_height(T->left)+1;
h2 = Bstree_height(T->right)+1;
h = (h1>h2?h1:h2);
}
return h;
} else {
return -1;
}
}
//输出二叉树总结点数目
int node_sum(Bstree T)
{
if(T!=NULL) {
int sum = 0;
if(T->left==NULL && T->right==NULL) {
sum = 1;
}else {
int sum1, sum2;
sum1 = node_sum(T->left);
sum2 = node_sum(T->right);
sum = sum1+sum2+1;
}
return sum;
} else {
return 0;
}
}
//叶子结点数目
int leaves_sum(Bstree T)
{
int sum = 0;
if(T!=NULL) {
if(T->left==NULL && T->right==NULL) {
sum = 1;
}else {
int sum1, sum2;
sum1 = leaves_sum(T->left);
sum2 = leaves_sum(T->right);
sum = sum1+sum2;
}
}
return sum;
}
//取出节点p的值
int retrieve_p(pos p)
{
return p->val;
}
//以层次方式打印输出
void print_Bstree(Bstree T)
{
output(T,0);
}
void output(Bstree T, int i)
{
if(T != NULL) {
for(int j = 0; j<i; j++) {
printf("\t");
}
printf("%d\n", T->val);
i++;
if(!(T->left == NULL && T->right == NULL)) {
if(T->left == NULL) {
printf("\n");
output(T->right,i);//输出右子树
} else if(T->right == NULL) {
output(T->left,i);//输出左子树
printf("\n");
} else {
output(T->left,i);//输出左子树
output(T->right,i);//输出右子树
}
}
}
}
main.c
#include "b_search_tree.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int A[13]={6,2,1,'#','#',4,3,'#','#','#',8,'#','#'};
int h = 0, sum = 0, leaves = 0;
Bstree T = create_Bstree_preorder(A,0,12);
int x = 6;
pos tmp = NULL;
print_Bstree(T);
preorder_traversal(T);
printf("\n");
inorder_traversal(T);
printf("\n");
postorder_traversal(T);
printf("\n");
preorder_traversal1(T);
printf("\n");
tmp = search(x,T);
printf("%d\n", retrieve_p(tmp));
h = Bstree_height(tmp);
printf("height of the node %d: %d\n", x,h);
tmp = find_max(T);
printf("the max node: %d\n", retrieve_p(tmp));
tmp = find_min(T);
printf("the min node: %d\n", retrieve_p(tmp));
sum = node_sum(T);
printf("this tree has %d node(s)\n", sum);
leaves = leaves_sum(T);
printf("this tree has %d leaves\n", leaves);
T = insert_node(5, T);
printf("after insert\n");
print_Bstree(T);
printf("after delete\n");
T = delete_node(2, T);
print_Bstree(T);
T = make_empty(T);
printf("empty? %d\n", is_empty(T));
return 0;
}