【编程练习】二叉查找树原理及基本操作编程(GNU C实现)

二叉查找树,又称二叉排序树


二叉查找树的定义:

(1)任意某节点x的左子树y和右子树z,满足key[y]<=key[x]<=key[z];

(2)包含关键字域key,指向左子女指针left_child指向右子女指针right_child,指向双亲指针parent,卫星数据data;


二叉查找树的查找:

(1)从根节点x开始,逐步下降,比较k与key的大小,相同则查找成功直接返回,否则若k<key,则继续查找x的左子树,否则继续查找x的右子树;递归步骤(1);

(2)其实递归的过程就是,一条由树根下降的过程;

(3)最大关键字是沿右子女指针right_child一直到NIL为止所找到的节点;

(4)最小关键字是沿右子女指针left_child一直到NIL为止所找到的节点;

(5)时间复杂度为O(lgn),空间复杂度为O(1);


二叉查找树的插入:

(1)若是一个空树,直接插入,且该节点为根节点;

(2)插入节点为x,在向下寻找插入位置的过程中,使用指针y始终指向所比较的值z的父节点,比较key(x)和key(z)直到z为NIL,根据走向确定x是y的左孩子还是右孩子;

(3)时间复杂度为O(lgn),空间复杂度为O(1);


二叉查找树的删除:

(1)若所删除的节点x,没有左孩子和右孩子,则直接删除x,并更新其父节点的相关指针域,是NIL成为它的子女;

(2)若所删除的节点x,只有一个孩子,则可删除x,并更新其父节点的相关指针域,使x以前的子女成为它的子女;

(3)若所删除的节点x,有两个孩子,则狸猫换太子,删除以x为根的后继(或前驱)y,用y的值替换x;

(4)时间复杂度为O(lgn),空间复杂度为O(1);


二叉查找树的更新:

(1)先删除某节点,然后再插入该节点;

(2)时间复杂度为O(lgn),空间复杂度为O(1);




程序实现:

输入:11个数,包括随机产生的6个随机数,以及固定的5个数来测试查找和删除;
我们另外使用了一个指针指向根节点;
#include<stdio.h>
#include<stdlib.h>

#define ARRAY_LENGTH (6)

struct btree_node{
	struct btree_node *parent;
	struct btree_node *left_child;
	struct btree_node *right_child;
	int key;
};

int * gendrate_seeds()
{	
	int* seeds = (int *)malloc(ARRAY_LENGTH * sizeof(int));
	srand( (unsigned)time( NULL ) );
	int i;
	for(i = 0; i < ARRAY_LENGTH; i++){
		seeds[i] = rand()%100 +1;
	}
	return seeds;
}

struct  btree_node * init_tree_root()
{
	struct btree_node *root_p;
	root_p =  (struct  btree_node *)malloc(sizeof(struct btree_node));
	root_p->left_child = NULL;
	root_p->right_child = NULL;
	root_p->parent = NULL;
	return root_p;
}

int tree_search_key(struct btree_node *cmp, int key)
{	
	if(cmp && cmp->key == key){
		return 1;
	}else if (cmp && cmp->key > key){
		return tree_search_key(cmp->left_child, key);	//impotant
	}else if (cmp && cmp->key < key){
		return tree_search_key(cmp->right_child, key);
	}
	return 0;
}

struct btree_node * tree_search_insert_node(struct btree_node *cmp, int key)
{
	if (cmp && cmp->key >= key){
		if(!cmp->left_child)
			return cmp;
		tree_search_insert_node(cmp->left_child, key);
	}else if (cmp && cmp->key < key){
		if(!cmp->right_child)
			return cmp;
		tree_search_insert_node(cmp->right_child, key);
	}
}

void tree_insert_node(struct btree_node *root_p, struct btree_node *node)
{	
	printf("success insert %d\n", node->key);
	if(!root_p->left_child && !root_p->right_child){
		root_p->left_child = node;
		root_p->right_child = node;
		node->parent = root_p;
		return;
	}
	
	struct btree_node* temp;
	temp = tree_search_insert_node(root_p->left_child, node->key);
	if(temp->key < node->key){
		temp->right_child = node;
	}else{
		temp->left_child = node;
	}
	node->parent = temp;
}

struct btree_node * tree_search_delete_node(struct btree_node *cmp, int key)
{
	if (cmp && cmp->key == key){
			return cmp;
	}else if (cmp && cmp->key < key){
		return tree_search_delete_node(cmp->right_child, key);
	}else if (cmp && cmp->key > key){
		return tree_search_delete_node(cmp->left_child, key);
	}
	return NULL;
}

struct btree_node * tree_search_prior(struct btree_node *root)
{
	while(root->right_child)
		root = root->right_child;
	return root;
}

void tree_delete_node(struct btree_node *root_p, int key)
{
	struct btree_node* temp;
	temp = tree_search_delete_node(root_p->left_child, key);
	if(temp == NULL){
		printf("con not delete because no this data %d\n", key);
		return;
	}
	
	if(!temp->left_child && !temp->right_child){//left_child and right_child are all NULL
		if(temp->parent->left_child == temp){
			temp->parent->left_child = NULL;
		}else{
			temp->parent->right_child = NULL;
		}
		free(temp);
		printf("success delete %d\n", key);
		return;
	}

	if(!temp->left_child && temp->right_child){//left_child is NULL
		if(temp->parent->left_child == temp){
			temp->parent->left_child = temp->right_child;
		}else{
			temp->parent->right_child = temp->right_child;	
		}
		temp->right_child->parent = temp->parent;
		free(temp);
		printf("success delete %d\n", key);
		return;
	}

	if(temp->left_child && !temp->right_child){//right_child is NULL
		if(temp->parent->left_child == temp){
			temp->parent->left_child = temp->left_child;	
		}else{
			temp->parent->right_child = temp->left_child;	
		}
		temp->left_child->parent = temp->parent;
		free(temp);
		printf("success delete %d\n", key);
		return;
	}
		
	//left_child and right_child are all NOT NULL
	printf("success delete %d\n", key);
	struct btree_node *prior;
	prior = tree_search_prior(temp->left_child);
	temp->key = prior->key;

	if(prior!= temp->left_child){
		prior->parent->right_child = prior->left_child;
	}else{
		temp->left_child = prior->left_child;
	}
	
	if(prior->left_child){
		prior->left_child->parent = prior->parent;
	}
	free(prior);
}

void display_btree_shape(struct btree_node* root, int level)
{
	if(root){
		display_btree_shape(root->right_child,level+1);
		printf("\n");
		int i;
		for(i = 0; i < level -1; i++)
			printf("   ");
		printf("%d", root->key);

		display_btree_shape(root->left_child,level+1);
	}
}

void free_btree(struct btree_node *root_p)
{
	while(root_p->left_child)
		tree_delete_node(root_p, root_p->left_child->key);

	free(root_p);
}

int main(void)
{
	
	int *data = gendrate_seeds();
	int datas[] = {45,49,33,101,95};

	struct  btree_node *root_p = init_tree_root();
	
	int i;
	struct  btree_node *ss;
	for(i = 0; i < ARRAY_LENGTH; i++){
		ss = (struct  btree_node *)malloc(sizeof(struct btree_node));
		ss->key= data[i];
		ss->left_child = NULL;
		ss->right_child = NULL;
		ss->parent = NULL;
		tree_insert_node(root_p, ss);
	}

	for(i = 0; i < sizeof(datas) / sizeof(datas[0]); i++){
		ss = (struct  btree_node *)malloc(sizeof(struct btree_node));
		ss->key= datas[i];
		ss->left_child = NULL;
		ss->right_child = NULL;
		ss->parent = NULL;
		tree_insert_node(root_p, ss);
	}

	display_btree_shape(root_p->left_child, 1);
	printf("\n");
	
	int datass = 101;
	if(tree_search_key(root_p->left_child, datass) == 1){
		printf("success query %d\n", datass);
	}else{
		printf("fail query %d\n", datass);
	}

	datass = 99;
	if(tree_search_key(root_p->left_child, datass) == 1){
		printf("success query %d\n", datass);
	}else{
		printf("fail query %d\n", datass);
	}

	printf("--------------------------\n");
	tree_delete_node(root_p, 45);
	tree_delete_node(root_p, 49);
	tree_delete_node(root_p, 33);
	tree_delete_node(root_p, 101);
	tree_delete_node(root_p, 95);
	
	free_btree(root_p);
	free(data);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值