二叉排序数的总结

做 九度笔记之 1467:二叉排序树时又重新翻阅了算法导论里相关的知识,之前都是看看也没有动手实践,这次就顺便把二叉排序数的其它函数都实现了下,还真发现了不少问题。

以下前提条件是所有的数都互不相同。

1查找

通过比较查找数值qvalue和 当前节点值node.value,如果相同就找到了,如果qvalue<node.value 就跑到左子树查找,否者到右子树查找。
biNode* search(biNode *root,int value){
	biNode*x =root;
	while(x!=NULL && x->value!=value){
		if(x->value > value){
			x = x->Left;
		}else
			x = x->Right;
	}
	return x;
}
如果找不到就返回NULL
注意这里循环的判断条件为 
while(x!=NULL && x->value!=value)

2.最大最小值

biNode* treeMax(biNode *root){
	biNode* x = root;
	while(x->Right!=NULL){
		x = x->Right;
	}
	return x;
}

biNode* treeMin(biNode *root){
	biNode* x = root;
	while(x->Left!=NULL){
		x = x->Left;
	}
	return x;
}

循环条件为
while(x->Right!=NULL)
while(x->Left!=NULL)

3.插入

类似查找,不过需要一个额外的变量y,表示当前节点的父亲节点。

void insert(biNode *&root,int value){
	biNode *temNode = new biNode(value);
	if(root==NULL){
		root  = temNode;
		return;
	}
	biNode *y = NULL;
	biNode *x = root;
	while(x!=NULL){
		if(value > x->value){
			y = x;
			x = x->Right;
		}else{
			y = x;
			x = x->Left;
		}
	}

	if(value < y->value){
		y->Left = temNode;
	}else
		y->Right = temNode;
	temNode->Parent = y;
}
这里需要注意的是参数 root 应为

biNode *&root
因为root初始为NULL, 出入后root的值就改变了,但是要想更改root的值就要用引用或者指针,也就是指针的指针,我们在这里用指针的引用。

然后需要注意的就是 要先判断root是否为NULL

这里的循环判断条件

while(x!=NULL)

4.求后继或前任

注意的是要分两种情况考虑。
后继就是求大于x.value的 最小数,如果存在右子树,右子树上的值都大于x.value,所以只要求treeMin(x->Right)就行
如果不存在右子树的话,就要向上寻找一个点y,x  满足x是y的左孩子, 则y的值大于以x为根的子树上所有节点的值。
在寻找过程中,x是y的右孩子,则y的值小于x的值。直到满足上面的条件,

求前继是相反的过程。
biNode* treeSuccessor(biNode *x){
	if(x->Right!=NULL){
		return treeMin(x->Right);
	}
	biNode *y = x->Parent;
	while(y!=NULL && x==y->Right){
		x = y;
		y = y->Parent;
	}
	return y;

}
biNode* treePredecessor(biNode *x){
	if(x->Left!=NULL){
		return treeMax(x->Left);
	}
	biNode *y = x->Parent;
	while(y!=NULL && x==y->Left){
		x = y;
		y = y->Parent;
	}
	return y;
}


5.删除

删除节点z


删除节点分为上面4中情况,(d)情况通过转换转为(c)情况。
void transplant(biNode *&root,biNode *u,biNode *v){// MUST *& ROOT
	if(u->Parent==NULL)
		root = v;//ATTENTION
	else if(u == u->Parent->Left)
		u->Parent->Left = v;//
	else
		u->Parent->Right = v;//
	if(v!=NULL)
		v->Parent = u->Parent;
}

void deleteNode(biNode *&root, biNode *z){// MUST *& ROOT
	if(z->Left==NULL){
		transplant(root,z,z->Right);
	}else if(z->Right == NULL)
		transplant(root,z,z->Left);
	else{
		//biNode *y = treeSuccessor(z);//ATTENION
		biNode *y = treeMin(z->Right);//ATTENION
		if(y->Parent!=z){
			transplant(root,y,y->Right);
			y->Right = z->Right;
			z->Right->Parent = y;
		}
		transplant(root,z,y);
		y->Left = z->Left;//ATTENTION
		z->Left->Parent = y;//
	}
}

transplant函数的作用是把
TRANSPLANT, which replaces one subtree as a child of its parent with
another subtree. When TRANSPLANT replaces the subtree rooted at node u with
the subtree rooted at node , node u’s parent becomes node ’s parent, and u’s
parent ends up having as its appropriate child.

transplant 和deleteNode函数都有可能改变root的值,所以root的参数为 指针引用
void transplant(biNode *&root,biNode *u,biNode *v)
void deleteNode(biNode *&root, biNode *z)

总结 

首先要谨记root为指针,指针保存的是地址,一定要注意函数是否有可能需要修改root的值,是的话就要把root的参数 为指针的引用, 因为只有这样才能真正的修改root的值。


//============================================================================
// Name        : BiTree.cpp
// Author      : wdy
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
using namespace std;
struct biNode{
	int value;
	biNode* Parent;
	biNode* Left;
	biNode* Right;

public:
	biNode(int value_):value(value_),Parent(NULL),Left(NULL),Right(NULL){};
};
//biNode *root=NULL;
void preWalkPrintTree(biNode *root){
	if(root==NULL){
		return;
	}
	std::cout<< root->value <<" ";
	preWalkPrintTree(root->Left);
	preWalkPrintTree(root->Right);
}
biNode* search(biNode *root,int value){
	biNode*x =root;
	while(x!=NULL && x->value!=value){
		if(x->value > value){
			x = x->Left;
		}else
			x = x->Right;
	}
	return x;
}
biNode* treeMax(biNode *root){
	biNode* x = root;
	while(x->Right!=NULL){
		x = x->Right;
	}
	return x;
}

biNode* treeMin(biNode *root){
	biNode* x = root;
	while(x->Left!=NULL){
		x = x->Left;
	}
	return x;
}
void insert(biNode *&root,int value){
	biNode *temNode = new biNode(value);
	if(root==NULL){
		root  = temNode;
		return;
	}
	biNode *y = NULL;
	biNode *x = root;
	while(x!=NULL){
		if(value > x->value){
			y = x;
			x = x->Right;
		}else{
			y = x;
			x = x->Left;
		}
	}

	if(value < y->value){
		y->Left = temNode;
	}else
		y->Right = temNode;
	temNode->Parent = y;
}
biNode* treeSuccessor(biNode *x){
	if(x->Right!=NULL){
		return treeMin(x->Right);
	}
	biNode *y = x->Parent;
	while(y!=NULL && x==y->Right){
		x = y;
		y = y->Parent;
	}
	return y;

}
biNode* treePredecessor(biNode *x){
	if(x->Left!=NULL){
		return treeMax(x->Left);
	}
	biNode *y = x->Parent;
	while(y!=NULL && x==y->Left){
		x = y;
		y = y->Parent;
	}
	return y;
}

void transplant(biNode *&root,biNode *u,biNode *v){// MUST *& ROOT
	if(u->Parent==NULL)
		root = v;//ATTENTION
	else if(u == u->Parent->Left)
		u->Parent->Left = v;//
	else
		u->Parent->Right = v;//
	if(v!=NULL)
		v->Parent = u->Parent;
}

void deleteNode(biNode *&root, biNode *z){// MUST *& ROOT
	if(z->Left==NULL){
		transplant(root,z,z->Right);
	}else if(z->Right == NULL)
		transplant(root,z,z->Left);
	else{
		//biNode *y = treeSuccessor(z);//ATTENION
		biNode *y = treeMin(z->Right);//ATTENION
		if(y->Parent!=z){
			transplant(root,y,y->Right);
			y->Right = z->Right;
			z->Right->Parent = y;
		}
		transplant(root,z,y);
		y->Left = z->Left;//ATTENTION
		z->Left->Parent = y;//
	}
}
void test(){
	int num[11] = {15,6,18,3,7,17,20,2,4,13,9};
	biNode *root=NULL;//ATTENTION
	std::cout<<"insert"<<std::endl;
	for(int i = 0;i<11;i++){
		insert(root,num[i]);
		/*
		preWalkPrintTree(root);
		std::cout<<std::endl;
		std::cout<<"tree max"<< treeMax(root)->value <<std::endl;
		std::cout<<"tree min"<< treeMin(root)->value <<std::endl;
		*/
	}
	//std::cout<<"2 succe"<<treeSuccessor(search(root,2))->value<<std::endl;;
	//std::cout<<"4 succe"<<treeSuccessor(search(root,4))->value<<std::endl;;
	//std::cout<<"9 succe"<<treeSuccessor(search(root,9))->value<<std::endl;;
	//std::cout<<"20 succe"<<treeSuccessor(search(root,20))->value<<std::endl;;
	//std::cout<<"15 succe"<<treeSuccessor(search(root,15))->value<<std::endl;;
	//std::cout<<"13 succe"<<treeSuccessor(search(root,13))->value<<std::endl;;
	//std::cout<<"****"<<std::endl;
	//std::cout<<"2 succe"<<treePredecessor(search(root,2))->value<<std::endl;;
	//std::cout<<"4 succe"<<treePredecessor(search(root,4))->value<<std::endl;;
	//std::cout<<"9 succe"<<treePredecessor(search(root,9))->value<<std::endl;;
	//std::cout<<"20 succe"<<treePredecessor(search(root,20))->value<<std::endl;;
	//std::cout<<"15 succe"<<treePredecessor(search(root,15))->value<<std::endl;;
	//std::cout<<"7 succe"<<treePredecessor(search(root,7))->value<<std::endl;;
	preWalkPrintTree(root);
	std::cout<<"****"<<std::endl;
	deleteNode(root,search(root,15));//Attention
	//biNode =
	preWalkPrintTree(root);

}
int main() {
	//cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
	test();
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值