数据结构与算法分析——c语言描述 练习5.15 答案
可扩散列是继B树以来又一个复杂的数据结构,当然没B树难。
这个写了我3天,才把插入写完。
难点是树叶分裂。
分裂:
首先判断当前dl是否小于目录D;
如果小于,不用倍增目录。要让这一个分开指向两片树叶。一半(左边),一半(右边)分别指向一片树叶。注意dl可能小于D不只1,所以就要判断一半的数量是多少。
等于的话。就要倍增目录。这种情况相对前者很简单。
ExtendHash.h
#ifndef _ExtendHash_H
#define _ExtendHash_H
#include<bitset>
#define BITS 6
typedef std::bitset<BITS> ElementType;
struct LeafNode;
typedef LeafNode* Leaf;
struct Directory;
typedef Directory* ExtendibleHash;
struct Position {
int branch;
int index;
};
ExtendibleHash initExtendibleHash(int D);
void destroyTable(ExtendibleHash h);
Position find(ElementType key, ExtendibleHash h);
void insert(ElementType key, ExtendibleHash h);
void traverse(ExtendibleHash h);
#endif
ExtendHash.cpp
#include"ExtendHash.h"
#include"fatal.h"
#include<bitset>
#define M 4
struct LeafNode {
ElementType elemArr[M];
int hasInsertedNum;//从1开始
int dl;//从1开始
};
struct Directory {
int D;
Leaf* theLeaves;
};
ExtendibleHash initExtendibleHash(int D) {
ExtendibleHash h = new Directory;
h->D = D;
int LeafNum = 1 << D;
h->theLeaves = new Leaf[LeafNum];
if (h->theLeaves == NULL)
Error("OUT OF MEMORY");
for (int i = 0; i < LeafNum; i++) {
h->theLeaves[i] = new LeafNode;
h->theLeaves[i]->hasInsertedNum = 0;
h->theLeaves[i]->dl = M / 2;
}
return h;
}
void destroyTable(ExtendibleHash h) {
int LeafNum = 1 << h->D;
for (int i = 0; i < LeafNum; ) {
int temp = i + (1 << (h->D - h->theLeaves[i]->dl));//因为有多个单元指向同一个树叶
delete h->theLeaves[i];
i = temp;
}
delete h->theLeaves;
delete h;
}
static int getLeafBranch(const ElementType &key, int D) {
int pos = 0;
for (int i = 1; i <= D; i++) {//bitset开始下标为0
pos = (pos << 1) + key[BITS - i];
}
return pos;
}
static int isLeafFull(ExtendibleHash h, int branch) {
return h->theLeaves[branch]->hasInsertedNum == M;
}
Position find(ElementType key, ExtendibleHash h) {
int branch = getLeafBranch(key, h->D);
int pos = -1;
for (int i = 0; i < h->theLeaves[branch]->hasInsertedNum; i++) {
if (key == h->theLeaves[branch]->elemArr[i]) {
pos = i;
break;
}
}
Position retPos;
retPos.branch = branch;
retPos.index = pos;
return retPos;
}
static int getStartIndex(int branch, int dl, int D) {
int pos = branch >> (D - dl);
return pos << (D - dl);
}
static void pointToNewLeaf(int branch, int dl, ExtendibleHash h, Leaf newLeaf) {
int pos = getStartIndex(branch, dl, h->D);
int amount = ((1 << (h->D - dl)) / 2);
pos += amount;
for (int i = 0; i < amount; i++) {
h->theLeaves[pos + i] = newLeaf;
}
}
static void split_leaf(ExtendibleHash h, int branch) {
Leaf oldLeaf, newLeaf;//newLeaf在右,oldLeaf在左
if (h->theLeaves[branch]->dl + 1 <= h->D)//不用倍增目录
{
newLeaf = new LeafNode;
if (newLeaf == NULL)
Error("OUT OF MOMORY");
newLeaf->hasInsertedNum = 0;
newLeaf->dl = h->theLeaves[branch]->dl;
oldLeaf = h->theLeaves[getStartIndex(branch, h->theLeaves[branch]->dl, h->D)];
pointToNewLeaf(branch, h->theLeaves[branch]->dl, h, newLeaf);
oldLeaf->dl++;
newLeaf->dl++;
}
else {//需要倍增目录
int siblingLeaf;
int newLeafNum = 1 << (h->D + 1);
Leaf* newLeafs = new Leaf[newLeafNum];
for (int i = 0; i < 1 << h->D; i++) {//
newLeafs[2 * i] = h->theLeaves[i];
newLeafs[2 * i + 1] = h->theLeaves[i];
}
free(h->theLeaves);
h->theLeaves = newLeafs;
h->D++;
branch *= 2;
siblingLeaf = branch + 1;
h->theLeaves[siblingLeaf] = new LeafNode;
if (h->theLeaves[siblingLeaf] == NULL)
Error("OUT OF MOMORY");
h->theLeaves[siblingLeaf]->hasInsertedNum = 0;
h->theLeaves[siblingLeaf]->dl = h->theLeaves[branch]->dl;
h->theLeaves[siblingLeaf]->dl++;
h->theLeaves[branch]->dl++;
newLeaf = h->theLeaves[siblingLeaf];
oldLeaf = h->theLeaves[branch];
}
for (int i = 0; i < oldLeaf->hasInsertedNum; i++) {
if (oldLeaf->elemArr[i][BITS - oldLeaf->dl] == true) {
newLeaf->elemArr[newLeaf->hasInsertedNum] = oldLeaf->elemArr[i];
newLeaf->hasInsertedNum++;
for (int j = i; j < oldLeaf->hasInsertedNum - 1; j++) {
oldLeaf->elemArr[j] = oldLeaf->elemArr[j + 1];
}
oldLeaf->hasInsertedNum--;
}
}
}
void insert(ElementType key, ExtendibleHash h) {
Position p = find(key, h);
int branch = p.branch;
int pos = p.index;
if (pos == -1) {//不存在要插入的元素
if (h->theLeaves[branch]->hasInsertedNum < M) {//还有空间插入
int hasInsertedNum = h->theLeaves[branch]->hasInsertedNum;
h->theLeaves[branch]->elemArr[hasInsertedNum] = key;
h->theLeaves[branch]->hasInsertedNum++;
}
else {//叶子没空间了
split_leaf(h, branch);
insert(key, h);
}
}
//traverse(h);
}
void traverse(ExtendibleHash h) {
printf("D: %d\n", h->D);
for (int i = 0; i < (1 << h->D); i++) {
printf("Leaf %d dl %d : ", i, h->theLeaves[i]->dl);
for (int j = 0; j < h->theLeaves[i]->hasInsertedNum; j++)
printf("%u ", h->theLeaves[i]->elemArr[j].to_ulong());
printf("\n");
}
printf("finish\n\n");
}
main.cpp
#include"ExtendHash.h"
#include<string>
#include<iostream>
int RandInt(int i, int j) {
int temp;
temp = (int)(i + (1.0*rand() / RAND_MAX)*(j - i));
return temp;
}
int main() {
ExtendibleHash h = initExtendibleHash(2);
unsigned long u = 0;
for (int i = 0; i <22; i++,u++) {
std::bitset<BITS> b(u);
insert(b, h);
//traverse(h);
}
traverse(h);
destroyTable(h);
h = initExtendibleHash(2);
for (int i = 0; i <22; i++) {
u = RandInt(0, 64);
std::bitset<BITS> b(u);
insert(b, h);
}
traverse(h);
destroyTable(h);
}