做 九度笔记之 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.
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;
}