二叉查找树模板

/*************************************************************************
root 根节点的 父亲节点 设为NULL

*************************************************************************/

 

//二叉查找树结点描述

1 typedef int KeyType;
2 typedef struct Node
3 {
4     KeyType key;          //关键字
5     struct Node * left;   //左孩子指针
6     struct Node * right;  //右孩子指针
7     struct Node * parent; //指向父节点指针
8 } Node,*PNode;

//往二叉查找树中插入结点
//插入的话,可能要改变根结点的地址,所以传的是二级指针

 1 void inseart(PNode * root,KeyType key)
 2 {
 3     //初始化插入结点
 4     PNode p=(PNode)malloc(sizeof(Node));
 5     p->key=key;
 6     p->left=p->right=p->parent=NULL;
 7     //空树时,直接作为根结点
 8     if((*root)==NULL)
 9     {
10         *root=p;
11         return;
12     }
13     //插入到当前结点(*root)的左孩子
14     if((*root)->left == NULL && (*root)->key > key)
15     {
16         p->parent=(*root);
17         (*root)->left=p;
18         return;
19     }
20     //插入到当前结点(*root)的右孩子
21     if((*root)->right == NULL && (*root)->key < key)
22     {
23         p->parent=(*root);
24         (*root)->right=p;
25         return;
26     }
27     if((*root)->key > key)
28         inseart(&(*root)->left,key);
29     else if((*root)->key < key)
30         inseart(&(*root)->right,key);
31     else
32         return;
33 }

 

//查找元素,找到返回关键字的结点指针,没找到返回NULL

 1 PNode search(PNode root,KeyType key)
 2 {
 3     if(root == NULL)
 4         return NULL;
 5     if(key > root->key) //查找右子树
 6         return search(root->right,key);
 7     else if(key < root->key) //查找左子树
 8         return search(root->left,key);
 9     else
10         return root;
11 }

 

//查找最小关键字,空树时返回NULL

 

1 PNode searchMin(PNode root)
2 {
3     if(root == NULL)
4         return NULL;
5     if(root->left == NULL)
6         return root;
7     else  //一直往左孩子找,直到没有左孩子的结点
8         return searchMin(root->left);
9 }

 


//查找最大关键字,空树时返回NULL

1 PNode searchMax(PNode root)
2 {
3     if(root == NULL)
4         return NULL;
5     if(root->right == NULL)
6         return root;
7     else  //一直往右孩子找,直到没有右孩子的结点
8         return searchMax(root->right);
9 }

 

//查找某个结点的前驱 max( <x )

 1 PNode searchPredecessor(PNode p)
 2 {
 3     //空树
 4     if(p==NULL)
 5         return p;
 6     //有左子树、左子树中最大的那个
 7     if(p->left)
 8         return searchMax(p->left);
 9     else//无左子树的情况。
10     {//右子树的节点值都大于它,忽略,只能从父亲节点找。
11         if(p->parent == NULL)
12             return NULL;
13         //向上寻找前驱
14         while(p)
15         {
16             if(p->parent->right == p)
17                 break;
18             p=p->parent;
19         }
20         return p->parent;
21     }
22 }

/****查找某个结点的后继 : min{   >x } ****/

 1 PNode searchSuccessor(PNode p)
 2 {
 3     //空树
 4     if(p==NULL)
 5         return p;
 6     //有右子树、右子树中最小的那个
 7     if(p->right)
 8         return searchMin(p->right);
 9     else//此时无右子树,左子树都比它小忽略。只能从父亲节点找。
10     {
11         if(p->parent == NULL)
12             return NULL;
13         //向上寻找后继
14         while(p)
15         {
16             if(p->parent->left == p)
17                 break;
18             p=p->parent;
19         }
20         return p->parent;
21     }
22 }

 

/**根据关键字删除某个结点,删除成功返回1,否则返回0
如果把根结点删掉,那么要改变根结点的地址,所以传二级指针**/

 

{
    PNode q;
    //查找到要删除的结点
    PNode p=search(*root,key);
    KeyType temp;    //暂存后继结点的值
    //没查到此关键字
    if(!p)
        return 0;
    //1.被删结点是叶子结点,直接删除
    if(p->left == NULL && p->right == NULL)
    {
        //只有一个元素,删完之后变成一颗空树
        if(p->parent == NULL)
        {
            free(p);
            (*root)=NULL;
        }
        else
        {
            //删除的结点是父节点的左孩子
            if(p->parent->left == p)
                p->parent->left=NULL;
            else  //删除的结点是父节点的右孩子
                p->parent->right=NULL;
            free(p);
        }
    }

    /** 2 .被删结点只有左子树 **/
    else if(p->left && !(p->right))
    {
        p->left->parent=p->parent;
        //改变指针指向。
        if(p->parent == NULL)//如果删除的该点恰好是根节点。
            *root=p->left;//此时左节点成为根节点。

        //删除的结点是父节点的左孩子
        else if(p->parent->left == p)
            p->parent->left=p->left;
        else //删除的结点是父节点的右孩子
            p->parent->right=p->left;
        free(p);
    }
    //3.被删结点只有右孩子
    else if(p->right && !(p->left))
    {
        p->right->parent=p->parent;
        //改变指针指向
        if(p->parent == NULL)
            *root=p->right;
        //删除的结点是父节点的左孩子
        else if(p->parent->left == p)
            p->parent->left=p->right;
        else //删除的结点是父节点的右孩子
            p->parent->right=p->right;
        free(p);
    }
    /**4.被删除的结点既有左孩子,又有右孩子
    //该结点的后继结点肯定无左子树(参考上面查找后继结点函数)
    //删掉后继结点,后继结点的值代替该结点 **/
    else
    {
        //找到要删除结点的后继
        q=searchSuccessor(p);
        temp=q->key;
        //删除后继结点
        deleteNode(root,q->key);
        p->key=temp;
    }
    return 1;
}

 

//创建一棵二叉查找树

1 void create(PNode* root,KeyType *keyArray,int length)
2 {
3     int i;
4     //逐个结点插入二叉树中
5     for(i=0; i<length; i++)
6         inseart(root,keyArray[i]);
7 }

 

main 函数

 1 int main(void)
 2 {
 3     int i;
 4     PNode root=NULL;
 5     KeyType nodeArray[11]= {15,6,18,3,7,17,20,2,4,13,9};
 6     create(&root,nodeArray,11);
 7     for(i=0; i<2; i++)
 8         deleteNode(&root,nodeArray[i]);
 9     printf("%d\n",searchPredecessor(root)->key);
10     printf("%d\n",searchSuccessor(root)->key);
11     printf("%d\n",searchMin(root)->key);
12     printf("%d\n",searchMax(root)->key);
13     printf("%d\n",search(root,13)->key);
14     return 0;
15 }

 

posted @ 2014-08-02 17:38  芷水  阅读(203)  评论(0编辑  收藏  举报