介绍:二叉排序树是以一定的规则排列树中元素,因而可以进行快速的排序和查询的树状数据结构,一般规则是:对于树中任意一个节点,左孩子严格小于根,根严格小于右孩子,有点像大根堆。(只是大根堆中左右孩子关系并不确定,且和根的关系是统一的,而且有上浮和下沉操作使得大根堆总是一棵完全二叉树,其不断弹出堆顶形成有序列的过程叫做堆排序。虽然二叉排序树中也有旋转操作使得树尽量平衡,但是由于数值大小分明的左右孩子,在进行平衡操作时远不如大根堆方便快捷。)对于一棵已经构造完成的排序二叉树,它的中序遍历序列即为升序排列的有序列,这就是二叉排序树的排序方法。
基本操作:二叉排序树的基本操作为查找、插入和删除。查找操作以及插入操作过程同二分查找类似,用待处理节点和当前节点进行数值比较,如果待处理节点的值小于当前节点的值,则进入当前节点的左子树进行操作,否则进入当前节点的右子树进行操作,直到到达叶子节点或者操作完成。删除操作有好几种实现方法,我是用的是“替罪羊节点法”,即从待删除节点的左子树中找到最大的一个节点(即“替罪羊节点”),用它的值覆盖待删除节点的值,然后删除替罪羊节点即可。在具体操作中还有许多需要注意的细节,在代码注释中有详细介绍。
一些想法:在最初的代码实现中,曾使用静态树,因为考虑到在处理大型数据时,重复的new或者malloc操作会使得程序慢的令人发指(并不是说指针慢,只是申请空间的过程耗费时间),所以一开始就开一段长度合适的空间,另外设置一个指针指示当前数组中可以用的节点,然后new操作在这里的实现就可以这样写:tmp->lc = &Tree[++index],如果当前序列空间不够时,再用malloc或new申请另一段空间,有点类似内存池的概念。这样的静态操作经在线评测系统(POJ)测试,在进行最基本的操作来处理100,000左右的数据量时会快上两个甚至更多的数量级。静态树的查找和插入操作都可以正常进行,但是在进行删除操作时,我自己写的回收空间算法(为了节省空间,删除的节点重新归到可用空间中,想法是把待删除节点和当前排序树二叉树用的最后一个节点进行交换,再把上文提到的指针前移一位即可,代码实现可以写成:swap(*tmp , Tree[index–])。)总是不能正确执行,调了一段时间未果就先放在一边,写现在这个用指针操作实现的排序二叉树。
代码:(内置测试数据,并对于测试数据保证代码正确)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
| #include<map> #include<set> #include<list> #include<queue> #include<stack> #include<ctime> #include<cmath> #include<string> #include<vector> #include<cstdio> #include<cstdlib> #include<cstring> #include<numeric> #include<iostream> #include<algorithm>
#define MAXN 10005 #define MAX_INT 2147483647 #define LC(x) (x << 1) #define RC(x) ((x << 1) | 1) #define MID(x,y) ( (x + y) >> 1 ) #define TIME_BEGIN double t1 = clock() #define TIME_END double t2 = clock();printf("\n%.2fms\n",t2-t1)
using namespace std;
struct node //结构体定义 { int data; node *lc , *rc , *fa; node() { data = -1; lc = rc = fa = NULL; } }; node *root = new node;;
int ary[15] = {0,213,5,12,45,65,2,1,4,8,6,554,52,-1},n = 12;
void myFind(int now , node *&tmp) { tmp = root; while(tmp) { if(now > tmp->data) tmp = tmp->rc; else if(now < tmp->data) tmp = tmp->lc; else return ; } }
void myInsert(int now) { node *tmp = root; while(1) { if(now > tmp->data) { if(!tmp->rc) { tmp->rc = new node; tmp->rc->data = now; tmp->rc->fa = tmp; return ; } tmp = tmp->rc; } else if(now < tmp->data) { if(!tmp->lc) { tmp->lc = new node; tmp->lc->data = now; tmp->lc->fa = tmp; return ; } tmp = tmp->lc; } else return ; } }
void myDelete(node *&tmp)
{ node *ano = tmp->lc; if(!ano) { if(tmp == tmp->fa->lc) tmp->fa->lc = tmp->rc; else tmp->fa->rc = tmp->rc; if(tmp->rc) tmp->rc->fa = tmp->fa; free(tmp); } else { while(ano->rc) ano = ano->rc; tmp->data = ano->data; if(ano->lc) { if(ano->fa->data < ano->lc->data) ano->fa->rc = ano->lc; else ano->fa->lc = ano->lc; ano->lc->fa = ano->fa; } else { if(ano->fa == tmp) ano->fa->lc = NULL; else ano->fa->rc = NULL; } free(ano); } }
void myInit() { root->data = MAX_INT; for(int i = 1;i <= n;i ++) myInsert(ary[i]); }
void myPrint(node *tmp) { if(!tmp) return ; myPrint(tmp->lc); cout<<tmp->data<<" "; myPrint(tmp->rc); }
void myInit_test() { cout<<endl; cout<<"====myInit函数测试开始==========="<<endl; cout<<endl; myInit(); cout<<endl; cout<<"====myInit函数测试结束==========="<<endl; cout<<endl; }
void myPrint_test() { cout<<endl; cout<<"====myPrint函数测试开始==========="<<endl; cout<<endl; myPrint(root->lc); cout<<endl; cout<<endl; cout<<"====myPrint函数测试结束==========="<<endl; cout<<endl; }
void myFind_test() { cout<<endl; cout<<"====myFind函数测试开始==========="<<endl; cout<<endl; for(int i = 1;i <= n;i ++) { node *tmp; myFind(ary[i] , tmp); cout<<tmp->data<<" "; } cout<<endl; cout<<endl; cout<<"====myFind函数测试结束==========="<<endl; cout<<endl; }
void myDelete_test() { cout<<endl; cout<<"====myDelete函数测试开始==========="<<endl; cout<<endl; for(int i = 1;i <= n;i ++) { node *tmp; myFind(ary[i] , tmp); myDelete(tmp); myPrint(root->lc); cout<<endl; myInsert(ary[i]); } cout<<endl; cout<<"====myDelete函数测试结束==========="<<endl; cout<<endl; }
int main() { TIME_BEGIN; myInit_test(); myPrint_test(); myFind_test(); myDelete_test(); TIME_END; }
|