- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试按级别顺序打印一棵 b 树,但它一直在崩溃。我不确定真正的原因是什么,但我认为它崩溃是因为指针。我正在尝试使用我在网上找到的一个函数,该函数遍历每个级别并将其放入队列中并打印出来,但我遇到了这个问题。如果有人有其他方法,请告诉我。
// C++ program for B-Tree insertion
#include<iostream>
#include <queue>
using namespace std;
int ComparisonCount = 0;
// A BTree node
class BTreeNode
{
int *keys; // An array of keys
int t; // Minimum degree (defines the range for number of keys)
BTreeNode **C; // An array of child pointers
int n; // Current number of keys
bool leaf; // Is true when node is leaf. Otherwise false
public:
BTreeNode(int _t, bool _leaf); // Constructor
// A utility function to insert a new key in the subtree rooted with
// this node. The assumption is, the node must be non-full when this
// function is called
void insertNonFull(int k);
// A utility function to split the child y of this node. i is index of y in
// child array C[]. The Child y must be full when this function is called
void splitChild(int i, BTreeNode *y);
// A function to traverse all nodes in a subtree rooted with this node
void traverse();
// A function to search a key in subtree rooted with this node.
BTreeNode *search(int k); // returns NULL if k is not present.
// Make BTree friend of this so that we can access private members of this
// class in BTree functions
friend class BTree;
};
// A BTree
class BTree
{
BTreeNode *root; // Pointer to root node
int t; // Minimum degree
public:
// Constructor (Initializes tree as empty)
BTree(int _t)
{
root = NULL; t = _t;
}
// function to traverse the tree
void traverse()
{
if (root != NULL) root->traverse();
}
// function to search a key in this tree
BTreeNode* search(int k)
{
return (root == NULL) ? NULL : root->search(k);
}
// The main function that inserts a new key in this B-Tree
void insert(int k);
};
// Constructor for BTreeNode class
BTreeNode::BTreeNode(int t1, bool leaf1)
{
// Copy the given minimum degree and leaf property
t = t1;
leaf = leaf1;
// Allocate memory for maximum number of possible keys
// and child pointers
keys = new int[2 * t - 1];
C = new BTreeNode *[2 * t];
// Initialize the number of keys as 0
n = 0;
}
// Function to traverse all nodes in a subtree rooted with this node
/*void BTreeNode::traverse()
{
// There are n keys and n+1 children, travers through n keys
// and first n children
int i;
for (i = 0; i < n; i++)
{
// If this is not leaf, then before printing key[i],
// traverse the subtree rooted with child C[i].
if (leaf == false)
{
ComparisonCount++;
C[i]->traverse();
}
cout << " " << keys[i];
}
// Print the subtree rooted with last child
if (leaf == false)
{
ComparisonCount++;
C[i]->traverse();
}
}*/
// Function to search key k in subtree rooted with this node
BTreeNode *BTreeNode::search(int k)
{
// Find the first key greater than or equal to k
int i = 0;
while (i < n && k > keys[i])
i++;
// If the found key is equal to k, return this node
if (keys[i] == k)
{
ComparisonCount++;
return this;
}
// If key is not found here and this is a leaf node
if (leaf == true)
{
ComparisonCount++;
return NULL;
}
// Go to the appropriate child
return C[i]->search(k);
}
// The main function that inserts a new key in this B-Tree
void BTree::insert(int k)
{
// If tree is empty
if (root == NULL)
{
ComparisonCount++;
// Allocate memory for root
root = new BTreeNode(t, true);
root->keys[0] = k; // Insert key
root->n = 1; // Update number of keys in root
}
else // If tree is not empty
{
// If root is full, then tree grows in height
if (root->n == 2 * t - 1)
{
ComparisonCount++;
// Allocate memory for new root
BTreeNode *s = new BTreeNode(t, false);
// Make old root as child of new root
s->C[0] = root;
// Split the old root and move 1 key to the new root
s->splitChild(0, root);
// New root has two children now. Decide which of the
// two children is going to have new key
int i = 0;
if (s->keys[0] < k)
{
ComparisonCount++;
i++;
}s->C[i]->insertNonFull(k);
// Change root
root = s;
}
else // If root is not full, call insertNonFull for root
root->insertNonFull(k);
}
}
// A utility function to insert a new key in this node
// The assumption is, the node must be non-full when this
// function is called
void BTreeNode::insertNonFull(int k)
{
// Initialize index as index of rightmost element
int i = n - 1;
// If this is a leaf node
if (leaf == true)
{
ComparisonCount++;
// The following loop does two things
// a) Finds the location of new key to be inserted
// b) Moves all greater keys to one place ahead
while (i >= 0 && keys[i] > k)
{
keys[i + 1] = keys[i];
i--;
}
// Insert the new key at found location
keys[i + 1] = k;
n = n + 1;
}
else // If this node is not leaf
{
// Find the child which is going to have the new key
while (i >= 0 && keys[i] > k)
i--;
// See if the found child is full
if (C[i + 1]->n == 2 * t - 1)
{
ComparisonCount++;
// If the child is full, then split it
splitChild(i + 1, C[i + 1]);
// After split, the middle key of C[i] goes up and
// C[i] is splitted into two. See which of the two
// is going to have the new key
if (keys[i + 1] < k)
i++;
}
C[i + 1]->insertNonFull(k);
}
}
// A utility function to split the child y of this node
// Note that y must be full when this function is called
void BTreeNode::splitChild(int i, BTreeNode *y)
{
// Create a new node which is going to store (t-1) keys
// of y
BTreeNode *z = new BTreeNode(y->t, y->leaf);
z->n = t - 1;
// Copy the last (t-1) keys of y to z
for (int j = 0; j < t - 1; j++)
z->keys[j] = y->keys[j + t];
// Copy the last t children of y to z
if (y->leaf == false)
{
ComparisonCount++;
for (int j = 0; j < t; j++)
z->C[j] = y->C[j + t];
}
// Reduce the number of keys in y
y->n = t - 1;
// Since this node is going to have a new child,
// create space of new child
for (int j = n; j >= i + 1; j--)
C[j + 1] = C[j];
// Link the new child to this node
C[i + 1] = z;
// A key of y will move to this node. Find location of
// new key and move all greater keys one space ahead
for (int j = n - 1; j >= i; j--)
keys[j + 1] = keys[j];
// Copy the middle key of y to this node
keys[i] = y->keys[t - 1];
// Increment count of keys in this node
n = n + 1;
}
void BTreeNode::traverse()
{
std::queue<BTreeNode*> queue;
queue.push(this);
while (!queue.empty())
{
BTreeNode* current = queue.front();
queue.pop();
int i;
for (i = 0; i < n; i++)
{
if (leaf == false)
queue.push(current->C[i]);
cout << " " << current->keys[i] << endl;
}
if (leaf == false)
queue.push(current->C[i]);
}
}
// Driver program to test above functions
int main()
{
BTree t(4); // A B-Tree with minium degree 4
srand(29324);
for (int i = 0; i<200; i++)
{
int p = rand() % 10000;
t.insert(p);
}
cout << "Traversal of the constucted tree is ";
t.traverse();
int k = 6;
(t.search(k) != NULL) ? cout << "\nPresent" : cout << "\nNot Present";
k = 28;
(t.search(k) != NULL) ? cout << "\nPresent" : cout << "\nNot Present";
cout << "There are " << ComparisonCount << " comparison." << endl;
system("pause");
return 0;
}
最佳答案
您的遍历代码使用 this
的字段值就好像它们是 current
的值一样循环体中的节点。
你需要坚持current->
像这样在循环体中的成员引用前面(在标有“//*”的行中):
while (!queue.empty())
{
BTreeNode* current = queue.front();
queue.pop();
int i;
for (i = 0; i < current->n; i++) //*
{
if (current->leaf == false) //*
queue.push(current->C[i]);
cout << " " << current->keys[i] << endl;
}
if (current->leaf == false) //*
queue.push(current->C[i]);
}
这是一个强有力的指标,表明所有的东西都符合 current->
的要求。在现实中想要生活在它所在的功能中this
因此不需要明确命名。
与我们在此处获得的大多数调试请求相比,您的代码组织得更好,阅读起来也更愉快,但它仍然相当脆弱,并且包含相当多的臭味,例如 if (current->leaf == false)
而不是 if (not current->is_leaf)
.
当你把它变成工作状态时,你可能想把它发布到 Code Review 上;我敢肯定,在那里闲逛的经验丰富的编码人员可以为您提供很多关于如何改进代码的宝贵建议。
为了简化原型(prototype)设计和开发,我强烈建议如下:
std::vector<>
在原型(prototype)阶段代替裸阵列assert()
用于记录和检查局部不变量/Wall /Wextra
编译你的代码并清理它,以便它始终在没有警告的情况下进行编译此外,不要使用 int
不分青红皂白;不能变成负数的事物的基本类型是 unsigned
(节点度数、当前键数等)。
P.S.:通过固定键数的顺序来构建一致的 B 树会更容易(即对于某些 K,键数可以在 K 和 2*K 之间变化)。将顺序固定在指针的数量上会使事情变得更加困难,一个结果是“顺序”2 的键的数量(其中一个节点允许有 2 到 4 个指针)可以在 1 到 3 之间变化。对于大多数处理 B 树的人们将是一个相当出乎意料的景象!
关于c++ - btree 程序可能因指针而崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36819023/
我的数学需要一点帮助,这几天我的大脑很痛。 我为许多 btree 的不同大小的节点使用了一个池。如果 btrees 对于大树和小树的每个节点的键平均数量往往相同,那么效果会很好。但是,如果分布不同,我
任何人都可以帮助消除此段错误。我已经在这个代码上工作了一个星期仍然无法调试它。这段代码是Btree的实现。插入部分工作正常,但删除部分出现段错误。我无法调试它,有人可以帮忙吗? 我已经根据此链接给出了
任何人都可以帮助消除此段错误。我已经在这个代码上工作了一个星期仍然无法调试它。这段代码是Btree的实现。插入部分工作正常,但删除部分出现段错误。我无法调试它,有人可以帮忙吗? 我已经根据此链接给出了
我正在尝试按级别顺序打印一棵 b 树,但它一直在崩溃。我不确定真正的原因是什么,但我认为它崩溃是因为指针。我正在尝试使用我在网上找到的一个函数,该函数遍历每个级别并将其放入队列中并打印出来,但我遇到了
我一直在阅读@XenphYan 的回答 How does database indexing work? 但是有些事情我无法理解 Due to the fact that a number of re
我想要一个在一个字段上进行全文搜索然后在不同字段上进行排序的查询(想象一下搜索一些文本文档并按发布日期排序)。该表有大约 1700 万行,它们或多或少按日期均匀分布。这将在 webapp 请求/响应周
让我们看两个表: CREATE TABLE `orders_products` ( `ORDER_ID` int(10) unsigned NOT NULL, `PRODUCT_ID
我正在尝试创建一个为 BTree 设置动画的 Java 小程序。我有创建树的代码,但现在我正在尝试显示它。我认为最简单的方法是按级别打印,但我不知道该怎么做。下面的代码是我的节点的构造函数。另外,如果
我在维基百科上读到的: In B-trees, internal (non-leaf) nodes can have a variable number of child nodes within s
我一直在 slady.net 玩非常酷的 btree applet| .我无法理解特定行为。看看这个起始状态: alt text http://www.freeimagehosting.net/upl
您好,这是我的 SearchTree 类中的代码。Node* 是一个 m_info 类型为 int 的结构体,m_left(smaller nodes by info) 和 m_right(bigge
想象一下,每天都会有一位作者送给您一本新书。这本书正在编写中。他没有告诉您他更改或添加了什么。 您的工作是确定更改和添加内容,然后仅将这些内容传递给出版商(出版商没有时间每天阅读整本书) 为了解决这个
所以我有一个包含大约 2000 万个键值对的列表,我将数据以不同的方式存储在几个 MapDB 中,以查看它如何影响我的程序性能,并进行实验。 问题是,将 2000 万个键值对插入(以随机顺序)到 ma
我找不到关于 Postgres 文档的足够信息,但很想知道 btree 索引对于 postgres varchar 列是怎样的。 任何链接/解释都可能有帮助。 PS:对不起,这个问题含糊不清 最佳答案
我曾尝试查找类似的问题,但没有找到任何问题,除了有关同一列的两个索引的问题(一般而言)。 假设我们有一个包含 COL 列的表。该表(以及整个数据库)对于客户端来说是只读的(让我们假设它更新一次/每隔很
我正在尝试实现 BTree。我几乎已经完成了这棵树,并且对于较小的输入效果很好,这意味着我已经在内存中实现了这棵树。现在我想玩大输入,为此我必须将树写入文件。我不知道从哪里开始。我正在使用 Java,
我有一张 OrderDish 表,其中包含: create table OrderDish( email VARCHAR(80), nOrd integer, totalPri
如何解决这个问题? 我的表结构: CREATE TABLE IF NOT EXISTS `tbl_foster_network` ( `network_id` int(11) NOT NULL C
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
我尝试使用 Java 来实现教科书《算法简介》第三版中的算法,但没有取得很大成功。几乎每次我尝试实现它们时,我都会遇到大量错误,以至于我不确定作者自己是否尝试过实现他们自己的伪代码。但具体来说,在这种
我是一名优秀的程序员,十分优秀!