- 浏览: 131804 次
- 性别:
- 来自: 成都
最新评论
-
yi_chao_jiang:
你好,多谢分享,问个问题,在上传数据的时候判断文件是否有上传记 ...
断点续传和下载原理分析 -
a41606709:
为什么我的tabhost显示不出来? 怎么设置在全部页面中让他 ...
TabActivity中的Tab标签详细设置 -
Zero颴:
大神篇,思路,配图都很清晰,perfect!
Android事件模型之interceptTouchEvnet ,onTouchEvent关系正解 -
QAZ503602501:
牛死人了!!!
B-树 -
mengsina:
很牛的文档。数学功底好啊
Android Matrix理论与应用详解
1.基本概念
二叉排序树,树的定义就不赘述了,主要就是想说明一下在设计类的过程中需要注意的问题。
a.问题引入?
设计插入,删除等操作的过程中,我们的二叉排序树根节点的指针有可能改变,如删除根结点的指针操作,那么root的指针指向已经不是原来的位置,而是新的位置,怎么样才能返回最新的位置呢?
b.问题解决
在设计类中的函数就可以轻易的解决这个问题,这个在函数设计之初就必须详细的考虑这个问题,这里有两种办法
首先,通过返回值,返回最新的root结点;
Node<T>* deleteBST(T x); Node<T>* insertBST(T x);
这样在使用的过程中就需要这样使用:
BiSortTree<int> bst; Node<int>* root = bst.getRoot(); ... bst.deleteBST(20);//这里假定20是根结点 bst.printBST(root); //这里打印出来的肯定不是现在最新的二叉树,因为原来的root已经改变了 正确的使用方法是: BiSortTree<int> bst; Node<int>* root = bst.getRoot(); ... root = bst.deleteBST(20);//这里假定20是根结点 bst.printBST(root);
其次,可以通过引用,设置函数的参数;
void deleteBST(Node<T>* &root, T x); void insertBST(Node<T>* &root, T x);
这里利用了指针引用,这样会在删除,插入操作自动更新root
它的使用很简单,直接使用就是了
c.设计的缺陷
根据面向对象的原则,在上述设计中void deleteBST(Node<T>* &root, T x);它的设计是不合理的,因为root已经暴露在函数外面,为了实现其隐蔽的原则,就必须将root封装起来,不让使用者接触,那么怎样设计了?
class BiSortTree{
public:
...
void insertBST(T x){ insertBST(root, x);}
void deleteBST(T x){ deleteBST(root, x);}
private:
...
void insertBST(Node<T>* &root, T x);
void deleteBST(Node<T>* &root, T x);
Node<T>* &root; //完成隐藏root
};
这样就实现了,隐蔽的原则,实现了面向对象的方法,使得使用者不用关心具体的实现,只是直接调用就ok了
2.代码实现
代码中就没有完全按照上述原则实现,所以需要自己改装
a.bisorttree.h
//二叉排序树 #ifndef BISORTTREE_H #define BISORTTREE_H //数据域,里面存放结点数据 template<class T> struct Data{ T data; //结点数据 int count; //次数 //int bf; //平衡因子(对于AVL平衡二叉树是需要的) }; template<class T> struct Node{ Data<T> data; Node<T> *rchild, *lchild; }; /** *注意插入,删除都可能改变根结点,故而可能改变root指向的指针,就要注意设计函数的参数或者返回值 *例如:void delete(T x);如果删除x是根结点,则删除后访问,就不能在找到root,访问内存出错 *故而要想删除之后访问不出错,应该设计成 *1.Node<T>* delete(T x);(利用返回值)返回最新根结点,使用方法Node<T>* root = delete(12); printBST(root); 注意不能这么用delete(12); printBST(root);root必须是返回最新的 *2.void delete(Node<T>* &root, T x);(利用函数参数,这样不是很好,破坏封装性,可以设计成private,在加public函数void delete(T x)) * 它的使用简单,直接就是delete(root, 12); printBST(root); */ template<class T> struct BiSortTree{ public: BiSortTree(); BiSortTree(T a[], int n); ~BiSortTree(); Node<T>* getRoot(); //--------删除------- void deleteBST(Node<T>* &root, T x); //设计方法1 //返回根结点 Node<T>* deleteBST(T x); //设计方法2:当删除根结点之后,root改变,必须重新获取,如果写成void deleteBST(T x)则访问内存出错,root已经删除 //--------插入------- //void insertBST(Node<T>* root, T x); //递归插入,不使用引用是不行的 void insertBST(Node<T>* &root, T x); //root写成引用,这样root改变就会自动实现,上面就不行(下面也是一种写法) //返回根结点(在首次插入之后,其实root就不会改变) Node<T>* insertBST(T x); //最好不写成void insertBST(T x),这样每次必须手动调用getRoot,才能获取最新,返回的结点都是最新的root结点 //--------搜索------- //返回搜索结点 Node<T>* searchBST(T x); //返回搜索结点 Node<T>* searchBST(Node<T>* root, T x); //递归搜索 void printBST(Node<T>* root); private: Node<T>* root; Node<T>* pre;//用于递归插入时,记录前序结点 void releaseBST(Node<T>* &root); void create(Node<T>* &root); void deleteNode(Node<T>* &root, Node<T>* r, Node<T>* pre);//删除结点p }; #endif
b.bisorttree.cpp
#include <iostream> #include "bisorttree.h" using namespace std; template<class T> BiSortTree<T>::BiSortTree(){ pre = NULL; root = NULL; create(root); } template<class T> BiSortTree<T>::BiSortTree(T* a, int n){ if(n <= 0) return; pre = NULL; root = NULL; for(int i=0; i<n; i++){ insertBST(root, a[i]); //insertBST(a[i]); } } template<class T> BiSortTree<T>::~BiSortTree(){ releaseBST(root); } template<class T> Node<T>* BiSortTree<T>::getRoot(){ return root; } //返回根结点 template<class T> Node<T>* BiSortTree<T>::insertBST(T x){ Node<T>* r = root; if(r == NULL){ Node<T>* t = new Node<T>; (t->data).data = x; (t->data).count = 1; t->lchild = t->rchild = NULL; root = t;//必须设置新的root结点,因为t和root在内存指向位置不同 }else{ Node<T>* p = r; //查找待插入结点位置 while(r){ if((r->data).data == x){ (r->data).count++; return root; } p = r; r = ((r->data).data > x)?r->lchild:r->rchild; } Node<T>* t = new Node<T>; (t->data).data = x; (t->data).count = 1; t->lchild = t->rchild = NULL; if((p->data).data > x){//插入左 p->lchild = t; }else{ p->rchild = t; } } return root; } //用于检测不用root引用是否会修改root,结果不使用root是不能改变root,必须是指针的引用 template<class T> void BiSortTree<T>::insertBST(Node<T>* &root, T x){ if(root){ pre = root; if((root->data).data > x) insertBST(root->lchild, x); else if((root->data).data < x) insertBST(root->rchild, x); else (root->data).count++; }else{ Node<T>* r = new Node<T>; (r->data).data = x; (r->data).count = 1; r->lchild = r->rchild = NULL; if(pre){ if((pre->data).data > x) pre->lchild = r; else pre->rchild = r; }else{ root = r; } } } template<class T> void BiSortTree<T>::deleteBST(Node<T>* &root, T x){ if(!root) return; Node<T>* pre = NULL, *r = root; //查找待插入结点位置(p是r的前序结点) while(r){ if((r->data).data == x){ if((r->data).count > 1){ (r->data).count--; return; }else{ break; } } pre = r; r = ((r->data).data > x)?r->lchild:r->rchild; } //没找到 if(!r) return; //如果pre == NULL说明是root结点 deleteNode(root, r, pre); } template<class T> Node<T>* BiSortTree<T>::deleteBST(T x){ if(!root) return root; Node<T>* pre = NULL, *r = root; //查找待删除结点位置(pre是r的前序结点) while(r){ if((r->data).data == x){ if((r->data).count > 1){ (r->data).count--; return root; }else{ break; } } pre = r; r = ((r->data).data > x)?r->lchild:r->rchild; } //没找到 if(!r) return root; //如果pre == NULL说明是root结点 deleteNode(root, r, pre); return root; } template<class T> Node<T>* BiSortTree<T>::searchBST(T x){ Node<T>* r = root; while(r){ if(r->data.data == x) break; r = ((r->data).data > x)?r->lchild:r->rchild; } //如果没找到,返回空 return r; } template<class T> Node<T>* BiSortTree<T>::searchBST(Node<T>* root, T x){ if(!root) return NULL; else{ if(root->data.data == x) return root; else if(root->data.data > x) return searchBST(root->lchild, x); else return searchBST(root->rchild, x); } } template<class T> void BiSortTree<T>::printBST(Node<T>* root){ if(root){ cout<<root->data.data<<" "; printBST(root->lchild); printBST(root->rchild); } } template<class T> void BiSortTree<T>::releaseBST(Node<T>* &root){ if(root){ releaseBST(root->lchild); releaseBST(root->rchild); delete root; } } template<class T> void BiSortTree<T>::create(Node<T>* &root){ T ch; cout<<"请输入创建一棵二叉排序树的结点数据(输入#结束):"<<endl; while(cin>>ch){ if(ch == '#') break; //insertBST(root, ch); insertBST(ch); } } //pre为空,说明删除的是根结点 template<class T> void BiSortTree<T>::deleteNode(Node<T>* &root, Node<T>* r, Node<T>* pre){ Node<T>* p; if(!r->rchild && !r->lchild){ //如果是叶子结点 if(pre){ if(pre->lchild == r){ pre->lchild = NULL; }else{ pre->rchild = NULL; } }else{ root = NULL; } delete r; }else if(r->rchild && r->lchild){ //如果左右子树都有(还有一种处理办法就是用右子树的最左结点替换待删除结点,然后删除最左结点) p = r; //寻找右子树的最左结点 r = r->rchild; while(r->lchild){ r = r->lchild; } //将删除结点的左结点接到找到的最左结点之后 r->lchild = p->lchild; //删除结点(如果pre是空,说明删除结点是根结点,不用改变前序结点指针) if(pre){ if(pre->lchild == p) pre->lchild = p->rchild; else pre->rchild = p->rchild; }else{ root = p->rchild; } delete p; }else if(r->lchild){ //如果只有左子树 p = r; if(pre){ if(pre->lchild == p) pre->lchild = r->lchild; else pre->rchild = r->lchild; }else{ root = r->lchild; } delete p; }else{ //如果只有右子树 p = r; if(pre){ if(pre->lchild == p) pre->lchild = r->rchild; else pre->rchild = r->rchild; }else{ root = r->rchild; } delete p; } }
c.main.cpp
#include <iostream> #include "bisorttree.cpp" using namespace std; int main(){ cout<<"----------二叉排序树测试----------"<<endl; BiSortTree<int> bst; Node<int>* root = bst.getRoot(); bst.printBST(root); cout<<"\n插入23"<<endl; bst.insertBST(23); //root = bst.insertBST(23); //bst.insertBST(24); root = bst.insertBST(24);//如果初始的root为空,则必须这样使用,因为root已经改变,如果上面那样用,就算插入了还是空的;当然如果已经不是空了,则root就没改变,可以输出,注:只有root改变就必须返回新的root bst.printBST(root); /* int a[] = {60, 40, 65, 30, 45, 70, 68, 20, 43}; BiSortTree<int> bst(a, 9); Node<int>* root = bst.getRoot(); if(root == NULL){ cout<<"---null---"<<endl; } cout<<"----------遍历结果------------"<<endl; bst.printBST(root); cout<<"\n插入23"<<endl; bst.insertBST(23); bst.printBST(root); Node<int> *p; cout<<"\n搜索23"<<endl; p = bst.searchBST(root,23); if(p) cout<<"搜索结果:"<<p->data.data<<",count:"<<p->data.count<<endl; else cout<<"无"<<endl; cout<<"删除叶子23"<<endl; bst.deleteBST(root, 23); bst.printBST(root); //测试构造函数和几种删除,一个root cout<<"\n删除叶子结点20"<<endl; bst.deleteBST(root, 20); bst.printBST(root); cout<<"\n删除根结点60"<<endl; //bst.deleteBST(root, 60); //1.方案1 root = bst.deleteBST(60); //2.方案2, 不获取返回值bst.deleteBST(60);是不正确的使用方法 bst.printBST(root); */ return 0; }
发表评论
-
排序方法总结
2012-08-12 11:34 1178这里面包含了所有常见的排序操作 1.性能等比较分析 2 ... -
常见字符串操作大全
2012-08-12 11:34 14631.常见的字符串操作 如计算长度,求子串等都是考验基本功的, ... -
KMP算法解析
2012-08-12 11:35 2841一.理论基础 1.什么 ... -
二叉堆的实现
2012-08-12 11:35 12121.堆的概念 这里只需要注意两点: a.堆的存储方式:就是 ... -
set和map的简单实现
2012-08-10 11:35 13211.Set的简单实现 set是利用二叉查找树来实现的,而且为 ... -
红黑树的插入总结
2012-08-10 11:25 14091.红黑树 这个在july的博客中有详尽的说明,我就不在赘述 ... -
B-树实现
2012-08-10 11:03 16271.什么是B-树? 这个在我的前一篇博客中已经详细的阐释过: ... -
平衡二叉树
2012-08-10 10:39 28601.问题描述 什么是平衡 ... -
B-树
2012-07-04 22:48 56771.B-树的概念 是一种多 ... -
构造哈夫曼树
2012-07-04 10:40 12331.算法说明 就是建造哈夫曼树树,从而使得构造出的树带权路径 ... -
线索二叉树
2012-07-04 09:20 12761.算法描述 就是简单的线索二叉树的建立,遍历,查找等基本操 ... -
二叉树基本操作大全
2012-07-03 18:22 26081.二叉树的基本操作 这里我有一个疑问: 在使用构造 ... -
多种队列的实现
2012-06-29 10:09 15621.算法描述 a.数据结构与算法(Mark Allen We ... -
栈的各种实现
2012-06-28 16:34 11091.算法描述 a.实现二个栈,在一个数组里面,除非没有任何空 ... -
中缀表达式转换为后缀
2012-06-28 11:10 18371.算法描述 例如a+b*c这是常见的中缀表达式,但是 ... -
后缀表达式的值
2012-06-27 16:33 13361.算法描述 计算后缀表达式的值 2.事例 如:( ... -
Josephus问题
2012-06-21 15:30 10021.算法描述 简单的游戏:有N个人坐成一圈,编号1-N、从编 ... -
关于最长递增子序列的实际应用--动态规划
2012-06-07 11:35 1837参考链接: a.http://www.programfan. ... -
线性查找二维数组
2012-06-05 17:23 10311.算法描述 有序(行有序,列有序,且每行从左至右递增 ... -
整数的随机置换
2012-06-05 15:10 2325算法描述:生成前N个整 ...
相关推荐
二叉排序树,又称二叉查找树或二叉搜索树,是一种特殊的二叉树数据结构,它具有以下特性:对于树中的每个节点,其左子树中的所有节点的值都小于该节点的值,而右子树中的所有节点的值都大于该节点的值。这种性质使得...
在数据结构的学习中,二叉排序树(Binary Search Tree,BST)是一种常见的树形数据结构,它具有查找、插入和删除等操作的高效性。在这个课程设计中,我们将重点探讨如何利用二叉链表作为存储结构来实现二叉排序树,...
二叉排序树(Binary Sort Tree,BST),也称为二叉搜索树,是一种特殊的二叉树数据结构,它的每个节点都包含一个键(key)、一个关联的值、一个指向左子节点的指针和一个指向右子节点的指针。在二叉排序树中,对于...
在数据结构中,二叉排序树(Binary Search Tree,BST)是一种十分重要的数据结构,它不仅能够存储具有排序性质的数据集合,还能够高效地完成插入、查找、删除等操作。二叉排序树插入算法是维护二叉排序树性质的关键...
【二叉排序树与文件操作】 功能要求: (1)从键盘输入一组学生记录建立二叉排序树; (2)二叉排序树存盘; (3)由文件恢复内存的二叉排序树; (4)中序遍历二叉排序树; (5)求二叉排序树深度; (6)求二叉...
二叉排序树(Binary Sort Tree,BST),也称为二叉查找树或二叉搜索树,是一种特殊的二叉树数据结构,它的每个节点都包含一个键(key)、一个关联的值、一个指向左子树的引用和一个指向右子树的引用。在二叉排序树中...
二叉排序树,又称二叉查找树或二叉搜索树,是一种特殊的数据结构,它具有以下特性:对于树中的任意节点,其左子树中的所有节点的值都小于该节点的值,而右子树中所有节点的值都大于该节点的值。这种特性使得在二叉...
【二叉排序树】,全称为Binary Sort Tree,是一种特殊的二叉树,其每个节点的值都大于其左子树中的所有节点值,且小于其右子树中的所有节点值。这种特性使得二叉排序树在查找、插入和删除操作上具有较高的效率。 在...
二叉排序树(Binary Sort Tree,BST),也称为二叉查找树或二叉搜索树,是一种自平衡的二叉树数据结构,它在处理搜索、插入和删除操作时具有较高的效率。二叉排序树的主要特性是:对于任意节点,其左子树中的所有...
二叉排序树(Binary Sort Tree,BST),也称为二叉查找树或有序二叉树,是一种特殊类型的二叉树,其每个节点的左子树只包含比其小的元素,右子树包含比其大的元素,且整个树保持自平衡。在本实验报告中,我们将深入...
二叉排序树(Binary Sort Tree,BST),也称为二叉搜索树或有序二叉树,是一种自平衡的二叉树数据结构。在二叉排序树中,对于任意一个节点,其左子树中的所有节点的值都小于该节点的值,而右子树中的所有节点的值都...
根据给定的信息,我们可以分析出该段代码主要实现了二叉排序树的基本操作,包括创建、插入元素、查找元素以及中序遍历等。下面将详细解释这些知识点。 ### 数据结构:二叉排序树 二叉排序树(Binary Search Tree, ...
二叉排序树(Binary Sort Tree,BST),也称为二叉搜索树,是一种特殊的二叉树数据结构,它具有以下特性: 1. 每个节点包含一个键(key)、一个关联的值、一个指向左子节点的引用和一个指向右子节点的引用。 2. ...
二叉排序树C语言的简单实现,包含如下操作: 1.创建二叉排序树; 2.销毁二叉排序树; 3.清空二叉排序树; 4.插入指点结点至二叉排序树; 5.删除二叉排序树指点结点; 5.获取二叉排序树指定结点; 6.获取二叉排序树根...
二叉排序树(Binary Sort Tree,BST),也称为二叉搜索树,是一种特殊的二叉树数据结构,它的每个节点都包含一个键值,且满足以下性质:对于任意节点,其左子树中所有节点的键值均小于该节点的键值;其右子树中所有...
二叉排序树(Binary Search Tree,BST),又称为二叉查找树或有序二叉树,是一种自平衡的二叉树数据结构。它在计算机科学中扮演着重要角色,特别是在数据检索、排序和组织方面。VC++是Microsoft开发的一款集成开发...