数据结构【查找】—B树
/*********************讲解后期补充*****************/
先上代码
1 #include "000库函数.h" 2 3 4 #define MAXSIZE 100//存储空间 5 6 #define m 3//B树的阶 7 #define N 17//数据元素的个数 8 #define MAX 5//字符串的最大长度 9 10 struct BTree 11 { 12 int keynum;//节点中关键字的个数 即节点大小 13 BTree *parent;//指向双亲的指针 14 struct Node//节点向量类型 15 { 16 int key;//关键字向量 17 BTree *ptr;//子树指针向量 18 int recptr;//记录指针向量 19 }; 20 Node node[m + 1];//0号单元未使用 21 }; 22 23 24 struct Result{ 25 BTree *pt;//指向找到的节点 26 int i;//在节点中的关键字序号 27 int tag;//查找成功与否 28 }; 29 30 int Search(BTree *p, int elem) {//p.node[i].key<=elem<p.node[i+1].key 31 int j; 32 for (int i = 1; i < p->keynum; ++i) 33 if (p->node[i].key <= elem) 34 j = i; 35 return j; 36 } 37 38 //查找B树中是否存在该数 39 /*关键字应该插在指针pt所指节点中的第i和第i+1个关键字之间*/ 40 Result* SearchBTree(BTree *T, int elem) { 41 BTree *p, *q; 42 p = T; 43 q = NULL; 44 int find = false; 45 Result *r = new Result; 46 int i = 0; 47 while (p && !find) { 48 i = Search(p, elem);//p.node[i].key<=elem<p.node[i+1].key 49 if (i > 0 && p->node[i].key == elem)//查找到了关键字 50 find = true; 51 else { 52 q = p; 53 p = p->node[i].ptr; 54 } 55 } 56 r->i = i; 57 if(find){//查找成功 58 r->pt = p; 59 r->tag = 1; 60 } 61 else {//查找不成功,返回elem的插入位置的信息 62 r->pt = q; 63 r->tag = 0; 64 } 65 return r; 66 } 67 68 /* 将r->key、r和ap分别插入到q->key[i+1]、q->recptr[i+1]和q->ptr[i+1]中 */ 69 int Insert(BTree* &pt, int n, int rx, BTree *ap) { 70 for (int i = pt->keynum; i > n; --i)//空出pt->node[n+1] 71 pt->node[i + 1] = pt->node[i];//向后挪,腾出位置来 72 pt->node[n + 1].key = rx; 73 pt->node[n + 1].ptr = ap; 74 pt->node[n + 1].recptr = rx; 75 pt->keynum++; 76 return true; 77 } 78 79 /* 将结点q分裂成两个结点,前一半保留,后一半移入新生结点ap */ 80 int split(BTree* &pt, BTree* &ap) { 81 int s = (m + 1) / 2; 82 ap = new BTree;//生成新的节点ap 83 ap->node[0].ptr = pt->node[s].ptr;//后一半移入ap中 84 for (int i = s + 1; i < m; ++i) { 85 ap->node[i - s] = pt->node[i]; 86 if (ap->node[i - s].ptr) 87 ap->node[i - s].ptr->parent = ap; 88 } 89 ap->keynum = m - s; 90 ap->parent = pt->parent; 91 pt->keynum = s - 1;/* q的前一半保留,修改keynum */ 92 93 return true; 94 } 95 96 /* 生成含信息(T,r,ap)的新的根结点&T,原T和ap为子树指针 */ 97 int NewRoot(BTree *T, int key, BTree *ap) { 98 BTree *p = new BTree; 99 p->node[0].ptr = T; 100 T = p; 101 if (T->node[0].ptr) 102 T->node[0].ptr->parent = T; 103 T->parent = NULL; 104 T->keynum = 1; 105 T->node[1].key = key; 106 T->node[1].recptr = key; 107 T->node[1].ptr = ap; 108 if (T->node[1].ptr) 109 T->node[1].ptr->parent = T; 110 111 return true; 112 } 113 114 /* 在m阶B树T上结点*q的key[i]与key[i+1]之间插入关键字K的指针r。若引起 */ 115 /* 结点过大,则沿双亲链进行必要的结点分裂调整,使T仍是m阶B树。 */ 116 int InsertBTree(BTree* &T, int elem, BTree *pt, int n) { 117 BTree *ap; 118 ap = new BTree; 119 bool finished = false; 120 int s, rx; 121 rx = elem; 122 while (pt && !finished) { 123 Insert(pt, n, rx, ap);// 将r->key、r和ap分别插入到q->key[i+1]、q->recptr[n+1]和q->ptr[n+1]中 */ 124 if (pt->keynum < m) 125 finished = true;//插入成功 126 else {//对节点进行分裂 127 s = (m + 1) / 2; 128 rx = pt->node[s].recptr; 129 split(pt, ap);/* 将q->key[s+1..m],q->ptr[s..m]和q->recptr[s+1..m]移入新结点*ap */ 130 pt = pt->parent; 131 if (pt) 132 n = Search(pt, elem);//在双亲结点中*q中查找rx->key的插入位置 133 } 134 } 135 if (!finished)/* T是空树(参数q初值为NULL)或根结点已分裂为结点*q和*ap */ 136 NewRoot(T, rx, ap);/* 生成含信息(T,rx,ap)的新的根结点*T,原T和ap为子树指针 */ 137 138 return true; 139 } 140 141 142 int T034() 143 { 144 int r[N] = { 22,16,41,58,8,11,12,16,17,22,23,31,41,52,58,59,61 }; 145 BTree *T = new BTree; 146 T = NULL; 147 Result *s; 148 for (int i = 0; i < N; i++) 149 { 150 s = SearchBTree(T, r[i]); 151 if (!s->tag) 152 InsertBTree(T, r[i], s->pt, s->i); 153 } 154 printf("\n请输入待查找记录的关键字: "); 155 int a; 156 scanf("%d", &a); 157 s = SearchBTree(T, a); 158 if (s->tag) 159 printf("(%d)", (s->pt)->node[a].key); 160 else 161 printf("没找到"); 162 printf("\n"); 163 164 return 0; 165 }