现在的位置: 首页 > 综合 > 正文

二叉搜索树 实现 算法摘记

2018年01月19日 ⁄ 综合 ⁄ 共 3053字 ⁄ 字号 评论关闭

二叉搜索树,详情见算法导论,直接代码。

/*
二叉查找树,实现了以下操作:插入结点、构造二叉树、删除结点、
查找、查找最大值、查找最小值、查找指定结点的前驱和后继。
所有操作时间复杂度 均为o(h),其中h是树的高度 

改变二叉树 ,用二级指针 
*/  
#include<iostream>
#include<stdio.h>  
#include<stdlib.h>
using namespace std;  

struct node  
{  
    int key;          //关键字  
    struct node *left;   //左孩子指针  
    struct node *right;  //右孩子指针  
    struct node *p; //指向父节点指针  
};  
  
//插入结点  
//插入的话,可能要改变根结点的地址,所以传的是二级指针
void insert(node** root,int key)  
{  
    node *p=(node*)malloc(sizeof(node)); 
	 
    p->key=key;  
    p->left=p->right=p->p=NULL; 
	
    if(*root==NULL)//空树,直接作为根结点 
	{  
        *root=p;  
        return;  
    }  
    //插入左孩子  
    if((*root)->left==NULL && key<(*root)->key)
	{  
        p->p=(*root);  
        (*root)->left=p;  
        return;  
    }  
    //插入右孩子  
    if((*root)->right==NULL && key>(*root)->key)
	{  
        p->p=(*root);  
        (*root)->right=p;  
        return;  
    }  
    
    if(key< (*root)->key) //插入到左子树 
    	insert(&(*root)->left,key);  
    else if(key> (*root)->key) //插入到右子树 
    	insert(&(*root)->right,key); 
    else  
        return;  
}  
  
//查找元素,找到返回关键字的结点指针,没找到返回NULL  
node* search(node* root,int key)  
{  
    if(root==NULL||key==root->key)  
        return root;  
        
    if(key >root->key) //查找右子树  
        return search(root->right,key);  
    else if(key < root->key) //查找左子树  
        return search(root->left,key);    
}  
  
//查找最小关键字,空树时返回NULL,否则一直向左子树查找  
node* searchMin(node* root)  
{  
    while(root->left!=NULL)
		root=root->left;
	return root; 
}  
 
//查找最大关键字,空树时返回NULL,否则一直向右子树查找  
node* searchMax(node* root)  
{  
    while(root->right!=NULL)
		root=root->right;
	return root; 
}  
  
//查找某个结点的前驱  
node* searchPredecessor(node *p)  
{  
    //空树  
    if(p==NULL)  
        return p;
		  
    //有左子树、左子树中最大的那个  
    if(p->left!=NULL)  
        return searchMax(p->left);  
    
	//无左子树,查找某个结点的右子树遍历完了  
    else
	{  
        if(p->p == NULL)  
            return NULL; 
			 
        //向上寻找前驱  
        while(p)
		{  
            if(p->p->right==p)//当p是右子树时,根就是前驱  
                break;  
            p=p->p;  
        }  
        return p->p;  
    }  
}  
  
//查找某个结点的后继  
node* searchSuccessor(node* p)  
{  
    if(p->right!=NULL)//有右子树、右子树中最小的那个 
		 return searchMin(p->right); 
        
    //无右子树,查找某个结点的左子树遍历完了  
    else
	{  
        if(p->p==NULL)  
            return NULL; 
			 
        //向上寻找后继  
        while(p)
		{  
            if(p->p->left==p)//当p是左子树时,根就是后继 
                break;  
            p=p->p;  
        }  
        return p->p;  
    }  
}  
  
//这里跟算法导论有点区别,未考虑删根节点 
void transplant(node** u,node** v)
{		
	if(*u==(*u)->p->left)
		(*u)->p->left=*v;
	else
		(*u)->p->right=*v;
	if(v!=NULL)
		(*v)->p=(*u)->p;
}

//如果把根结点删掉,那么要改变根结点的地址,所以传二级指针 
int deleteNode(node** root,int key)  
{  
     
    node* p=search(*root,key); //查找到要删除的结点 
    node *y=NULL;
    
	if(p->left==NULL)
		{
		transplant(&p,&(p->right));	 
		}
		
	else if(p->right==NULL)
		transplant(&p,&(p->left));
	else//左右不为空 
	{
		y=searchMin(p->right);
		
		if(y->p!=p)//是右子树,y右子树替换y,y替换p 
		{
			transplant(&y,&(y->right));
			y->right=p->right;
			y->right->p=y;
		} 
		transplant(&p,&y);//y是右孩子 
		y->left=p->left;
		y->left->p=y;
	} 
}

//创建二叉查找树  
void create(node** root,int *keyArray,int length)  
{  
    int i;  
    //逐个结点插入二叉树中  
    for(i=0;i<length;i++)  
        insert(root,keyArray[i]);  
}  
  
int main(void)  
{  
    int i;  
    node* root=NULL;  
    int a[11]={15,6,18,3,7,17,20,2,4,13,9};
	/*
			    15
		    6       18
		 3    7   17  20
		2 4    13
			  9	
	*/  
    create(&root,a,11);
	 
	printf("%d\n",searchPredecessor(root)->key); //15的前驱13  
    printf("%d\n",searchSuccessor(root)->key);//15后继17 
    printf("%d\n",searchMin(root)->key);//2  
    printf("%d\n",searchMax(root)->key);//20  
    printf("%d\n",search(root,13)->key);//13
	printf("%d\n",search(root,13)->left->key);//查找13的左子树9 
	
    deleteNode(&root,6);
    printf("删去6之后:\n");
    /*
			    15
		    7      18
		 3   13   17  20
	   2 4  9
	*/  
	root=root->left;//节点7 
    printf("%d\n",searchPredecessor(root)->key); //7的前驱4 
    printf("%d\n",searchSuccessor(root)->key);//7后继9  
    printf("%d\n",searchMin(root)->key);  //2  
    printf("%d\n",searchMax(root)->key);  //13
    printf("%d\n",search(root,3)->key);
    printf("%d\n",search(root,3)->left->key); //查找3的左子树2  
    return 0;  
}  

抱歉!评论已关闭.