📄 btree.c
字号:
/* 删除数据函数 */
void delete_f(void)
{
int del_id, position; /* position记录删除数据在节点中的位置 */
char ans;
Node_type *node;
puts("\n ---- DELETE ----");
printf(" Please enter ID number: ");
scanf("%d", &del_id);
node = search(del_id, root, &position);
if(node != NULL)
{
printf(" Are you sure? (Y/N): ");
ans = getche();
printf("\n");
ans = toupper(ans);
if(ans == 'Y')
root = removing(del_id, root);
}
else
puts(" ID number not found!!");
}
/* 将数据从B-tree中删除,若删除后节点内数据笔数为0,则一并删除该节点 */
Node_type *removing(int del_id, Node_type *node)
{
Node_type *p;
if(!deldata(del_id, node));
else
if(node->count == 0)
{
p = node;
node = node->link[0];
free(p);
}
return node;
}
/* 将数据从B-tree中移除,若删除失败则传回0,否则传回数据在节点中所在位置 */
int deldata(int del_id, Node_type *p)
{
int k;
int found;
if(p == NULL)
return 0;
else
{
if((found = searchnode(del_id, p, &k)) != 0)
{
if(p->link[k-1])
{
replace(p, k);
if(!(found = deldata(p->id[k], p->link[k])))
printf(" Key not found");
}
else
move(p,k);
}
else
found = deldata(del_id, p->link[k]);
if(p->link[k] != NULL)
{
if(p->link[k]->count < MIN)
restore(p, k);
}
return found;
}
}
/* 将节点中的数据从k的位置逐一左移 */
void move(Node_type *p, int k)
{
int i;
for(i = k+1; i <= p->count; i++)
{
p->id[i-1] = p->id[i];
strcpy(p->name[i-1], p->name[i]);
p->score[i-1] = p->score[i];
p->link[i-1] = p->link[i];
}
p->count--;
}
/* 寻找删除非叶时的替代数据 */
void replace(Node_type *p, int k)
{
Node_type *q;
for(q = p->link[k]; q->link[0]; q = q->link[0]);
p->id[k] = q->id[1];
strcpy(p->name[k], q->name[1]);
p->score[k] = q->score[1];
}
/* 数据删除后,重新调整为B-tree */
void restore(Node_type *p, int k)
{
if(k == 0) /* 删除数据为节点中的第一笔数据 */
{
if(p->link[1]->count > MIN)
getright(p, 1);
else
combine(p, 1);
}
else
if(k == p->count) /* 删除数据为节点中的最后一笔数据 */
{
if(p->link[k-1]->count > MIN)
getleft(p, k);
else
combine(p, k);
}
else /* 删除数据为节点中其它位置的数据 */
if(p->link[k-1]->count > MIN)
getleft(p, k);
else
if(p->link[k+1]->count > MIN)
getright(p, k+1);
else
combine(p, k);
}
/* 向左兄弟节点借数据时,做数据右移的动作 */
void getleft(Node_type *p, int k)
{
int c;
Node_type *t;
t = p->link[k];
for(c = t->count; c > 0; c--)
{
t->id[c+1] = t->id[c];
strcpy(t->name[c+1], t->name[c]);
t->score[c+1] = t->score[c];
t->link[c+1] = t->link[c];
}
t->link[1] = t->link[0];
t->count++;
t->id[1] = p->id[k];
strcpy(t->name[1], p->name[k]);
t->score[1] = p->score[k];
t = p->link[k-1];
p->id[k] = t->id[t->count];
strcpy(p->name[k], t->name[t->count]);
p->score[k] = t->score[t->count];
p->link[k]->link[0] = t->link[t->count];
t->count--;
}
/* 向右兄弟节点借数据时,做左移的动作 */
void getright(Node_type *p, int k)
{
int c;
Node_type *t;
t = p->link[k-1];
t->count++;
t->id[t->count] = p->id[k];
strcpy(t->name[t->count], p->name[k]);
t->score[t->count] = p->score[k];
t->link[t->count] = p->link[k]->link[0];
t = p->link[k];
p->id[k] = t->id[1];
strcpy(p->name[k], t->name[1]);
p->score[k] = t->score[1];
t->link[0] = t->link[1];
t->count--;
for(c = 1; c <= t->count; c++)
{
t->id[c] = t->id[c+1];
strcpy(t->name[c], t->name[c+1]);
t->score[c] = t->score[c+1];
t->link[c] = t->link[c+1];
}
}
/* 将三个节点中的数据合并至一个节点中 */
void combine(Node_type *p, int k)
{
int c;
Node_type *l, *q;
q = p->link[k];
l = p->link[k-1];
l->count++;
l->id[l->count] = p->id[k];
strcpy(l->name[l->count], p->name[k]);
l->score[l->count] = p->score[k];
l->link[l->count] = q->link[0];
for(c = 1; c <= q->count; c++)
{
l->count++;
l->id[l->count] = q->id[c];
strcpy(l->name[l->count], q->name[c]);
l->score[l->count] = q->score[c];
l->link[l->count] = q->link[c];
}
for(c = k; c < p->count; c++)
{
p->id[c] = p->id[c+1];
strcpy(p->name[c], p->name[c+1]);
p->score[c] = p->score[c+1];
p->link[c] = p->link[c+1];
}
p->count--;
free(q);
}
/* 数据输出函数 */
void list_f(void)
{
puts("\n ---- LIST ----");
puts(" *******************************");
puts(" ID NAME SCORE");
puts(" =============================");
show(root);
puts(" *******************************");
}
/* 以递归方式输出节点数据,输出数据采中序法,nd为欲输出数据的节点 */
void show(Node_type *nd)
{
if(nd != NULL)
{
if(nd->count > 0)
{
if(nd->count == 1)
{
show(nd->link[0]);
printf(" %-6d %-10s %4d\n",
nd->id[1], nd->name[1], nd->score[1]);
show(nd->link[1]);
}
else
if(nd->count == 2)
{
show(nd->link[0]);
printf(" %-6d %-10s %4d\n",
nd->id[1], nd->name[1], nd->score[1]);
show(nd->link[1]);
printf(" %-6d %-10s %4d\n",
nd->id[2], nd->name[2], nd->score[2]);
show(nd->link[2]);
}
}
}
}
/* 查询某一特定数据 */
void query_f(void)
{
int query_id, position;
Node_type *quenode;
puts("\n ---- QUERY ----");
printf(" Please enter ID number: ");
scanf("%d", &query_id);
quenode = search(query_id, root, &position);
if(quenode != NULL)
{
printf(" ID number: %d\n", quenode->id[position]);
printf(" Name: %s\n", quenode->name[position]);
printf(" Score: %d\n", quenode->score[position]);
}
else
puts(" ID number not found!!");
}
/* 将B-tree中的数据储存到文件中 */
void save(Node_type *node, FILE *outfile)
{
if(node->count != 0)
{
if(node->count == 1)
{
save(node->link[0], outfile);
fprintf(outfile, " %6d %10s %4d\n", node->id[1], node->name[1],
node->score[1]);
save(node->link[1], outfile);
}
else
if(node->count == 2)
{
save(node->link[0], outfile);
fprintf(outfile, " %6d %10s %4d\n", node->id[1], node->name[1],
node->score[1]);
save(node->link[1], outfile);
fprintf(outfile, " %6d %10s %4d\n", node->id[2], node->name[2],
node->score[2]);
save(node->link[2], outfile);
}
}
}
/* 结束本系统 */
void quit(void)
{
printf("\n Thanks for using, bye bye!!");
exit(0);
}
/* 查找某一键值所在节点,target为查找键值,传回值为target所在节点指针,若没有找
到则传回NULL */
Node_type *search(int target, Node_type *node, int *targetpos)
{
if(node == NULL)
return NULL;
else
if(searchnode(target, node, targetpos))
return node;
else
return search(target, node->link[*targetpos], targetpos);
}
/* 查找某一键值在节点中的位置,target为查找键值,k记录键值所在位置,传回0表
示查找失败,传回1表示查找成功 */
int searchnode(int target, Node_type *p, int *k)
{
if(target < p->id[1])
{
*k = 0;
return 0;
}
else
{
*k = p->count;
while((target < p->id[*k]) && *k > 1)
(*k)--;
if(target == p->id[*k])
return 1;
else
return 0;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -