基础算之五排序: 二叉排序树
来源:互联网 发布:阿里云 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
- 基础算之五排序: 二叉排序树
- C++基础笔记之五:快速排序
- 基础算法系列(五)排序算法之冒泡排序
- 数据结构和算法系列12 五大查找之二叉排序树
- 排序之五:快速排序
- 排序之五----堆排序
- Linux基础之五
- 排序算法:二叉排序树
- 【算法基础】二叉排序树
- poj1577 二叉排序树基础练习题
- BST 基础二叉排序树
- 内部排序之五:基数排序
- 算法五之快速排序
- 算法五之快速排序
- 基础排序之归并排序
- 基础排序之快速排序
- 排序算法(五)之计数排序
- 排序算法之五 归并排序
- 类似微博的文件上传按钮file的美化
- 完成量实现线程同步
- 新浪微博错误代码大全
- TreeList + <select />+Ajax实现按部门选择员工
- 以前同事做的一款游戏还不错
- 基础算之五排序: 二叉排序树
- C#事件(event)解析
- DX纹理映射
- linux c/c++ GDB教程详解
- 纠正网上资料的错误,loadView,viewDidLoad,viewDidUnload
- 软键盘弹出后重新布局(把布局向上顶)
- C++内存分配
- eclipse配置jrebel后,无法自动部署的问题
- Android单元测试Unable to find instrumentation target package的问题