本文学习的是:二叉搜索(排序)树的普通操作
包括:插入,删除,查找,前序遍历,中序遍历,后序遍历,树的最大深度,最小深度,最大值,最小值和节点个数。
首先需要清楚二叉搜索树的定义:
二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
(4)没有键值相等的节点。
图1
如图1所示,就是一棵二叉搜索树!
下面对程序进行解析:
(0)前提准备:
做了一个结构体,方便操作。
<span style="font-family:SimSun;font-size:18px;">struct node {
int value;
struct node* left;
struct node* right;
};
typedef struct node NODE;
typedef struct node* PNODE;
</span>
(1)插入函数insert_node(PNODE *n int value)
思路:传入插入函数的参数是(1)指向tree的指针(2)要插入的数值value
如果树为空,那么就新建一棵树,让其根(root)为要插入的数值value
如果树不为空,那么让value与原来树的根(相对根)进行比较,如果比它小,必然要插入到左子树中,如果比它大,必然要插入到右子树中。这里就要用到递归,将指向左子树的指针更改为参数值,进行对insert_node函数的调用,同理右子树。
这里注意二叉搜索树的第(4)条,如果要插入的数值在tree中已经存在,那么什么也不做,直接返回。
C语言代码:
(1)插入节点函数
<span style="font-family:SimSun;font-size:18px;">void insert_node (PNODE* n,int value) {
if(*n == NULL) {
new_node(n,value);
}else if ((*n)->value == value){
return ;
}else if (value < (*n)->value) {
insert_node(&((*n)->left),value);
}else {
insert_node(&((*n)->right),value);
}
}</span>
(2)新建节点函数
<span style="font-family:SimSun;font-size:18px;">void new_node (PNODE* n,int value) {
*n = (PNODE)malloc(sizeof(NODE));
if(*n != NULL) {
(*n)->value = value;
(*n)->left = NULL;
(*n)->right = NULL;
}
}</span>
(2)删除 delet_node(PNODE* n,int value)
这是最麻烦的一个操作了!因为删除要考虑4种情况。
思路:
(1)如果要删除的节点是叶子节点:比如我要删除的是10(或者30,或者50)
图1
将20这个节点指向10这个节点的指针设为NULL,然后释放它。
(2)如果要删除的节点只有右节点:我要删除的是20
图2
将30这个节点顶替20这个位置,然后释放它
(3)如果要删除的节点只有左节点:同理(2)(就不上图了。)
(4)如果要删除的节点既有左节点(左子树)又有节点(子树):我要删除的是20
图1
可以在20节点的左子树中找最大的值或者在右子树中找到最小的值,顶替20的位置,释放它,然后再调整树。
在编码的过程中可以将第一种情况与第二种情况合并。
传入删除函数的参数是(1)指向tree的指针(2)要删除的数值value
C语言代码:
(1)判断要删除哪一个
void delet_node(PNODE* n,int value) {
if(*n == NULL) {
return ;
}
if((*n)->value == value) {
deletenode(n);
}else if(value < (*n)->value) {
delet_node(&((*n)->left),value);
}else {
delet_node(&((*n)->right),value);
}
}
如果树非空,对当前节点与要删除的节点做对比,如果不等,进行左右比较,如果相等要进行删除工作。
(2)判断如果删
void deletenode(PNODE* n) {
PNODE temp = NULL;
if(n == NULL) {
return ;
}
if((*n)->right == NULL) {
temp = *n;
*n = (*n)->left;
free_node(n);
}else if((*n)->left == NULL) {
temp = *n;
*n = (*n)->right;
free_node(n);
}else {
for(temp == (*n)->right;temp->left !=NULL;temp = temp->left);
temp->left = (*n)->left;
temp = (*n);
*n = (*n)->right;
free_node(&temp);
}
}
这里即对如上4种情况讨论(合并为3种)的代码实现。
(3)正式删除
void free_node(PNODE* n) {
if(*n !=NULL) {
free(*n);
*n = NULL;
}
}
这里是真正的删除节点操作。
(3)查找find_node(PNODE n,int value)
有了上面两个函数的基础,再编写查找就不是很困难了,还是使用递归。但要注意,前两个不需要返回值,所以都设为void类型,但是查找要有返回值,是否为NULL,所以函数返回类型是PNODE
C语言代码:
PNODE find_node (PNODE n,int value) {
if (n == NULL) {
return NULL;
}else if (n->value ==value) {
return n;
}else if (value <= n->value) {
return find_node(n->left,value);
}else {
return find_node(n->right,value);
}
}
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
struct node {
int value;
struct node* left;
struct node* right;
};
typedef struct node NODE;
typedef struct node* PNODE;
void new_node (PNODE* n,int value) {
*n = (PNODE)malloc(sizeof(NODE));
if(*n != NULL) {
(*n)->value = value;
(*n)->left = NULL;
(*n)->right = NULL;
}
}
void free_node(PNODE* n) {
if(*n !=NULL) {
free(*n);
*n = NULL;
}
}
void deletenode(PNODE* n) {
PNODE temp = NULL;
if(n == NULL) {
return ;
}
if((*n)->right == NULL) {
temp = *n;
*n = (*n)->left;
free_node(n);
}else if((*n)->left == NULL) {
temp = *n;
*n = (*n)->right;
free_node(n);
}else {
for(temp == (*n)->right;temp->left !=NULL;temp = temp->left);
temp->left = (*n)->left;
temp = (*n);
*n = (*n)->right;
free_node(&temp);
}
}
PNODE find_node (PNODE n,int value) {
if (n == NULL) {
return NULL;
}else if (n->value ==value) {
return n;
}else if (value <= n->value) {
return find_node(n->left,value);
}else {
return find_node(n->right,value);
}
}
void insert_node (PNODE* n,int value) {
if(*n == NULL) {
new_node(n,value);
}else if ((*n)->value == value){
return ;
}else if (value < (*n)->value) {
insert_node(&((*n)->left),value);
}else {
insert_node(&((*n)->right),value);
}
}
void delet_node(PNODE* n,int value) {
if(*n == NULL) {
return ;
}
if((*n)->value == value) {
deletenode(n);
}else if(value < (*n)->value) {
delet_node(&((*n)->left),value);
}else {
delet_node(&((*n)->right),value);
}
}
void Pre_order_traversal(PNODE n) {
if(n != NULL) {
printf ("%d ",n->value);
Pre_order_traversal(n->left);
Pre_order_traversal(n->right);
}
}
void In_order_traversal(PNODE n) {
if(n != NULL) {
In_order_traversal(n->left);
printf ("%d ",n->value);
In_order_traversal(n->right);
}
}
void Post_order_traversal(PNODE n) {
if(n != NULL) {
Post_order_traversal(n->left);
Post_order_traversal(n->right);
printf ("%d ",n->value);
}
}
int get_max_depth(PNODE n) {
int left = 0;
int right = 0;
if(n == NULL) {
return 0;
}
if(n->left != NULL) {
left=1 + get_max_depth(n->left);
}
if(n->right != NULL) {
right=1 + get_max_depth(n->right);
}
return (left > right ? left : right);
}
int get_min_depth(PNODE n) {
int left = 0;
int right = 0;
if(n == NULL) {
return 0;
}
if(n->left != NULL) {
left = 1 + get_min_depth(n->left);
}
if(n->right != NULL) {
right = 1 + get_min_depth(n->right);
}
return (left > right) ? right : left;
}
int get_max_value(PNODE n) {
if(n == NULL) {
return 0;
}
if(n->right == NULL) {
return n->value;
}else {
return get_max_value(n->right);
}
}
int get_min_value(PNODE n) {
if(n == NULL) {
return 0;
}
if(n->left == NULL) {
return n->value;
}else {
return get_min_value(n->left);
}
}
int get_num_nodes(PNODE n) {
int left = 0;
int right = 0;
if(n == NULL) {
return 0;
}
if(n->left != NULL) {
left = 1 + get_num_nodes(n->left);
}
if(n->right != NULL) {
right = 1 + get_num_nodes(n->right);
}
return left+right+1;
}
int main() {
char buf[50];
int option;
PNODE tree = NULL;
PNODE node = NULL;
while(1) {
printf ("\n-----------------------\n");
printf ("Options are:\n\n");
printf ("0 Exit\n");
printf ("1 Insert node\n");
printf ("2 Delet node\n");
printf ("3 Find node\n");
printf ("4 Pre order traversal\n");
printf ("5 In order traversal\n");
printf ("6 Post order traversal\n");
printf ("7 Max depth\n");
printf ("8 Min depth\n");
printf ("9 Max value\n");
printf ("10 Min value\n");
printf ("11 Node count\n\n");
printf ("\n-----------------------\n");
printf ("Select an option: ");
scanf ("%d",&option);
printf ("\n------------------------\n");
if (option < 0 || option > 11) {
printf ("Invalid option!");
continue;
}
switch(option) {
case 0:
return 0;
case 1:
printf ("Enter number to insert: ");
scanf ("%d",&option);
printf ("\n\n");
insert_node (&tree,option);
break;
case 2:
printf ("Enter number to delet: ");
scanf ("%d",&option);
printf ("\n\n");
delet_node (&tree,option);
break;
case 3:
printf ("Enter number to find: ");
scanf ("%d",&option);
printf ("\n\n");
node = find_node (tree,option);
if (node != NULL) {
printf ("Found node\n\n");
}else {
printf ("Couldn't find node\n\n");
}
break;
case 4:
printf ("Pre order traversal: ");
printf ("\n\n");
Pre_order_traversal(tree);
break;
case 5:
printf ("In order traversal: ");
printf ("\n\n");
In_order_traversal(tree);
break;
case 6:
printf ("Post order traversal: ");
printf ("\n\n");
Post_order_traversal(tree);
break;
case 7:
printf ("Max depth is %d\n\n",get_max_depth(tree));
break;
case 8:
printf ("Min depth is %d\n\n",get_min_depth(tree));
break;
case 9:
printf ("Max value is %d\n\n",get_max_value(tree));
break;
case 10:
printf ("Min value is %d\n\n",get_min_value(tree));
break;
case 11:
printf ("Node count is %d\n\n",get_num_nodes(tree));
break;
}
}
return 0;
}
多多指正~
![大笑](http://static.blog.csdn.net/xheditor/xheditor_emot/default/laugh.gif)
![大笑](http://static.blog.csdn.net/xheditor/xheditor_emot/default/laugh.gif)