6.3.1二叉排序树

#include "stdafx.h"
#include 
<iostream.h>
#include 
<malloc.h>

typedef 
struct btnode * bitreptr;

struct btnode
{
    
int data;                    //数据
    bitreptr lchild;            //左节点指针
    bitreptr rchild;            //右节点指针
}
;

//建立一个新结点
bitreptr CreateNewNode(int data)
{
    bitreptr node
=(bitreptr)malloc(sizeof(btnode));
    node
->data=data;
    node
->lchild=NULL;
    node
->rchild=NULL;
    
return node;
}


//中根遍历
void inorder(const bitreptr root)
{
    bitreptr node
=root;
    
if (node!=NULL)
    
{
        inorder(node
->lchild);
        cout
<<node->data<<endl;
        inorder(node
->rchild);
    }

}

//建立P135的图6-2的图
bitreptr CreateStaticBinTree()
{
    bitreptr node37
=CreateNewNode(37);

    bitreptr node21
=CreateNewNode(21);
    node37
->lchild=node21;
    bitreptr node6
=CreateNewNode(6);
    node21
->lchild=node6;
    bitreptr node32
=CreateNewNode(32);
    node21
->rchild=node32;
    bitreptr node23
=CreateNewNode(23);
    node32
->lchild=node23;
    bitreptr node33
=CreateNewNode(33);
    node32
->rchild=node33;

    bitreptr node51
=CreateNewNode(51);
    node37
->rchild=node51;
    bitreptr node86
=CreateNewNode(86);
    node51
->rchild=node86;
    bitreptr node60
=CreateNewNode(60);
    node86
->lchild=node60;
    bitreptr node65
=CreateNewNode(65);
    node60
->rchild=node65;

    
return node37;
}


//在二叉排序树上进行查找
bitreptr search_bst(bitreptr node,int key)
{
    
if (node==NULL)
    
{
        
return NULL;
    }

    
else if (key==node->data)
    
{
        cout
<<"匹配"<<endl;
        
return node;
    }

    
else if (key>node->data)
    
{
        bitreptr tmp
=search_bst(node->rchild,key);
        cout
<<"返回"<<endl;
        
return tmp;
    }

    
else if (key<node->data)
    
{
        bitreptr tmp
=search_bst(node->lchild,key);
        cout
<<"返回"<<endl;
        
return tmp;
    }

}


//书上的二叉排序树的插入算法,做了一点修改,书上的算法只能确保要么存在,要么插入,我加了一个参数,记录一下找到的结点

//此算法精妙之处在于递归算法的实现,像node->rchild=insert_bst(node->rchild,key);return node;这样的,如果匹配成功则
//将此结点返回,那么返回到上层的递归调用时只是做了一些赋值;如果匹配不成功,则创建了一个新结点,然后返回后链接到上次
//调用的结点的相应指针域上.此算法唯一浪费的就是赋值操作的浪费,因为每递归调用一次在返回时都将做一次赋操作,另外,在
//二叉排序树的整体算法中,包括查找,插入,删除其实都可以遵寻同一个方式,就此书上的两个例子而言,查找和插入的算法还是很
//相似的,但是如果在此基础上做删除操作,就不能按这样的递归方式,因为在递归时候没有记录相关的信息,相比之下,严蔚敏版的
//数据结构的算法记录了相关的信息,使其查找,插入,删除操作可以按同一思路进行,容易理解消化.
bitreptr insert_bst(bitreptr node,int key,bitreptr & findnode)
{
    
if (node==NULL)
    
{
        findnode
=CreateNewNode(key);
        
return findnode;
    }

    
else if (key==node->data)
    
{
        findnode
=node;
        
return node;
    }

    
else if (key>node->data)
    
{
        node
->rchild=insert_bst(node->rchild,key,findnode);
        
return node;
    }

    
else if (key<node->data)
    
{
        node
->rchild=insert_bst(node->lchild,key,findnode);
        
return node;
    }

}

//严蔚敏版对二叉排序树的实现
//node:初始结点   key:查找的关键字值   parent:node的双亲    findnode:找到的结点或新增的结点
void Yan_insert_bst(bitreptr node,int key,bitreptr parent,bitreptr & findnode)
{
    
if (node==NULL)
    
{
        findnode
=CreateNewNode(key);
        
if (parent!=NULL)
        
{
            
if (parent->data<key)
            
{
                parent
->rchild=findnode;
            }

            
else
            
{
                parent
->lchild=findnode;
            }

        }

    }

    
else if (key==node->data)
    
{
        findnode
=node;
        
return;
    }

    
else if (key>node->data)
    
{
        Yan_insert_bst(node
->rchild,key,node,findnode);
        
return;
    }

    
else if (key<node->data)
    
{
        Yan_insert_bst(node
->lchild,key,node,findnode);
        
return;
    }

}

//删除
void Delete_bst(bitreptr node,int key,bitreptr parent,bitreptr & findnode)
{
    
if (node==NULL)
    
{
        findnode
=NULL;
        
return;
    }

    
else if (key==node->data)
    
{
        
//分4种情况处理
        
//1.页子结点直接删除
        if (node->lchild==NULL && node->rchild==NULL)
        
{
            
if (parent!=NULL)
            
{
                
if (parent->data>node->data)
                
{
                    parent
->lchild=NULL;
                }

                
else
                
{
                    parent
->rchild=NULL;
                }

            }

            free(node);
            node
=NULL;
        }

        
//2.右子树为空,则直接连接左子树
        else if (node->rchild==NULL)
        
{
            bitreptr tmp
=node;
            node
=node->lchild;
            free(tmp);
            tmp
=NULL;
        }

        
//3.左子树为空,则直接连接右子树
        else if (node->lchild==NULL)
        
{
            bitreptr tmp
=node;
            node
=node->rchild;
            free(tmp);
            tmp
=NULL;
        }

        
//4.待删结点的有左右子树的删除算法,书上讲的不是很清楚,我在这里说一下,其思路是,其右子树的相对位置不会改变,在待删结点的左
        
//子树上找最大的结点,替换掉这个待删结点.那么,因为其左子树也是二叉排序树,所以这个左子树上的最大结点也就是其待删结点的左子
        
//树上的首节点的右子树上的最后一个其rchild为NULL的结点.然后将这个结点的左子树挂到它的父结点的右子树结点上,将这个结点的左/右
        
//指向待删结点的左/右结点上.修改其它待删结点的父结点,指向这个新的结点.
        
//其中,有一个特例,就是这个待删结点的左子树的首节点,其右子树为空,那么此时只需要将这个左子树挂到这个待删结点上就可以了.
        else
        
{
            bitreptr leftnode
=node->lchild;
            
if (leftnode->rchild==NULL)
            
{
                
//此待删除结点的左子树首结点不存在右子树的情况,则直接将此左子树挂接到待删处
                bitreptr tmp=node;
                node
=node->lchild;
                free(tmp);
                tmp
=NULL;
            }

            
else
            
{
                bitreptr rightnode
=leftnode->rchild;
                bitreptr rightparent
=leftnode;
                
//找到右子树最大的
                while(rightnode->rchild!=NULL)
                
{
                    rightparent
=rightnode;
                    rightnode
=rightnode->rchild;
                }

                
//将右子树中最大结点的左子树挂接到其父结点的右子树上
                rightparent->rchild=rightnode->lchild;
                
//修改此结点的左子树指向待删结点的左子树,右结点指向待删结点的右子树
                rightnode->lchild=node->lchild;
                rightnode
->rchild=node->rchild;
                
                bitreptr tmp
=node;
                node
=rightnode;
                free(tmp);
            }

        }

        
if (parent->data>node->data)
        
{
            parent
->lchild=node;
        }

        
else
        
{
            parent
->rchild=node;
        }

        
return;
    }

    
else if (key>node->data)
    
{
        Delete_bst(node
->rchild,key,node,findnode);
        
return;
    }

    
else if (key<node->data)
    
{
        Delete_bst(node
->lchild,key,node,findnode);
        
return;
    }

}

int main(int argc, char* argv[])
{
    
//1.测试静态二叉排序树上的查找算法
    bitreptr tree=CreateStaticBinTree();
    cout
<<"建立二叉树的结点为:"<<endl;
    inorder(tree);
    bitreptr findnode
=search_bst(tree,65);
    
if (findnode!=NULL)
    
{
        cout
<<"findnode="<<findnode->data<<endl;
    }

    
//2.测试书上的二叉排序树的插入算法
    findnode=NULL;
    insert_bst(tree,
86,findnode);
    cout
<<"测试使用书上算法插入一个现存的结点:"<<findnode->data<<endl;
    cout
<<"当前结点为:"<<endl;
    inorder(tree);
    findnode
=NULL;
    insert_bst(tree,
88,findnode);
    cout
<<"测试使用书上算法插入一个不存在的结点:"<<findnode->data<<endl;
    cout
<<"当前结点为:"<<endl;
    inorder(tree);
    
//3.测试严蔚敏版二叉排序树的插入算法
    findnode=NULL;
    Yan_insert_bst(tree,
32,NULL,findnode);
    cout
<<"测试严蔚敏版的算法插入一个现存的结点:"<<findnode->data<<endl;
    cout
<<"当前结点为:"<<endl;
    inorder(tree);
    findnode
=NULL;
    Yan_insert_bst(tree,
34,NULL,findnode);
    cout
<<"测试严蔚敏版的算法插入一个不现存的结点:"<<findnode->data<<endl;
    cout
<<"当前结点为:"<<endl;
    inorder(tree);
    
//4.测试删除算法
    cout<<"测试删除结点86"<<endl;
    findnode
=NULL;
    Delete_bst(tree,
86,NULL,findnode);
    cout
<<"当前结点为:"<<endl;
    inorder(tree);
    
return 0;
}

    
posted @ 2007-08-04 11:01  吴东雷  阅读(701)  评论(0编辑  收藏  举报