可扩散列

数据结构与算法分析——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);
}


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值