Exemplo n.º 1
0
static void btree_push(struct btree_info *info,
			struct bnode_info *node)
{
	assert(info != NULL);
	assert(node != NULL);
	
	bnode_init(node);

	// 1. 是否为空树
	if (info->root == NULL) {
		info->root = node;
		return ;
	}
	// 2.非空树
	struct bnode_info **pparent = &info->root;
	struct bnode_info *cur = NULL;

	while (*pparent != NULL) {
		cur = *pparent;
		if (info->cmp(node, cur) >= 0) {
			pparent = &cur->rchild;
		} else {
			pparent = &cur->lchild;
		}
	}  
	*pparent = node;
	node->parent = cur;

}
Exemplo n.º 2
0
bnode* bnode_create(void* k,void* v,int kS,int vS,bnode* p,bnode* l,bnode* r){
	bnode* node = malloc(sizeof(bnode));
	if(!node){return NULL;}
	node->key = malloc(kS);
	node->value = malloc(vS);
	if(!node->key || !node->value){
		free(node->key);
		free(node->value);
		return NULL;
	}
	if(k){memcpy(node->key,k,kS);}
	else{node->key = 0;}

	if(v){memcpy(node->value,v,vS);}
	else{node->value = NULL;}

	bnode_init(node,node->key,node->value,kS,vS,p,l,r);
	return node;
}
Exemplo n.º 3
0
Arquivo: btree.c Projeto: sktwj/var
//第2个参数是要删除的节点的小结构体的地址
static inline void del_node(struct btree *btree, struct bnode *bnode)
{
	//树上的节点的身份
	enum e_id {
		ROOT, LCHILD, RCHILD,
	} id;

	if (!bnode->parent) { //是否树根节点
		id = ROOT;
	} else if (bnode->parent->lchild == bnode) { //是否是其父亲节点的左孩子
		id = LCHILD;
	} else if (bnode->parent->rchild == bnode) { //是否是其父亲节点的右孩子
		id = RCHILD;
	}

	if (!bnode->lchild && !bnode->rchild) { //如果要删除的节点是叶子节点
		printf("ok\n");
		switch (id) {
		case ROOT:
			btree->root = NULL;
			break;
		case LCHILD:
			printf("ok1\n");
			bnode->parent->lchild = NULL;
			bnode->parent = NULL;
			break;
		case RCHILD:
			printf("ok2\n");
			bnode->parent->rchild = NULL;
			bnode->parent = NULL;
			break;
		}

	} else if (bnode->lchild && !bnode->rchild) { //如果要删除的节点有左孩子,没有右孩子
		switch (id) {
		case ROOT:
			bnode->lchild->parent = NULL;
			btree->root = bnode->lchild;
			//bnode->parent->lchild = bnode->lchild;
			break;
		case LCHILD:
			bnode->lchild->parent = bnode->parent;
			bnode->parent->lchild = bnode->lchild;
			bnode_init(bnode);
			break;
		case RCHILD:
			bnode->lchild->parent = bnode->parent;
			bnode->parent->rchild = bnode->lchild;
			bnode_init(bnode);
			break;
		}

	} else if (!bnode->lchild && bnode->rchild) { //如果要删除的节点有右孩子,没有左孩子
		switch (id) {
		case ROOT:
			bnode->rchild->parent = NULL;
			btree->root = bnode->rchild;
			break;
		case LCHILD:
			bnode->rchild->parent = bnode->parent;
			bnode->parent->lchild = bnode->rchild;
			bnode_init(bnode);
			break;
		case RCHILD:
			bnode->rchild->parent = bnode->parent;
			bnode->parent->rchild = bnode->rchild;
			bnode_init(bnode);
			break;
		}

	} else { //如果要删除的节点两个孩子都存在
	//找到一个能顶替删除节点的节点来取代要删除的节点,可以找这样的两个节点之一:
	//1、要删除节点的左孩子的最右边的孩子(其实就是找要删除节点的左子树中值最大的节点)
	//2、要删除节点的右孩子的最左边的孩子(其实就是找要删除节点的右子树中值最小的节点)
	
	//下面的代码以1来做:
		//定位到要删除节点的顶替节点
		struct bnode *cur = bnode->lchild;
		while (cur->rchild) {
			cur = cur->rchild;
		}

		//判断能顶替要删除的节点是其父亲节点的左孩子还是右孩子
		if (cur == cur->parent->lchild) { //是左孩子
			cur->parent->lchild = cur->lchild;
		} else { //是右孩子
			cur->parent->rchild = cur->lchild;
		}

		if (cur->lchild) { //cur的左孩子是否存在
			cur->lchild->parent = cur->parent;
		} 

		switch (id) {
		case ROOT:
			btree->root = cur;
			break;
		case LCHILD:
			bnode->parent->lchild = cur;
			break;
		case RCHILD:
			bnode->parent->rchild = cur;
			break;
		}

		//cur接收所有要删除节点bnode的所有关系
		cur->parent = bnode->parent;
		cur->lchild = bnode->lchild;
		cur->rchild = bnode->rchild;
	
		if (cur->lchild) {
			cur->lchild->parent = cur;
		}
		if (cur->rchild) { //其实这个判断条件可以不要,因为既然要删除的节点必定是有两个孩子的,我们选择的能顶替它(要删除的节点)的节点是它左(要删除节点)孩子的最右边的孩子,假如它的左孩子没有右孩子,那么它的左孩子就是能顶替它的节点,如果该节点没有左孩子,那么上面的第230行如果不判断,231行就会出现段错误。但右孩子之所以不用判断,是因为它现在接收的右孩子就是要删除节点的右孩子(该右孩子必定存在,否则我们要删除的节点就不是有两个孩子的节点)。
			cur->rchild->parent = cur;
		}
	}

	bnode_init(bnode); //初始化要删除的节点,使其不再指向之前所指向的节点
}