- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
以下是我在 C 中用于实现 B-Tree 的代码。该代码有时工作起来很奇怪,因为它有时会给出“Segmentation Fault”,如果我再次运行它并提供相同的输入值,它就可以正常工作。
也有这样的情况,我输入了 1 个值(例如 500),现在这应该是根值,但是代码还打印了两个空的 (nil) 子值。
而且所有这些行为都是不稳定的,并不是每次都会发生。它几乎不会发生第二次。我敢肯定,这与内存有关。有人可以建议我治疗。
提前致谢!!
#include <stdio.h>
#include <stdlib.h>
#define ORDER 4
struct node{
int n;
int keys[ORDER-1];
struct node *children[ORDER];
};
struct toReturn{
int result;
struct node* nodeReturn;
};
struct node* splitNodeAndAdd(struct node* , int );
struct node* insertInTree(struct node* , int );
struct toReturn* insertRecursive(struct node *, int );
struct node* splitNodeAndAddNode(struct node* , struct node* );
struct node* addElement(struct node *, int);
void printTree(struct node*, int);
void addAndSort(int *, int, int);
int checkLeaf(struct node* node);
int main(){
int inputElement = 0;
printf("Enter the element you want to add. Press 0 to quit\n");
scanf("%d",&inputElement);
struct node * root;
root = (struct node*) malloc(sizeof(struct node));
while(inputElement != 0){
root = addElement(root,inputElement);
printTree(root,0);
scanf("%d",&inputElement);
}
return 0;
}
struct node* addElement(struct node * rootNode, int inputElement){
if(rootNode->n == 0){
rootNode->keys[0] = inputElement;
rootNode->n += 1;
return rootNode;
}
else{
rootNode = insertInTree(rootNode,inputElement);
return rootNode;
}
}
struct node* insertInTree(struct node* node, int inputElement){
if(checkLeaf(node) == 0){ //It is leaf node.
if(node->n == ORDER - 1){
struct node * temp = node;
struct node *newRoot = (struct node*) malloc(sizeof(struct node));
node = newRoot;
newRoot->children[0] = temp;
newRoot = splitNodeAndAdd(newRoot,inputElement);
return newRoot;
} else{
addAndSort(node->keys,node->n,inputElement);
node->n += 1;
}
} else{
//recursive add . DO IT.
struct toReturn * returnedValue = insertRecursive(node,inputElement);
node = returnedValue->nodeReturn;
}
return node;
}
//Change split node and add before running. Won't work otherwise.
struct toReturn* insertRecursive(struct node *node, int inputElement){
if(checkLeaf(node) == 0){
if(node->n == ORDER - 1){
struct node * temp = node;
struct node *newRoot = (struct node*) malloc(sizeof(struct node));
node = newRoot;
newRoot->children[0] = temp;
newRoot = splitNodeAndAdd(newRoot,inputElement);
struct toReturn *value = (struct toReturn*) malloc(sizeof(struct toReturn));
value->result = 0;
value->nodeReturn = newRoot;
return value; // Also send parameter to show its done.
} else{
addAndSort(node->keys,node->n,inputElement);
node->n += 1;
struct toReturn *value = (struct toReturn*) malloc(sizeof(struct toReturn));
value->result = 1;
value->nodeReturn = node;
return value; // Also send parameter to show its done.
}
}
else{
int i = node->n;
i -= 1;
while( i >= 0 && inputElement < node->keys[i]){
i -= 1;
}
i += 1;
//Go to child node of this using 'i'
struct toReturn* returnedValue = insertRecursive(node->children[i],inputElement);
if(returnedValue->result == 0){
//Now we have a node in returnedValue to be added to current node.
//Check if current root is also going to be full.
if(node->n == ORDER - 1){
struct node* currentNode = node;
struct node* nodeToAdd = returnedValue->nodeReturn;
struct node* newRoot = (struct node*) malloc(sizeof(struct node));
newRoot->children[0] = currentNode;
newRoot = splitNodeAndAddNode(newRoot,nodeToAdd);
struct toReturn* temp = (struct toReturn*) malloc(sizeof(struct toReturn));
temp->result = 0;
temp->nodeReturn = newRoot;// whatever is returned from splitNodeAndAddNode.
return temp;
} else{
int k = i;
for(k = node->n; k>i; k--){
node->keys[k] = node->keys[k-1];
}
for(k = node->n + 1; k > i; k--){
node->children[k] = node->children[k-1];
}
node->keys[i] = returnedValue->nodeReturn->keys[0];
node->n += 1;
node->children[i] = returnedValue->nodeReturn->children[0];
node->children[i+1] = returnedValue->nodeReturn->children[1];
returnedValue->result = 1;
returnedValue->nodeReturn = node;
}
}else{
node->children[i] = returnedValue->nodeReturn;
returnedValue->nodeReturn = node;
}
return returnedValue;
}
}
struct node* splitNodeAndAddNode(struct node* node, struct node* toAdd){
struct node* leftChild = node->children[0];
struct node* allChildren[ORDER+1];
int i = 0;
for(i = 0; i<ORDER; i++){
allChildren[i] = leftChild->children[i];
}
int childrenCount = 0;
int j = 0;
struct node* rightChild = (struct node*) malloc(sizeof(struct node));
int array[ORDER];
for(i=0; i<ORDER - 1; i++){
array[i] = leftChild->keys[i];
}
addAndSort(array,ORDER-1,toAdd->keys[0]);
int addedPosition = 0;
for(i=0; i<ORDER; i++){
if(array[i] == toAdd->keys[0]){
addedPosition = i;
}
}
for(j=ORDER-1; j>= addedPosition; j--){
allChildren[j+1] = allChildren[j];
}
allChildren[addedPosition] = toAdd->children[0];
allChildren[addedPosition+1] = toAdd->children[1];
int median = ORDER / 2;
node->keys[0] = array[median];
node->n += 1;
//add left and right child of node.
for(i = 0; i<median; i++){
leftChild->keys[i] = array[i];
leftChild->children[i] = allChildren[childrenCount];
childrenCount++;
}
leftChild->children[i] = allChildren[childrenCount];
childrenCount++;
leftChild->n = median;
for(i = median; i<ORDER-1; i++){
leftChild->keys[i] = 0;
}
int k = 0;
for(i = median+1; i<ORDER; i++){
rightChild->keys[k] = array[i];
rightChild->n += 1;
rightChild->children[k] = allChildren[childrenCount];
childrenCount++;
k++;
}
rightChild->children[k] = allChildren[childrenCount];
childrenCount++;
node->children[0] = leftChild;
node->children[1] = rightChild;
return node;
}
struct node* splitNodeAndAdd(struct node* rootNode, int inputElement){
struct node* leftChild = rootNode->children[0];
struct node* rightChild = (struct node*) malloc(sizeof(struct node));
int i = 0;
int j = 0;
int array[ORDER];
for(i =0; i<ORDER-1;i++){
array[i] = leftChild->keys[i];
}
addAndSort(array,ORDER-1,inputElement);
int medianIndex = 0;
for(i = 0; i<ORDER; i++){
if(inputElement == array[i]){
medianIndex = i;
break;
}
}
int median = ORDER / 2;
for(j=0; j<median; j++){
leftChild->keys[j] = array[j];
}
for(j=median; j<ORDER-1;j++){
leftChild->keys[j] = 0;
}
leftChild->n = median;
rootNode->keys[0] = array[median];
rootNode->n += 1;
int k = 0;
for(j= median+1; j<ORDER; j++){
rightChild->keys[k] = array[j];
rightChild->n += 1;
k++;
}
rootNode->children[0] = leftChild;
rootNode->children[1] = rightChild;
//Have to add all children if this is not leaf node.
//Have to change rootNode[0] to long term picture.
return rootNode;
}
void printTree(struct node *a, int level){
printf("%d : ",level);
for(int i=0; i<a->n; i++){
printf("%d ",a->keys[i]);
}
printf("\n");
if(checkLeaf(a) == 1){
for(int i=0; i <= a->n ; i++){
printTree(a->children[i],level+1);
}
}else {
return;
}
}
int checkLeaf(struct node* node){
int i = 0;
if(node->children[i] != NULL){
return 1;
}
return 0;
}
void addAndSort(int *array, int elementCount, int inputElement){
int i = 0;
for(i = elementCount-1; i >=0 && array[i] > inputElement; i--){ //else find the best
array[i+1] = array[i];
}
array[i+1] = inputElement;
}
最佳答案
正如我在评论中所说,需要审查的代码太多,特别是当您没有给我们足够的提示从哪里开始看问题。
Can you elaborate a bit on allocated memory for the root node in main, you didn't initialize it, I am not sure if I follow. I think I reserved memory, then why is it causing such erratic behaviour. I presume it takes garbage value sometimes, am I right ?
我简要地查看了代码,发现了相同的模式。你刚才分配内存,但在读取内容之前不初始化内存分配的内存。这会产生未定义的行为以及你是什么观察,有时工作,有时不工作,这是一个经典的标志未定义的行为。由于未定义行为的性质,它非常很难,有时几乎不可能预测会发生什么。在多数情况下您需要做的就是找到未定义行为的来源。
在你的情况下,我做的第一件事就是查看你的 malloc
调用,看看在哪里你初始化内存。你没有做到这一点,所以我停止寻找更多错误,因为这很可能是您所有问题的根源。
当你用malloc
分配内存时,你只能从操作系统,不能保证内存在任何初始化方式,这意味着内存具有随机值。你在 main
root = (struct node*) malloc(sizeof(struct node));
while(inputElement != 0) {
root = addElement(root,inputElement);
...
}
然后 addElement
执行:
struct node* addElement(struct node * rootNode, int inputElement){
if(rootNode->n == 0){
rootNode->keys[0] = inputElement;
...
} else {
rootNode = insertInTree(rootNode,inputElement);
...
}
}
如您所见,您已经为 root
节点分配了内存,但是 root->n
不是初始化后,它的值是随机的,可能是 0,但也可能是 24 或-12389。所以你的代码已经在做一些不可预测的事情,因为只是查看代码,您无法知道 rootNode->keys[0] = inputElement;
被执行,或者 rootNode = insertInTree(rootNode,inputElement);
。那就是未定义行为的性质。在 rootNode->n
为 0 的幸运情况下,功能可能会正常工作。
你必须做
root = malloc(sizeof *root);
if(root == NULL)
{
fprintf(stderr, "No memory left\n");
return 1;
}
// initializing the memory
root->n = 0;
memset(root->keys, 0, sizeof root->keys / sizeof root->keys[0]);
for(size_t i = 0; i < sizeof root->children / sizeof root->children[0]; ++i)
root->children[i] = NULL;
while(inputElement != 0) {
root = addElement(root,inputElement);
...
}
malloc
malloc
/realloc
malloc
/realloc
sizeof(struct node)
,改用sizeof *root
,使代码更健壮。free()
内存。free()
内存我还建议您创建一个函数,返回一个新的分配+初始化节点,否则您将一次又一次地重复相同的代码。这适用于您所有的 malloc
调用。
当然,在您的情况下,可以通过使用 calloc
来避免初始化而不是 malloc
。 calloc
的工作方式类似于 malloc
但它还会设置分配的内存为 0。这是一个很棒的功能,因为如果您的内存必须用 0 和 NULL
指针1 初始化,这样可以节省很多时间和你可以做
root = calloc(1, sizeof *root);
if(root == NULL)
{
fprintf(stderr, "No memory left\n");
return 1;
}
// initializing the memory with 0 is not needed
// anymore as calloc takes care of that
while(inputElement != 0) {
root = addElement(root,inputElement);
...
}
在整个代码中进行此更改,这将消除许多未定义行为的来源。这并不意味着你所有的问题都是虽然解决了。
脚注
1传说说存在 NULL
的架构未解释为 0,因此使用 calloc
初始化 NULL
指针可能会失败。但我敢说任何人都可以找到人们使用的任何商业上成功的架构这些天在这种情况下富有成效。
关于c - C 中段错误的不稳定行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49962451/
如果输入稳定,我想触发 AJAX 请求(以便不在每个新字符后发送请求)。我尝试了以下方法: $('#input').keyup(function(){ // Get the value when
我读到,我们可以插入以将选择排序更改为稳定排序,而不是交换。我在网上得到了以下相同的实现。 void selection ( int a[], int n ) { while ( --n >
我正在尝试创建一个非常节省空间的不寻常的关联数组实现,我需要一个满足以下所有条件的排序算法: 稳定(不改变具有等键的元素的相对顺序。) 就地或几乎就地(O(log n) 堆栈很好,但没有 O(n) 空
我有一个节点的无线网状网络,每个节点都能够向其邻居报告其“距离”,以(简化的)信号强度来衡量。节点在地理上位于 3d 空间中,但由于 radio 干扰,节点之间的距离不需要在三角(三角?)上一致。即,
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我正在实现一个玩具调度程序,它读取进程规范(例如到达时间、总运行时间)的输入文件,然后根据随机 io/cpu 突发调度进程。 文件格式 Arrival time, total CPU time, CP
我正在使用 JRedis 的同步实现,但我打算切换到异步方式与 Redis 服务器通信。 但在此之前我想问一下社区 JRedisFuture 是否实现了 alphazero 的 jredis对于生产使
我们正在为我们的公司构建一个RESTful API,它将提供XML,JSON和可能的其他内容类型。 我的团队正在寻找一个框架(按优先顺序排列): 有据可查 理想的情况下,它具有出色的教程以及繁荣的社区
我的网站希望用户上传他们的照片...但我该如何保护我们的服务器免受伤害?只允许 JPG 应该可以避免病毒问题,但如果有人选择 10Gb 文件怎么办 - 这会减慢整个网站的速度吗? 我们使用的是经典 A
关闭。这个问题需要更多 focused .它目前不接受答案。 想改进这个问题?更新问题,使其仅关注一个问题 editing this post . 8 个月前关闭。 Improve this ques
据我所知,paintEvent() 是在 QApplication 对象的“主循环”中执行的,并且可以为其内部系统任务花费时间,从而延迟执行排队槽或其他事件。 但是,如果我需要播放非常流畅的动画并且我
我想对随机排序的 ActiveRecord 模型列表(来自 MySQL 数据库的行)进行分页。 但是,这种随机化需要在每个 session 的基础上持续存在,以便访问该网站的其他人也会收到一个随机的、
在 Flutter Web 稳定后,我尝试按照文档中给出的说明将我的 Flutter Mobile 应用程序转换为 Flutter Web。一切都很好,但这里的问题是 Web 上的文本不可选择!我刚刚
我正在尝试制作一个包含 Nginx stable 最新使用 vts 模块编译的 dockerfile .... 我遇到了一个大问题,当我放入将下载的 docker 文件时我找不到一些汽车链接安装最新的
已结束。此问题正在寻求书籍、工具、软件库等的推荐。它不满足Stack Overflow guidelines 。目前不接受答案。 我们不允许提出寻求书籍、工具、软件库等推荐的问题。您可以编辑问题,以便
我正在使用以下命令将 Airflow 部署到 Kubernetes 中:https://github.com/helm/charts/tree/master/stable/airflow 我正在尝
我已经安装了本地测试elasticsearch和logstash,它们似乎看不到本地es-知道在集群/ ns中如何看到es吗? helm repo add elastic https://helm.e
我最近加入了一家公司,担任发布工程师,在这里,大量的开发团队以各种语言开发了众多服务,应用程序和Web应用程序,它们之间具有各种相互依赖性。 我正在尝试找到一种简化并最好自动发布的方法。当前,发布团队
已结束。此问题正在寻求书籍、工具、软件库等的推荐。它不满足Stack Overflow guidelines 。目前不接受答案。 我们不允许提出寻求书籍、工具、软件库等推荐的问题。您可以编辑问题,以便
我想知道一种在 Windows 上使用简单批处理和 ffmpeg 稳定 goPro 视频的简单方法。 最佳答案 1) 在您的计算机上安装 ffmpeg:按照 steps 安装 2) 在您要处理的视频旁
我是一名优秀的程序员,十分优秀!