基础算之五排序: 二叉排序树

来源:互联网 发布:阿里云 rds 读写分离 编辑:程序博客网 时间:2024/05/21 07:09

 

二叉排序数或者是一棵空树,或者是一棵具有以下性质的二叉树:

1)若它有左子树,则左子树上所有结点的数据均小于根结点的数据。

2)若它有右子树,则右子树上所有结点的数据均大于根结点的数据。

3)左、右子树本身又各是一棵二叉排序树。

 

 

 

实际操作:

    我们都知道,对一个东西进行操作,无非就是增删查改,接下来我们就聊聊其中的基本操作。

    <1> 插入:相信大家对“排序树”的概念都清楚了吧,那么插入的原理就很简单了。

                    比如说我们插入一个20到这棵树中。

                                 首先:20跟50比,发现20是老小,不得已,得要归结到50的左子树中去比较。

                                 然后:20跟30比,发现20还是老小。

                              再然后:20跟10比,发现自己是老大,随即插入到10的右子树中。

                                 最后: 效果呈现图如下:

 

 

  <2>查找:相信懂得了插入,查找就跟容易理解了。

                    就拿上面一幅图来说,比如我想找到节点10.

                                     首先:10跟50比,发现10是老小,则在50的左子树中找。

                                     然后:10跟30比,发现还是老小,则在30的左子树中找。

                                  再然后:  10跟10比,发现一样,然后就返回找到的信号。

                

 <3>删除:删除节点在树中还是比较麻烦的,主要有三种情况。

                   《1》 删除的是“叶节点20“,这种情况还是比较简单的,删除20不会破坏树的结构。如图:

 

《2》删除”单孩子节点90“,这个情况相比第一种要麻烦一点点,需要把他的孩子顶上去。

 

 

《3》删除“左右孩子都有的节点50”,这个让我在代码编写上纠结了好长时间,问题很直白,

                           我把50删掉了,谁顶上去了问题,是左孩子呢?还是右孩子呢?还是另有蹊跷?这里我就

                           坦白吧,不知道大家可否知道“二叉树”的中序遍历,不过这个我会在后面讲的,现在可以当

                          公式记住吧,就是找到右节点的左子树最左孩子。

                          比如:首先 找到50的右孩子70。

                                  然后  找到70的最左孩子,发现没有,则返回自己。

                                  最后  原始图和最终图如下。

 

 

程序:

 

1 )结构定义

int a[]={40,28,6,72,100,3,54,1,80,91,38};int insertarray[]={99,47,16,28};//结构定义typedef struct BiSortTree{int data;struct BiSortTree *left;struct BiSortTree *right;}BSTreeNode;


 

 

2)生成二叉排序树

//根据用户的输入的整数生成一个二叉排序树void insert(BSTreeNode *&bstree,BSTreeNode*sNode){if (bstree==NULL) bstree=sNode;else if (sNode->data == bstree->data)return;else if (sNode->data < bstree->data)insert(bstree->left,sNode);else if (sNode->data > bstree->data)insert(bstree->right,sNode);}void create(BSTreeNode *&b){int x;BSTreeNode *s;b=NULL;do {scanf("%d",&x);s=(BSTreeNode *)malloc(sizeof(BSTreeNode));s->data=x;s->left=NULL;s->right=NULL;if (x!=-1) insert(b,s);} while(x!=-1);}//根据数组元素值生成一个二叉排序数void create_fromarray(BSTreeNode *&b,int r[],int n){int i;BSTreeNode *s;b=NULL;for(i=0;i<n;i++){s=(BSTreeNode *)malloc(sizeof(BSTreeNode));s->data=r[i];s->left=NULL;s->right=NULL;insert(b,s);}}


 

3)查找

//二叉查找数静态查找函数,递归实现BSTreeNode *search(BSTreeNode *b,int x){if(b==NULL) return (NULL);else{if(b->data==x) return(b);if(x<b->data) return (search(b->left,x));else return(search(b->right,x));}}//"二叉查找数静态查找函数,非递归实现"BSTreeNode *static_search(BSTreeNode *b,int key){if(b==NULL) return NULL;while (b!=NULL){if(b->data == key){printf("\n数据域=%d\t地址=0x%08x\t\n",b->data,b);return b;}if(b->data > key)b=b->left;elseb=b->right;}return NULL;}//二叉查找树动态查找函数,非递归实现void dynamic_search(BSTreeNode *btree,BSTreeNode **parent,BSTreeNode **p,int key){*parent = NULL;*p=btree;while (*p!=NULL){if((*p)->data == key)return;*parent=*p;if((*p)->data>key)*p = (*p)->left;else*p = (*p)->right;}}


4)插入

//二叉查找树插入值为key的节点的函数,非递归.bool insert_key(BSTreeNode *&bstree,int key){BSTreeNode *parent,*q,*newnode;dynamic_search(bstree,&parent,&q,key);if (q!=NULL)return false;  //节点在树中已经存在,插入失败.newnode = (BSTreeNode *)malloc(sizeof(BSTreeNode));newnode->data =key;newnode->left=newnode->right=NULL;if(parent==NULL)bstree=newnode;   //原树为空,新建结点为根结点else{if(parent->data>key)parent->left=newnode;elseparent->right=newnode;}return true;}//二叉查找树插入一批节点函数void insert_array(BSTreeNode *&bstree,int a[],int n){int i;for(i=0;i<n;i++){if(!insert_key(bstree,a[i]))printf("\n插入失败!<键值为%d的节点已经存在>\n",a[i]);}}


 

5)删除

//二叉查找树删除结点函数void delnode(BSTreeNode *&btree,int x){BSTreeNode *p,*q,*r,*t;p=btree;q=NULL;while (p!=NULL && p->data!=x){if (x<p->data){q=p;p=p->left;}else{q=p;p=p->right;}}if(p==NULL) printf("未找到数据域为%d的结点\n",x);else if (p->left == NULL){if(q==NULL) t=p->right;else if(q->left ==p) q->left=p->right;else q->right = p->right;}else{r=p->left;while(r->right!=NULL)r=r->right;r->right=p->right;if(q==NULL) t=p->left;else if(q->left == p) q->left=p->left;else q->right=p->left;}}


 

6)输出

//假设二叉排序树各元素值均不相同,按递增输出各元素值void incr_order(BSTreeNode *bstree){if(bstree!=NULL){incr_order(bstree->left);printf("%d ",bstree->data);incr_order(bstree->right);}}//假设二叉排序树各元素值均不相同,按递减输出各元素值void dest_order(BSTreeNode *bstree){if(bstree!=NULL){dest_order(bstree->right);printf("%d ",bstree->data);dest_order(bstree->left);}}


示例:

 

int main(){BSTreeNode *b;BSTreeNode *search_num;//create(bstree);create_fromarray(b,a,11);search_num = search(b,54);search_num = static_search(b,54);BSTreeNode *searchnum,*searchnum_parent;dynamic_search(b,&searchnum_parent,&searchnum,54);delnode(b,72);//bstree =NULL;insert_key(b,8);insert_array(b,insertarray,4);incr_order(b);printf("\n");dest_order(b);return 1;}


 

 

参考资料:

http://www.cnblogs.com/xiaopohou/archive/2012/01/18/2325601.html

 

 

原创粉丝点击