码迷,mamicode.com
首页 > 其他好文 > 详细

二叉搜索树操作

时间:2016-04-29 17:46:52      阅读:118      评论:0      收藏:0      [点我收藏+]

标签:

本文学习的是:二叉搜索(排序)树的普通操作

包括:插入,删除,查找,前序遍历,中序遍历,后序遍历,树的最大深度,最小深度,最大值,最小值和节点个数。


首先需要清楚二叉搜索树的定义

二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树:
(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);
	}
}


4)到此为止,我们就解决了二叉搜索树中最难的三种操作,即插入,删除和搜索,以下其他操作就很容易了,这里就直接给出全部代码。

#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://blog.csdn.net/qq_28684963/article/details/51240366

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!