数据结构与算法分析——c语言描述 练习4.37c 答案
不是很难。反而测试的时候爆出了一个删除的bug。。。原来是树叶删除后剩下两个儿子没有更新索引。
再爆出一个删除bug,不过这个bug是调试原来发的三阶b树才发现的。还是索引的问题,问题是移动儿子指针再更新兄弟的索引,sonbranch已经不是指向兄弟了。互换两行代码顺序即可。虽然这个bug很简单。但是找出来可是。。。。。。。。。一个中午和半个下午又没了。。。。
#include"btree.h"
#include<stdlib.h>
#include"fatal.h"
struct BtreeNode;
#define M 3
struct BtreeNode {
int type;
int sonNum;//儿子数量,或当前拥有数据的数量(最底层)
PtrToNode PtrToSon[M];
ElementType elem[M];
};
static int binarySearch(PtrToNode bottomNode, ElementType X) {//对分搜索
if (bottomNode->type != 2)
Error("ERROR!...");
ElementType* arr = bottomNode->elem;
int n = bottomNode->sonNum;
if (n > 0) {
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = (high + low) / 2;
if (X < arr[mid]) {
high = mid - 1;
}
else if (X > arr[mid]) {
low = mid + 1;
}
else
return mid;
}
return -1;
}
return -1;
}
static int getSonBranch(PtrToNode Node, ElementType X) {
ElementType* arr = Node->elem;
int n = Node->sonNum;
if (n == 1)
return 0;
else if (n == 2) {
if (X < arr[0])
return 0;
else
return 1;
}
else if (n >= 2) {
int low = 0;
int high = n - 1 - 1;//第一个分支没有索引
while (low <= high) {
int mid = (high + low) / 2;
if (X < arr[mid]) {
high = mid - 1;
}
else if (X > arr[mid]) {
low = mid + 1;
}
else
return mid + 1;//第一个分支没有索引
}
return high + 1;//退出循环,此时high在左,low在右,X位于high和low的值之间
}
else {
Error("GET SON BRANCH ERROR");
}
}
static void binaryInsert(ElementType arr[], int n, ElementType X) {
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = (low + high) / 2;
if (arr[mid] < X) {
low = mid + 1;
}
else if (arr[mid] > X)
high = mid - 1;
}
while (arr[low] < X&& low < n) {
low++;
}
for (int i = n; i > low; i--) {
arr[i] = arr[i - 1];
}
arr[low] = X;
}
static void binaryInsertForBottomNode(PtrToNode bottomNode, ElementType X) {//对分插入
if (bottomNode->type != 2)
Error("eror!");
ElementType* arr = bottomNode->elem;
int n = bottomNode->sonNum;
if (n > 0) {
binaryInsert(arr, n, X);
}
else
arr[0] = X;
bottomNode->sonNum++;
}
static PtrToNode allocNode(int type) {//0为内部节点 1为叶子 2为底层节点
PtrToNode p = malloc(sizeof(struct BtreeNode));
if (p == NULL)
Error("OUT OF SPACE!!");
p->type = type;
p->sonNum = 0;
return p;
}
static void updateIndex(PtrToNode p) {
if (p->sonNum >= 2) {
for (int i = 0; i < p->sonNum - 1; i++) {
PtrToNode son = p->PtrToSon[i + 1];
while (son->type != 2) {
son = son->PtrToSon[0];
}
p->elem[i] = son->elem[0];
}
}
}
static PtrToNode insertAndSplitBottomNode(PtrToNode b1, ElementType X) {
if (b1->sonNum != 3)
Error("ERROR!");
PtrToNode b2 = allocNode(2);
ElementType tempElem[4];
for (int i = 0; i < 3; i++)
tempElem[i] = b1->elem[i];
binaryInsert(tempElem, 3, X);
for (int i = 0; i < 2; i++)
b1->elem[i] = tempElem[i];
for (int i = 0; i < 2; i++)
b2->elem[i] = tempElem[i + 2];
b1->sonNum = b2->sonNum = 2;
return b2;
}
static PtrToNode split(Btree father, PtrToNode newSon, int sonBranch) {
PtrToNode allSon[4];
int i, j;
for (i = 0, j = 0; j <= sonBranch; i++, j++)
allSon[i] = father->PtrToSon[j];
allSon[i++] = newSon;
for (; j < father->sonNum; i++, j++)
allSon[i] = father->PtrToSon[j];
PtrToNode newFater = allocNode(father->type);
father->sonNum = 2;
father->PtrToSon[0] = allSon[0];
father->PtrToSon[1] = allSon[1];
updateIndex(father);
newFater->sonNum = 2;
newFater->PtrToSon[0] = allSon[2];
newFater->PtrToSon[1] = allSon[3];
updateIndex(newFater);
return newFater;
}
static void insertPtrToSon(PtrToNode father, PtrToNode newSon, int sonBranch) {
if (father->sonNum == 0) {
father->PtrToSon[0] = newSon;
}
else {
int i;
for (i = father->sonNum; i > sonBranch + 1; i--) {
father->PtrToSon[i] = father->PtrToSon[i - 1];
}
father->PtrToSon[sonBranch + 1] = newSon;
}
father->sonNum++;
}
Btree createBtree() {
Btree t = malloc(sizeof(struct BtreeNode));
if (t == NULL)
Error("OUT OF MEMORY!");
t->sonNum = 0;
t->type = 1;//空树,根节点也是树叶
return t;
}
void makeEmpty(Btree t) {
if (t->type) {
for (int i = 0; i < t->sonNum; i++)
free(t->PtrToSon[i]);
free(t);
}
else {
for (int i = 0; i < t->sonNum; i++) {
makeEmpty(t->PtrToSon[i]);
}
free(t);
}
}
PtrToNode find(ElementType X, Btree t) {
if (t->type == 0) {//内部节点
int p = getSonBranch(t, X);
return find(X, t->PtrToSon[p]);
}
else {
int p;
if (t->sonNum == 0)//刚创建树的时候,空
return NULL;
else if (t->sonNum == 1) {
p = binarySearch(t->PtrToSon[0], X);
if (p == -1)
return NULL;
else
return t->PtrToSon[0];
}
else {
p = getSonBranch(t, X);//选择儿子分支
int tempCursor = binarySearch(t->PtrToSon[p], X);//在最底层中查找
if (tempCursor == -1)
return NULL;
return t->PtrToSon[p];
}
}
}
static void insertElem_LeafEmpty(ElementType X, Btree t) {
//leafAddNewSon(t, 0);
PtrToNode newSon = allocNode(2);
binaryInsertForBottomNode(newSon, X);
insertPtrToSon(t, newSon, 0);
}
static void insertElem_LeafSonNotFull(ElementType X, Btree t, int sonChoice) {
binaryInsertForBottomNode(t->PtrToSon[sonChoice], X);
updateIndex(t);
}
static Btree insert_internal(ElementType X, Btree t);
static void insertElem_LeafNotFull_LeafSonFull(ElementType X, Btree t, int sonBranch) {
PtrToNode newSon = insertAndSplitBottomNode(t->PtrToSon[sonBranch], X);
insertPtrToSon(t, newSon, sonBranch);
updateIndex(t);
}
static PtrToNode insertElem_LeafFull_LeafSonFull(ElementType X, Btree t, int sonBranch) {
PtrToNode newSon = insertAndSplitBottomNode(t->PtrToSon[sonBranch], X);
PtrToNode newFather = split(t, newSon, sonBranch);
return newFather;
}
static Btree insert_internal(ElementType X, Btree t) {
if (t->type == 0) {//非叶子
int sonBranch = getSonBranch(t, X);
PtrToNode newSon = insert_internal(X, t->PtrToSon[sonBranch]);
if (newSon) {
if (t->sonNum < M) {
insertPtrToSon(t, newSon, sonBranch);
updateIndex(t);
return NULL;
}
else {
PtrToNode newfather = split(t, newSon, sonBranch);
return newfather;
}
}
else
return NULL;
}
else if (t->type == 1) {//叶子
if (t->sonNum == 0) {
insertElem_LeafEmpty(X, t);
return NULL;
}
else {
int sonBranch = getSonBranch(t, X);//选择儿子分支
int XCursor = binarySearch(t->PtrToSon[sonBranch], X);//在儿子中查找
if (XCursor == -1) {//不存在X
if (t->PtrToSon[sonBranch]->sonNum < M) {//叶子的儿子数量未满
insertElem_LeafSonNotFull(X, t, sonBranch);
return NULL;
}
else if (sonBranch > 0 && t->PtrToSon[sonBranch - 1]->sonNum < M) {//左兄弟未满
t->PtrToSon[sonBranch - 1]->elem[M - 1] = t->PtrToSon[sonBranch]->elem[0];
t->PtrToSon[sonBranch - 1]->sonNum++;
for (int i = 0; i < M - 1; i++) {
t->PtrToSon[sonBranch]->elem[i] = t->PtrToSon[sonBranch]->elem[i + 1];
}
t->PtrToSon[sonBranch]->sonNum--;
binaryInsertForBottomNode(t->PtrToSon[sonBranch], X);
updateIndex(t);
return NULL;
}
else if (sonBranch + 1 < t->sonNum&& t->PtrToSon[sonBranch + 1]->sonNum < M) {//右兄弟未满
binaryInsertForBottomNode(t->PtrToSon[sonBranch + 1], t->PtrToSon[sonBranch]->elem[M - 1]);
t->PtrToSon[sonBranch]->sonNum--;
binaryInsertForBottomNode(t->PtrToSon[sonBranch], X);
updateIndex(t);
return NULL;
}
else if (t->sonNum < M && t->PtrToSon[sonBranch]->sonNum == M) {//父亲未满,儿子满,分裂
insertElem_LeafNotFull_LeafSonFull(X, t, sonBranch);
return NULL;
}
else {//父亲满,儿子满
PtrToNode newfather = insertElem_LeafFull_LeafSonFull(X, t, sonBranch);
return newfather;
}
}
else
return NULL;//已存在X
}
}
else {
Error("type error");
}
}
Btree insert(ElementType X, Btree t) {
PtrToNode p = insert_internal(X, t);
if (p == NULL)
return t;
else {
PtrToNode newRoot = allocNode(0);
insertPtrToSon(newRoot, t, 0);
insertPtrToSon(newRoot, p, 0);
updateIndex(newRoot);
return newRoot;
}
}
void Dir(Btree t) {
if (t->type == 0) {
for (int i = 0; i < t->sonNum; i++)
Dir(t->PtrToSon[i]);
}
else if (t->type == 1) {
printf("\n");
for (int i = 0; i < t->sonNum; i++) {
for (int j = 0; j < t->PtrToSon[i]->sonNum; j++) {
printf("%d ", t->PtrToSon[i]->elem[j]);
}
printf(" ");
}
}
}
static void deleteAndFreePtrToSon(PtrToNode father, int sonBranch) {
free(father->PtrToSon[sonBranch]);
for (int i = sonBranch; i < father->sonNum - 1; i++) {
father->PtrToSon[i] = father->PtrToSon[i + 1];
}
father->sonNum--;
}
static void deletePtrToSon(PtrToNode father, int sonBranch) {
for (int i = sonBranch; i < father->sonNum - 1; i++) {
father->PtrToSon[i] = father->PtrToSon[i + 1];
}
father->sonNum--;
}
static void binaryDeleteForBottomNode(PtrToNode bottomNode, ElementType X) {
int p = binarySearch(bottomNode, X);
if (p != -1) {
for (int i = p; i < bottomNode->sonNum - 1; i++) {
bottomNode->elem[i] = bottomNode->elem[i + 1];
}
bottomNode->sonNum--;
}
}
static int delete_internal(ElementType X, Btree t) {//返回类型0表示儿子够,1表示儿子不够
if (t->type == 0) {//内部节点
int p = getSonBranch(t, X);
int isSon_NotEnough_grandson = delete_internal(X, t->PtrToSon[p]);
if (isSon_NotEnough_grandson == 0)
return 0;
else {
int brother;
if (p + 1 < t->sonNum) {
brother = p + 1;
}
else {
brother = p - 1;
}
if (t->PtrToSon[brother]->sonNum == 2) {
if (p < brother) {
insertPtrToSon(t->PtrToSon[brother], t->PtrToSon[p]->PtrToSon[0], -1);
}
else
insertPtrToSon(t->PtrToSon[brother], t->PtrToSon[p]->PtrToSon[0], 1);
updateIndex(t->PtrToSon[brother]);//这个顺序一定要在前面,因为deleteAndFreePtrToSon移动了儿子指针,所以要先更新
deleteAndFreePtrToSon(t, p);
updateIndex(t);
return t->sonNum == 1;
}
else if (t->PtrToSon[brother]->sonNum == 3) {
if (p < brother) {
insertPtrToSon(t->PtrToSon[p], t->PtrToSon[brother]->PtrToSon[0], 0);
deletePtrToSon(t->PtrToSon[brother], 0);
}
else {
insertPtrToSon(t->PtrToSon[p], t->PtrToSon[brother]->PtrToSon[2], -1);
deletePtrToSon(t->PtrToSon[brother], 2);
}
updateIndex(t->PtrToSon[p]);
updateIndex(t->PtrToSon[brother]);
updateIndex(t);
return 0;
}
else {
Error("what the hell?");
return 0;
}
}
}
else if (t->type == 1) {//叶子
int p;
if (t->sonNum == 0)//刚创建树的时候,空
return 0;
if (t->sonNum == 1) {
p = 0;
}
else {
p = getSonBranch(t, X);//选择儿子分支
}
binaryDeleteForBottomNode(t->PtrToSon[p], X);
if (t->PtrToSon[p]->sonNum == 0) {
deleteAndFreePtrToSon(t, p);
return 0;
}
else if (t->PtrToSon[p]->sonNum == 1) {
int brother;
if (p > 0) {
brother = p - 1;
}
else if (p + 1 < t->sonNum) {
brother = p + 1;
}
else {//只有一个儿子,无兄弟
return 0;
}
if (t->PtrToSon[brother]->sonNum == 3) {
if (brother < p) {
t->PtrToSon[p]->elem[1] = t->PtrToSon[p]->elem[0];
t->PtrToSon[p]->elem[0] = t->PtrToSon[brother]->elem[2];
t->PtrToSon[p]->sonNum++;
t->PtrToSon[brother]->sonNum--;
}
else {
t->PtrToSon[p]->elem[1] = t->PtrToSon[brother]->elem[0];
for (int i = 0; i < 2; i++) {
t->PtrToSon[brother]->elem[i] = t->PtrToSon[brother]->elem[i + 1];
}
t->PtrToSon[p]->sonNum++;
t->PtrToSon[brother]->sonNum--;
}
updateIndex(t);
return 0;
}
else if (t->PtrToSon[brother]->sonNum == 2) {
binaryInsertForBottomNode(t->PtrToSon[brother], t->PtrToSon[p]->elem[0]);
deleteAndFreePtrToSon(t, p);
updateIndex(t);
return t->sonNum == 1;
}
else {
Error("what the hell?");
return 0;
}
}
else//底层节点关键字数目为2
return 0;
}
else {
Error("what the hell?");
return 0;
}
}
Btree Delete(ElementType X, Btree t) {
if (delete_internal(X, t)) {
if (t->type == 0) {
Btree newRoot = t->PtrToSon[0];
free(t);
return newRoot;
}
}
updateIndex(t);
return t;
}