Автор: Пользователь скрыл имя, 23 Декабря 2012 в 23:41, курсовая работа
Целью создания программного продукта данной курсовой работы является изучение структуры данных B+ - дерево.
В данной курсовой работе реализуется программный комплекс "Информационно-поисковая система банка на основе B+-дерева".
Основания для разработки
Данный программный продукт разрабатывается как задание на курсовую работу по дисциплине "Структуры и алгоритмы обработки данных".
1 ТЕХНИЧЕСКОЕ ЗАДАНИЕ 5
1.1 Введение 5
1.2 Основания для разработки 6
1.3 Назначение разработки 6
1.3.1 Функциональное и эксплуатационное назначение изделия 6
1.3.2 Перечень требований пользователя к программному продукту 6
1.3.3 Рассмотренные альтернативы 6
1.4 Требования к программе или программному изделию 7
1.4.1 Стандарты 7
1.4.2 Требования к составу и параметрам технических средств 7
1.4.3 Требования к информационной и программной совместимости 7
1.4.4 Требования к функциональным характеристикам 8
1.4.5 Результирующие компоненты изделия 8
1.4.6 Носители информации 8
1.4.7 Безопасность и секретность 8
1.4.8 Удобства эксплуатации 8
1.4.9 Мобильность 9
1.5 Требования к программной документации 9
1.6 Стадии и этапы разработки 9
1.7 Порядок контроля и приемки 10
2 ТЕХНИЧЕСКИЙ ПРОЕКТ 11
2.1 Анализ области 11
2.2 Структура программы 11
2.2.1 Класс TFormMain 11
2.2.2 Класс CBTree 12
2.2.3 Методические ограничения 13
2.2.4 Аппаратные ограничения 13
3 РАБОЧИЙ ПРОЕКТ 14
3.1 Введение 14
3.2 Назначение разработки 14
3.3 Требования к программе или программному изделию 14
3.3.1 Стандарты 14
3.3.2 Требования к составу и параметрам технических средств 14
3.3.3 Требования к информационной и программной совместимости 15
3.3.4 Результирующие компоненты изделия 15
3.3.5 Безопасность и секретность 15
3.3.6 Рестарт 15
3.4 Описание модулей Form.h и Form.cpp 16
3.4.1 Диаграммы классов 16
3.4.2 Описание структуры Bus 17
3.4.3 Описание класса TFormMain 17
3.4.4 Описание констант и макроопределений 17
3.4.5 Описание подпрограмм 18
3.5 Описание модуля Bstar.h 22
3.5.1 Диаграммы классов 22
3.5.2 Описание структуры CBTree<Data,T>::Node 23
3.5.3 Описание класса template <class Data, short T=2> class CBTree 23
3.5.4 Описание констант и макроопределений 24
3.5.5 Описание подпрограмм 24
3.6 Тестирование 34
3.6.1 Цель испытаний 34
3.6.2 Тесты 34
Список использованных источников 41
Приложение А. 42
Приложение Б 54
}
//----------------------------
void __fastcall TFormMain::
TScrollCode ScrollCode, int &ScrollPos)
{
Y0 = - ScrollPos + 20;
PaintBox->Refresh();
}
//----------------------------
Приложение Б
Листинг файла BTree.h
#pragma once
#ifndef BTREE
#define BTREE
#define NULL 0
typedef enum{
SUCCESS,
NOT_FOUND,
NO_FREE_SPACE,
KEY_ALREADY_EXISTS,
NOT_ENOUGH_KEYS
} RESULT;
template <class Data>
class CB_PLUS_Tree
{
public:
static short T;
struct Node{
Data* item; // массив записей. В узле находятся сами записи, а не указатели
Node** ptr; // массив указателей на другие узлы
Node* parent; // родитель узла
short keys_count; // количество занятых мест в узле
bool leaf; // является ли узел листом
short index; // индекс узла
static short T; // порядок дерева
short level; // уровень в иерархии, глубина. 0 у корня
short width; // ширина (количество листьев, родственных узлу). Для листьев = 1
short indent; // количество неродственных узлу листьев, висящих слева. У листьев - число левых соседей
void Reset()
{
T = CB_PLUS_Tree<Data>::T;
item = new Data[2*T+1];
ptr = new Node*[2*T+2];
for (short i=0; i<2*T+1; ++i){
ptr[i] = NULL;
item[i] = NULL;
}
ptr[2*T+1] = NULL;
level = width = indent = 0;
}
Node(Data data, Node* p, short i, bool l): keys_count(0), index(i), leaf(l), parent(p)
{
Reset();
if (&data != NULL){
if (leaf){
item[0] = data;
} else {
item[0].key = data.key;
}
keys_count = 1;
}
}
Node(Data * data, Node** pointers, short count, Node* p, short i, bool l):keys_count(count), index(i), leaf(l), parent(p)
{
Reset();
for (short i=0; i<count; ++i){
item[i] = data[i];
ptr[i] = pointers[i];
if (ptr[i]!=NULL){
ptr[i]->index = i;
ptr[i]->parent = this;
}
}
ptr[count] = pointers[count];
if (ptr[i]!=NULL){
ptr[count]->index = count;
ptr[count]->parent = this;
}
}
~Node()
{
delete [] item;
delete [] ptr;
parent = NULL;
item = NULL;
ptr = NULL;
keys_count = index = 0;
leaf = true;
}
};
Node* root;
public:
CB_PLUS_Tree(void);
CB_PLUS_Tree(short t); // t - порядок дерева
void SetOrder(short t); // установка порядка
RESULT AddKey(Data); // добавление записи в дерево
Node* SearchKey(Data d, Node* node, short & index); // поиск записи d в поддереве node. Возвращает узел, в котором завершился поиск. index - возвращаемая позиция ключа в найденном узле. Если поиск неудачный, то index = -1
RESULT DeleteKey(Data d);
void AssignLevels(Node*
node);
short AssignWidths(Node* node); // установка ширины узлов (количества родственных листьев);
void AssignIndents(Node* node);
~CB_PLUS_Tree(void);
private:
void SplitNode(Node* node); // разбиение узла
void InsertPointer(Node* node, short index, Node* pointer); // Вставка указателя
void InsertKey(Node* node, Data d); // вставка ключа d в узел node
void EraseKeys(Node* node,short start, short count);
void ErasePointers(Node* node,short start, short count);
void Balancing(Node* node);
Node* ReplaceKey(Node* node, short & index);
void ConcatNodes(Node* left, Node* right);
bool TransferFromLeftNode(Node* dest);
bool TransferFromRightNode(Node* dest);
};
template <class Data>
short CB_PLUS_Tree<Data>::T = 3;
template <class Data>
short CB_PLUS_Tree<Data>::Node::T = 3;
template <class Data>
CB_PLUS_Tree<Data>::CB_PLUS_
{
T = 3;
root = NULL;
}
template <class Data>
CB_PLUS_Tree<Data>::CB_PLUS_
{
T = t;
root = NULL;
}
template <class Data>
CB_PLUS_Tree<Data>::~CB_PLUS_
{
}
template <class Data>
void CB_PLUS_Tree<Data>::SetOrder(
{
T = t;
}
template <class Data>
typename CB_PLUS_Tree<Data>::Node* CB_PLUS_Tree<Data>::SearchKey(
{
index = -1;
Node* found = NULL;
if (node->leaf){
for (short i=0; i<node->keys_count; ++i){
if (d.key == node->item[i].key){
index = i;
return node;
}
}
return node;
}
for (short i=0; i<node->keys_count; ++i){
if (d.key <= node->item[i].key){
found = SearchKey(d,node->ptr[i],
return found;
}
}
found = SearchKey(d,node->ptr[node->
return found;
}
template <class Data>
void CB_PLUS_Tree<Data>::InsertKey(
{
for (short i = node->keys_count-1; i>=0; --i){
if (d.key > node->item[i].key){
if (node->leaf){
node->item[i+1] = d;
break;
} else {
break;
}
}
else{
node->item[i+1] = node->item[i];
if (i == 0){
break;
break;
}
}
}
}
template <class Data>
void CB_PLUS_Tree<Data>::
{
for (short i = node->keys_count; i>=index; --i){
node->ptr[i+1] = node->ptr[i];
if (node->ptr[i+1]!=NULL)
node->ptr[i+1]->index = i+1;
}
node->ptr[index] = pointer;
}
template <class Data>
RESULT CB_PLUS_Tree<Data>::AddKey(
{
if (root == NULL){ // если корня нет, то создаем его
root = new Node(d,NULL,0,true); // с одной записью d
return SUCCESS;
}
short index = -1;
Node* dest = SearchKey(d,root,index);
if (index != -1) // запись уже есть в узле
return KEY_ALREADY_EXISTS;
InsertKey(dest,d);
dest->keys_count++;
if (dest->keys_count == 2*T+1)
SplitNode(dest);
return SUCCESS;
}
template <class Data>
void CB_PLUS_Tree<Data>::SplitNode(
{
Node * left = NULL;
Node * right = NULL;
if (!node->leaf){
left = new Node(&node->item[0],&node->
right = new Node(&node->item[T+1],&node->
} else{
left = new Node(&node->item[0],&node->
right = new Node(&node->item[T+1],&node->
}
if (node == root){
Node* new_root = NULL;
if (node->leaf){
new_root = new Node(node->item[T],NULL,0,
}else{
new_root = new Node(node->item[T],NULL,0,
}
new_root->ptr[0] = left;
left->index = 0;
new_root->ptr[1] = right;
right->index = 1;
left->parent = right->parent = root = new_root;
}
else{
Node* Parent = node->parent;
Parent->ptr[node->index] = left;
InsertPointer(Parent,node->
if (node->leaf){
InsertKey(Parent,node->item[T]
} else {
InsertKey(Parent,node->item[T]
}
Parent->keys_count++;
if (Parent->keys_count == 2*T+1)
SplitNode(Parent);
}
delete node;
}
template <class Data>
RESULT CB_PLUS_Tree<Data>::DeleteKey(
{
short index = -1;
Node* node = SearchKey(d,root,index);
if (index==-1)
return NOT_FOUND;
if (node->leaf == false){
node = ReplaceKey(node,index);
}
EraseKeys(node,index,1);
node->keys_count--;
if (node == root && node->keys_count == 0){
root = NULL;
}
else{
Balancing(node);
}
return SUCCESS;
}
template <class Data>
void CB_PLUS_Tree<Data>::Balancing(
{
if (node == root)
return;
Node* Parent = node->parent;
bool flag = false;
if (Parent == root)
flag = true;
Node* left = NULL;
Node* right = NULL;
if (node->index != 0)
left = Parent->ptr[node->index-1];
if (node->index != Parent->keys_count)
right = Parent->ptr[node->index+1];
if (node->keys_count < T){
if (left != NULL){
if (!TransferFromLeftNode(node)){
ConcatNodes(left,node);
if ((flag && Parent == root) || !flag)
Balancing(Parent);
}
}
else if (right != NULL){
if (!TransferFromRightNode(node))
ConcatNodes(node,right);
if ((flag && Parent == root) || !flag)
Balancing(Parent);
}
}
}
}
template <class Data>
void CB_PLUS_Tree<Data>::
{
Data* items = new Data[2*T+1];
Node** ptrs = new Node*[2*T+2];
for (short i=0; i<2*T+1; ++i){
items[i] = NULL;
ptrs[i] = NULL;
}
ptrs[2*T+1]=NULL;
short length;
if (!left->leaf){
length = left->keys_count + right->keys_count + 1;
for (short i=0; i<length; ++i){
if (i < left->keys_count){
items[i] = left->item[i];
ptrs[i] = left->ptr[i];
}
else if (i == left->keys_count){
items[i] = left->parent->item[left->
ptrs[i] = left->ptr[i];
}
else if (i < length){
items[i] = right->item[i-left->keys_
ptrs[i] = right->ptr[i-left->keys_count-
}
}
ptrs[length] = right->ptr[right->keys_count];
if (left->parent == root && root->keys_count == 1){
Node* new_root = new Node(items,ptrs,length,NULL,0,
root = new_root;
delete left->parent;
}
else{
Node* new_node = new Node(items,ptrs,length,left->
EraseKeys(left->parent,left->
ErasePointers(left->parent,
left->parent->ptr[left->index] = new_node;
left->parent->keys_count--;
}
}
else{
length = left->keys_count + right->keys_count;
for (short i=0; i<length; ++i){
if (i < left->keys_count){
items[i] = left->item[i];
ptrs[i] = left->ptr[i];
}
else {
items[i] = right->item[i-left->keys_
ptrs[i] = right->ptr[i-left->keys_count]
}
}
ptrs[length] = right->ptr[right->keys_count];
if (left->parent == root && root->keys_count == 1){
Node* new_root = new Node(items,ptrs,length,NULL,0,
root = new_root;
delete left->parent;
}
else{
Node* new_node = new Node(items,ptrs,length,left->
EraseKeys(left->parent,left->
ErasePointers(left->parent,
left->parent->ptr[left->index] = new_node;
left->parent->keys_count--;
}
}
delete left;
delete right;
delete [] items;
delete [] ptrs;
left = right = NULL;
items = NULL;
ptrs = NULL;
}
template <class Data>
bool CB_PLUS_Tree<Data>::
{
Node* left = NULL;
if (dest->index !=0)
left = dest->parent->ptr[dest->index-
else
return false;
if (left->keys_count < T+1)
if (TransferFromLeftNode(left)!=
return false;
if (!dest->leaf){
InsertPointer(dest,0,left->
ErasePointers(left,left->
if (dest->ptr[0] != NULL){
dest->ptr[0]->parent = dest;
dest->ptr[0]->index = 0;
}
InsertKey(dest,left->parent->
dest->keys_count++;
left->parent->item[left->
EraseKeys(left,left->keys_
left->keys_count--;
}else{
dest->parent->item[left->
InsertKey(dest,left->item[
dest->keys_count++;
EraseKeys(left,left->keys_
left->keys_count--;
}
return true;
}
template <class Data>
bool CB_PLUS_Tree<Data>::
{
Node* right = NULL;
if (dest->index != dest->parent->keys_count)
right = dest->parent->ptr[dest->index+
else
return false;
if (right->keys_count < T+1)
if (TransferFromRightNode(right)!
return false;
if (!dest->leaf){
InsertPointer(dest,dest->keys_
ErasePointers(right,0,1);
if (dest->ptr[dest->keys_count+1] != NULL){
dest->ptr[dest->keys_count+
dest->ptr[dest->keys_count+
}
InsertKey(dest,dest->parent->
dest->keys_count++;
right->parent->item[dest->
EraseKeys(right,0,1);
right->keys_count--;
} else{
InsertKey(dest,right->item[0])
dest->keys_count++;
right->parent->item[dest->
EraseKeys(right,0,1);
right->keys_count--;
}
return true;
}
template <class Data>
void CB_PLUS_Tree<Data>::EraseKeys(
{
for (short i = start; i<node->keys_count; ++i){
if (i+count < node->keys_count)
node->item[i] = node->item[i+count];
else
node->item[i] = NULL;
}
}
template <class Data>
void CB_PLUS_Tree<Data>::
{
for (short i = start; i<node->keys_count+1; ++i){
if (i+count < node->keys_count+1){
node->ptr[i] = node->ptr[i+count];
if (node->ptr[i]!=NULL){
node->ptr[i]->index = i;
}
}
else
node->ptr[i] = NULL;
}
}
template <class Data>
typename CB_PLUS_Tree<Data>::Node* CB_PLUS_Tree<Data>::
{
if (node->leaf == true){
return node;
}
Node* left = node->ptr[index];
Node* right = node->ptr[index+1];
Node* leaf = NULL;
if (left->keys_count > right->keys_count){
node->item[index] = left->item[left->keys_count-1]
index = left->keys_count-1;
leaf = ReplaceKey(left,index);
}
else{
node->item[index] = right->item[0];
index = 0;
leaf = ReplaceKey(right,index);
}
return leaf;
}
template <class Data>
void CB_PLUS_Tree<Data>::
{
if (node->parent != NULL)
node->level = node->parent->level + 1;
else
node->level = 0;
if (node->leaf == true)
return;
for (short i=0; i<=node->keys_count; ++i){
AssignLevels(node->ptr[i]);
}
}
//----------------------------
template <class Data>
short CB_PLUS_Tree<Data>::
{
node->width = 0;
if (node->leaf == true){
node->width = 1;
return 1;
}
for (short i=0; i<=node->keys_count; ++i){
node->width += AssignWidths(node->ptr[i]);
}
return node->width;
}
//----------------------------
template <class Data>
void CB_PLUS_Tree<Data>::
{
if (node->index == 0)
if (node == root)
node->indent = 0;
else
node->indent = node->parent->indent;
else
node->indent = node->parent->ptr[node->index-
if (node->leaf == true)
return;
for (short i=0; i<=node->keys_count; ++i){
AssignIndents(node->ptr[i]);
}
}
//----------------------------
#pragma hdrstop
#endif