Btree算法的C语言实现
btree.h
//实现对order序(阶)的B-TREE结构基本操作的封装。
//查找:search,插入:insert,删除:remove。
//创建:create,销毁:destory,打印:print。
#ifndef BTREE_H
#define BTREE_H #ifdef __cplusplus
extern "C" {
#endif ////* 定义m序(阶)B 树的最小度数BTree_D=ceil(m)*/
/// 在这里定义每个节点中关键字的最大数目为:2 * BTree_D - 1,即序(阶):2 * BTree_D.
#define BTree_D 2
#define ORDER (BTree_D * 2) //定义为4阶B-tree,2-3-4树。最简单为3阶B-tree,2-3树。
//#define ORDER (BTree_T * 2-1) //最简单为3阶B-tree,2-3树。 typedef int KeyType;
typedef struct BTNode{
int keynum; /// 结点中关键字的个数,keynum <= BTree_N
KeyType key[ORDER-1]; /// 关键字向量为key[0..keynum - 1]
struct BTNode* child[ORDER]; /// 孩子指针向量为child[0..keynum]
bool isLeaf; /// 是否是叶子节点的标志
}BTNode; typedef BTNode* BTree; ///定义BTree ///给定数据集data,创建BTree。
void BTree_create(BTree* tree, const KeyType* data, int length); ///销毁BTree,释放内存空间。
void BTree_destroy(BTree* tree); ///在BTree中插入关键字key。
void BTree_insert(BTree* tree, KeyType key); ///在BTree中移除关键字key。
void BTree_remove(BTree* tree, KeyType key); ///深度遍历BTree打印各层结点信息。
void BTree_print(const BTree tree, int layer=1); /// 在BTree中查找关键字 key,
/// 成功时返回找到的节点的地址及 key 在其中的位置 *pos
/// 失败时返回 NULL 及查找失败时扫描到的节点位置 *pos
BTNode* BTree_search(const BTree tree, int key, int* pos); #ifdef __cplusplus
}
#endif #endif
btree.c
//实现对order序(阶)的B-TREE结构基本操作的封装。
//查找:search,插入:insert,删除:remove。
//创建:create,销毁:destory,打印:print。
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "btree.h" //#define max(a, b) (((a) > (b)) ? (a) : (b))
#define cmp(a, b) ( ( ((a)-(b)) >= (0) ) ? (1) : (0) ) //比较a,b大小
#define DEBUG_BTREE // 模拟向磁盘写入节点
void disk_write(BTNode* node)
{
//打印出结点中的全部元素,方便调试查看keynum之后的元素是否为0(即是否存在垃圾数据);而不是keynum个元素。
printf("向磁盘写入节点");
for(int i=0;i<ORDER-1;i++){
printf("%c",node->key[i]);
}
printf("\n");
} // 模拟从磁盘读取节点
void disk_read(BTNode** node)
{
//打印出结点中的全部元素,方便调试查看keynum之后的元素是否为0(即是否存在垃圾数据);而不是keynum个元素。
printf("向磁盘读取节点");
for(int i=0;i<ORDER-1;i++){
printf("%c",(*node)->key[i]);
}
printf("\n");
} // 按层次打印 B 树
void BTree_print(const BTree tree, int layer)
{
int i;
BTNode* node = tree; if (node) {
printf("第 %d 层, %d node : ", layer, node->keynum); //打印出结点中的全部元素,方便调试查看keynum之后的元素是否为0(即是否存在垃圾数据);而不是keynum个元素。
for (i = 0; i < ORDER-1; ++i) {
//for (i = 0; i < node->keynum; ++i) {
printf("%c ", node->key[i]);
} printf("\n"); ++layer;
for (i = 0 ; i <= node->keynum; i++) {
if (node->child[i]) {
BTree_print(node->child[i], layer);
}
}
}
else {
printf("树为空。\n");
}
} // 结点node内对关键字进行二分查找。
int binarySearch(BTNode* node, int low, int high, KeyType Fkey)
{
int mid;
while (low<=high)
{
mid = low + (high-low)/2;
if (Fkey<node->key[mid])
{
high = mid-1;
}
if (Fkey>node->key[mid])
{
low = mid+1;
}
if (Fkey==node->key[mid])
{
return mid;//返回下标。
}
}
return 0;//未找到返回0.
} /***************************************************************************************
将分裂的结点中的一半元素给新建的结点,并且将分裂结点中的中间关键字元素上移至父节点中。
parent 是一个非满的父节点
node 是 tree 孩子表中下标为 index 的孩子节点,且是满的,需分裂。
分裂确保有序的情况下是均衡的
*******************************************************************/
void BTree_split_child(BTNode* parent, int index, BTNode* node)
{
#ifdef DEBUG_BTREE
printf("BTree_split_child!\n");
#endif
assert(parent && node);
int i; // 创建新节点,存储 node 中后半部分的数据
BTNode* newNode = (BTNode*)calloc(sizeof(BTNode), 1);
if (!newNode) {
printf("Error! out of memory!\n");
return;
} newNode->isLeaf = node->isLeaf;
newNode->keynum = BTree_D - 1; // 拷贝 node 后半部分关键字,然后将node后半部分置为0。
for (i = 0; i < newNode->keynum; ++i){
newNode->key[i] = node->key[BTree_D + i];
node->key[BTree_D + i] = 0;
} // 如果 node 不是叶子节点,拷贝 node 后半部分的指向孩子节点的指针,然后将node后半部分指向孩子节点的指针置为NULL。
if (!node->isLeaf) {
for (i = 0; i < BTree_D; i++) {
newNode->child[i] = node->child[BTree_D + i];
node->child[BTree_D + i] = NULL;
}
} // 将 node 分裂出 newNode 之后,里面的数据减半
node->keynum = BTree_D - 1; // 调整父节点中的指向孩子的指针和关键字元素。分裂时父节点增加指向孩子的指针和关键元素。
for (i = parent->keynum; i > index; --i) {
parent->child[i + 1] = parent->child[i];
} parent->child[index + 1] = newNode; for (i = parent->keynum - 1; i >= index; --i) {
parent->key[i + 1] = parent->key[i];
} parent->key[index] = node->key[BTree_D - 1];
++parent->keynum; node->key[BTree_D - 1] = 0; // 写入磁盘
disk_write(parent);
disk_write(newNode);
disk_write(node);
} void BTree_insert_nonfull(BTNode* node, KeyType key)
{
assert(node); int i; // 节点是叶子节点,直接插入,如果比其他值小,那么移动其他值
if (node->isLeaf) {
i = node->keynum - 1;
while (i >= 0 && key < node->key[i]) {
node->key[i + 1] = node->key[i];
--i;
} node->key[i + 1] = key;
++node->keynum; // 写入磁盘
disk_write(node);
} // 节点是内部节点
else {
/* 查找插入的位置*/
i = node->keynum - 1;
while (i >= 0 && key < node->key[i]) {
--i;
} ++i; // 从磁盘读取孩子节点
disk_read(&node->child[i]); // 如果该孩子节点已满,分裂调整值
if (node->child[i]->keynum == (ORDER-1)) {
BTree_split_child(node, i, node->child[i]);
// 如果待插入的关键字大于该分裂结点中上移到父节点的关键字,在该关键字的右孩子结点中进行插入操作。
if (key > node->key[i]) {
++i;
}
}
BTree_insert_nonfull(node->child[i], key);
}
} void BTree_insert(BTree* tree, KeyType key)
{
#ifdef DEBUG_BTREE
printf("BTree_insert:\n");
#endif
BTNode* node;
BTNode* root = *tree; // 树为空
if (NULL == root) {
root = (BTNode*)calloc(sizeof(BTNode), 1);
if (!root) {
printf("Error! out of memory!\n");
return;
}
root->isLeaf = true;
root->keynum = 1;
root->key[0] = key; *tree = root; // 写入磁盘
disk_write(root); return;
} // 根节点已满,插入前需要进行分裂调整
if (root->keynum == (ORDER-1)) {
// 产生新节点当作根
node = (BTNode*)calloc(sizeof(BTNode), 1);
if (!node) {
printf("Error! out of memory!\n");
return;
} *tree = node;
node->isLeaf = false;
node->keynum = 0;
node->child[0] = root; BTree_split_child(node, 0, root); BTree_insert_nonfull(node, key);
} // 根节点未满,在当前节点中插入 key
else {
BTree_insert_nonfull(root, key);
}
}
// 对 tree 中的节点 node 进行合并孩子节点处理.
// 注意:孩子节点的 keynum 必须均已达到下限,即均等于 BTree_D - 1
// 将 tree 中索引为 index 的 key 下移至左孩子结点中,
// 将 node 中索引为 index + 1 的孩子节点合并到索引为 index 的孩子节点中,右孩子合并到左孩子结点中。
// 并调相关的 key 和指针。
void BTree_merge_child(BTree* tree, BTNode* node, int index)
{
#ifdef DEBUG_BTREE
printf("BTree_merge_child!\n");
#endif
assert(tree && node && index >= 0 && index < node->keynum); int i; KeyType key = node->key[index];
BTNode* leftChild = node->child[index];
BTNode* rightChild = node->child[index + 1]; assert(leftChild && leftChild->keynum == BTree_D - 1
&& rightChild && rightChild->keynum == BTree_D - 1); // 将 node中关键字下标为index 的 key 下移至左孩子结点中,该key所对应的右孩子结点指向node的右孩子结点中的第一个孩子。
leftChild->key[leftChild->keynum] = key;
leftChild->child[leftChild->keynum + 1] = rightChild->child[0];
++leftChild->keynum; // 右孩子的元素合并到左孩子结点中。
for (i = 0; i < rightChild->keynum; ++i) {
leftChild->key[leftChild->keynum] = rightChild->key[i];
leftChild->child[leftChild->keynum + 1] = rightChild->child[i + 1];
++leftChild->keynum;
} // 在 node 中下移的 key后面的元素前移
for (i = index; i < node->keynum - 1; ++i) {
node->key[i] = node->key[i + 1];
node->child[i + 1] = node->child[i + 2];
}
node->key[node->keynum - 1] = 0;
node->child[node->keynum] = NULL;
--node->keynum; // 如果根节点没有 key 了,并将根节点调整为合并后的左孩子节点;然后删除释放空间。
if (node->keynum == 0) {
if (*tree == node) {
*tree = leftChild;
} free(node);
node = NULL;
} free(rightChild);
rightChild = NULL;
} void BTree_recursive_remove(BTree* tree, KeyType key)
{
// B-数的保持条件之一:
// 非根节点的内部节点的关键字数目不能少于 BTree_D - 1 int i, j, index;
BTNode *root = *tree;
BTNode *node = root; if (!root) {
printf("Failed to remove %c, it is not in the tree!\n", key);
return;
} // 结点中找key。
index = 0;
while (index < node->keynum && key > node->key[index]) {
++index;
} /*======================含有key的当前结点时的情况====================
node:
index of Key: i-1 i i+1
+---+---+---+---+
* key *
+---+---+---+---+---+
/ \
index of Child: i i+1
/ \
+---+---+ +---+---+
* * * *
+---+---+---+ +---+---+---+
leftChild rightChild
============================================================*/
/*一、结点中找到了关键字key的情况.*/
BTNode *leftChild, *rightChild;
KeyType leftKey, rightKey;
if (index < node->keynum && node->key[index] == key) {
/* 1,所在节点是叶子节点,直接删除*/
if (node->isLeaf) {
for (i = index; i < node->keynum-1; ++i) {
node->key[i] = node->key[i + 1];
//node->child[i + 1] = node->child[i + 2];叶子节点的孩子结点为空,无需移动处理。
}
node->key[node->keynum-1] = 0;
//node->child[node->keynum] = NULL;
--node->keynum; if (node->keynum == 0) {
assert(node == *tree);
free(node);
*tree = NULL;
} return;
}
/*2.选择脱贫致富的孩子结点。*/
// 2a,选择相对富有的左孩子结点。
// 如果位于 key 前的左孩子结点的 key 数目 >= BTree_D,
// 在其中找 key 的左孩子结点的最后一个元素上移至父节点key的位置。
// 然后在左孩子节点中递归删除元素leftKey。
else if (node->child[index]->keynum >= BTree_D) {
leftChild = node->child[index];
leftKey = leftChild->key[leftChild->keynum - 1];
node->key[index] = leftKey; BTree_recursive_remove(&leftChild, leftKey);
}
// 2b,选择相对富有的右孩子结点。
// 如果位于 key 后的右孩子结点的 key 数目 >= BTree_D,
// 在其中找 key 的右孩子结点的第一个元素上移至父节点key的位置
// 然后在右孩子节点中递归删除元素rightKey。
else if (node->child[index + 1]->keynum >= BTree_D) {
rightChild = node->child[index + 1];
rightKey = rightChild->key[0];
node->key[index] = rightKey; BTree_recursive_remove(&rightChild, rightKey);
}
/*左右孩子结点都刚脱贫。删除前需要孩子结点的合并操作*/
// 2c,左右孩子结点只包含 BTree_D - 1 个节点,
// 合并是将 key 下移至左孩子节点,并将右孩子节点合并到左孩子节点中,
// 删除右孩子节点,在父节点node中移除 key 和指向右孩子节点的指针,
// 然后在合并了的左孩子节点中递归删除元素key。
else if (node->child[index]->keynum == BTree_D - 1
&& node->child[index + 1]->keynum == BTree_D - 1){
leftChild = node->child[index]; BTree_merge_child(tree, node, index); // 在合并了的左孩子节点中递归删除 key
BTree_recursive_remove(&leftChild, key);
}
} /*======================未含有key的当前结点时的情况====================
node:
index of Key: i-1 i i+1
+---+---+---+---+
* keyi *
+---+---+---+---+---+
/ | \
index of Child: i-1 i i+1
/ | \
+---+---+ +---+---+ +---+---+
* * * * * *
+---+---+---+ +---+---+---+ +---+---+---+
leftSibling Child rightSibling
============================================================*/
/*二、结点中未找到了关键字key的情况.*/
else {
BTNode *leftSibling, *rightSibling, *child;
// 3. key 不在内节点 node 中,则应当在某个包含 key 的子节点中。
// key < node->key[index], 所以 key 应当在孩子节点 node->child[index] 中
child = node->child[index];
if (!child) {
printf("Failed to remove %c, it is not in the tree!\n", key);
return;
}
/*所需查找的该孩子结点刚脱贫的情况*/
if (child->keynum == BTree_D - 1) {
leftSibling = NULL;
rightSibling = NULL; if (index - 1 >= 0) {
leftSibling = node->child[index - 1];
} if (index + 1 <= node->keynum) {
rightSibling = node->child[index + 1];
}
/*选择致富的相邻兄弟结点。*/
// 3a,如果所在孩子节点相邻的兄弟节点中有节点至少包含 BTree_D 个关键字
// 将 node 的一个关键字key[index]下移到 child 中,将相对富有的相邻兄弟节点中一个关键字上移到
// node 中,然后在 child 孩子节点中递归删除 key。 请看M
if ((leftSibling && leftSibling->keynum >= BTree_D)
|| (rightSibling && rightSibling->keynum >= BTree_D)) {
int richR = 0;
if(rightSibling) richR = 1;
if(leftSibling && rightSibling) {
richR = cmp(rightSibling->keynum,leftSibling->keynum);
}
if (rightSibling && rightSibling->keynum >= BTree_D && richR) {
//相邻右兄弟相对富有,则该孩子先向父节点借一个元素,右兄弟中的第一个元素上移至父节点所借位置,并进行相应调整。
child->key[child->keynum] = node->key[index];
child->child[child->keynum + 1] = rightSibling->child[0];
++child->keynum; node->key[index] = rightSibling->key[0]; for (j = 0; j < rightSibling->keynum - 1; ++j) {//元素前移
rightSibling->key[j] = rightSibling->key[j + 1];
rightSibling->child[j] = rightSibling->child[j + 1];
}
rightSibling->key[rightSibling->keynum-1] = 0;
rightSibling->child[rightSibling->keynum-1] = rightSibling->child[rightSibling->keynum];
rightSibling->child[rightSibling->keynum] = NULL;
--rightSibling->keynum;
}
else {//相邻左兄弟相对富有,则该孩子向父节点借一个元素,左兄弟中的最后元素上移至父节点所借位置,并进行相应调整。
for (j = child->keynum; j > 0; --j) {//元素后移
child->key[j] = child->key[j - 1];
child->child[j + 1] = child->child[j];
}
child->child[1] = child->child[0];
child->child[0] = leftSibling->child[leftSibling->keynum];
child->key[0] = node->key[index - 1];
++child->keynum; node->key[index - 1] = leftSibling->key[leftSibling->keynum - 1]; leftSibling->key[leftSibling->keynum - 1] = 0;
leftSibling->child[leftSibling->keynum] = NULL; --leftSibling->keynum;
}
}
/*相邻兄弟结点都刚脱贫。删除前需要兄弟结点的合并操作,*/
// 3b, 如果所在孩子节点相邻的兄弟节点都只包含 BTree_D - 1 个关键字,
// 将 child 与其一相邻节点合并,并将 node 中的一个关键字下降到合并节点中,
// 再在 node 中删除那个关键字和相关指针,若 node 的 key 为空,删之,并调整根为合并结点。
// 最后,在相关孩子节点child中递归删除 key。
else if ((!leftSibling || (leftSibling && leftSibling->keynum == BTree_D - 1))
&& (!rightSibling || (rightSibling && rightSibling->keynum == BTree_D - 1))) {
if (leftSibling && leftSibling->keynum == BTree_D - 1) { BTree_merge_child(tree, node, index - 1);//node中的右孩子元素合并到左孩子中。 child = leftSibling;
} else if (rightSibling && rightSibling->keynum == BTree_D - 1) { BTree_merge_child(tree, node, index);//node中的右孩子元素合并到左孩子中。
}
}
} BTree_recursive_remove(&child, key);//调整后,在key所在孩子结点中继续递归删除key。
}
} void BTree_remove(BTree* tree, KeyType key)
{
#ifdef DEBUG_BTREE
printf("BTree_remove:\n");
#endif
if (*tree==NULL)
{
printf("BTree is NULL!\n");
return;
} BTree_recursive_remove(tree, key);
} //=====================================search==================================== BTNode* BTree_recursive_search(const BTree tree, KeyType key, int* pos)
{
int i = 0; while (i < tree->keynum && key > tree->key[i]) {
++i;
} // Find the key.
if (i < tree->keynum && tree->key[i] == key) {
*pos = i;
return tree;
} // tree 为叶子节点,找不到 key,查找失败返回
if (tree->isLeaf) {
return NULL;
} // 节点内查找失败,但 tree->key[i - 1]< key < tree->key[i],
// 下一个查找的结点应为 child[i] // 从磁盘读取第 i 个孩子的数据
disk_read(&tree->child[i]); // 递归地继续查找于树 tree->child[i]
return BTree_recursive_search(tree->child[i], key, pos);
} BTNode* BTree_search(const BTree tree, KeyType key, int* pos)
{
#ifdef DEBUG_BTREE
printf("BTree_search:\n");
#endif
if (!tree) {
printf("BTree is NULL!\n");
return NULL;
}
*pos = -1;
return BTree_recursive_search(tree,key,pos);
} //===============================create===============================
void BTree_create(BTree* tree, const KeyType* data, int length)
{
assert(tree); int i; #ifdef DEBUG_BTREE
printf("\n 开始创建 B-树,关键字为:\n");
for (i = 0; i < length; i++) {
printf(" %c ", data[i]);
}
printf("\n");
#endif for (i = 0; i < length; i++) {
#ifdef DEBUG_BTREE
printf("\n插入关键字 %c:\n", data[i]);
#endif
int pos = -1;
BTree_search(*tree,data[i],&pos);//树的递归搜索,查看data[i]是否在树中,在树里,pos改为0。
if (pos!=-1)
{
printf("this key %c is in the B-tree,not to insert.\n",data[i]);
}else{
BTree_insert(tree, data[i]);//插入元素到BTree中。
} #ifdef DEBUG_BTREE
BTree_print(*tree);//树的深度遍历。
#endif
} printf("\n");
}
//===============================destroy===============================
void BTree_destroy(BTree* tree)
{
int i;
BTNode* node = *tree; if (node) {
for (i = 0; i <= node->keynum; i++) {
BTree_destroy(&node->child[i]);
} free(node);
} *tree = NULL;
} //测试order序(阶)的B-TREE结构基本操作。
//查找:search,插入:insert,删除:remove。
//创建:create,销毁:destory,打印:print。 #include <stdio.h>
#include "btree.h" void test_BTree_search(BTree tree, KeyType key)
{
int pos = -1;
BTNode* node = BTree_search(tree, key, &pos);
if (node) {
printf("在%s节点(包含 %d 个关键字)中找到关键字 %c,其索引为 %d\n",
node->isLeaf ? "叶子" : "非叶子",
node->keynum, key, pos);
}
else {
printf("在树中找不到关键字 %c\n", key);
}
} void test_BTree_remove(BTree* tree, KeyType key)
{
printf("\n移除关键字 %c \n", key);
BTree_remove(tree, key);
BTree_print(*tree);
printf("\n");
}
test.c
#include "btree.h"
void test_btree()
{ KeyType array[] = {
'G','G', 'M', 'P', 'X', 'A', 'C', 'D', 'E', 'J', 'K',
'N', 'O', 'R', 'S', 'T', 'U', 'V', 'Y', 'Z', 'F', 'X'
};
//KeyType array[] = {'A','B','C','D','E','F','G','H','I','J'};
const int length = sizeof(array)/sizeof(KeyType);
BTree tree = NULL;
BTNode* node = NULL;
int pos = -1;
KeyType key1 = 'R'; // in the tree.
KeyType key2 = 'B'; // not in the tree. // 创建
BTree_create(&tree, array, length); printf("\n=== 创建 B- 树 ===\n");
BTree_print(tree);
printf("\n"); // 查找
test_BTree_search(tree, key1);
printf("\n");
test_BTree_search(tree, key2); // 移除不在B树中的元素
test_BTree_remove(&tree, key2);
printf("\n"); // 插入关键字
printf("\n插入关键字 %c \n", key2);
BTree_insert(&tree, key2);
BTree_print(tree);
printf("\n"); test_BTree_search(tree, key2); // 移除关键字
test_BTree_remove(&tree, key2);
test_BTree_search(tree, key2);
BTree_print(tree); key2 = 'M';
test_BTree_remove(&tree, key2);
test_BTree_search(tree, key2);
BTree_print(tree); key2 = 'E';
test_BTree_remove(&tree, key2);
test_BTree_search(tree, key2);
BTree_print(tree); key2 = 'G';
test_BTree_remove(&tree, key2);
test_BTree_search(tree, key2);
BTree_print(tree); key2 = 'A';
test_BTree_remove(&tree, key2);
test_BTree_search(tree, key2);
BTree_print(tree); key2 = 'D';
test_BTree_remove(&tree, key2);
test_BTree_search(tree, key2);
BTree_print(tree); key2 = 'K';
test_BTree_remove(&tree, key2);
test_BTree_search(tree, key2);
BTree_print(tree); key2 = 'P';
test_BTree_remove(&tree, key2);
test_BTree_search(tree, key2);
BTree_print(tree); key2 = 'J';
test_BTree_remove(&tree, key2);
test_BTree_search(tree, key2);
BTree_print(tree); key2 = 'C';
test_BTree_remove(&tree, key2);
test_BTree_search(tree, key2);
BTree_print(tree); key2 = 'X';
test_BTree_remove(&tree, key2);
test_BTree_search(tree, key2);
BTree_print(tree); key2 = 'O';
test_BTree_remove(&tree, key2);
test_BTree_search(tree, key2);
BTree_print(tree); key2 = 'V';
test_BTree_remove(&tree, key2);
test_BTree_search(tree, key2);
BTree_print(tree); key2 = 'R';
test_BTree_remove(&tree, key2);
test_BTree_search(tree, key2);
BTree_print(tree); key2 = 'U';
test_BTree_remove(&tree, key2);
test_BTree_search(tree, key2);
BTree_print(tree); key2 = 'T';
test_BTree_remove(&tree, key2);
test_BTree_search(tree, key2);
BTree_print(tree); key2 = 'N';
test_BTree_remove(&tree, key2);
test_BTree_search(tree, key2);
BTree_print(tree); key2 = 'S';
test_BTree_remove(&tree, key2);
test_BTree_search(tree, key2);
BTree_print(tree); key2 = 'Y';
test_BTree_remove(&tree, key2);
test_BTree_search(tree, key2);
BTree_print(tree); key2 = 'F';
test_BTree_remove(&tree, key2);
test_BTree_search(tree, key2);
BTree_print(tree); key2 = 'Z';
test_BTree_remove(&tree, key2);
test_BTree_search(tree, key2);
BTree_print(tree);
// 销毁
BTree_destroy(&tree);
}
int main()
{
test_btree(); return 0;
}
Btree算法的C语言实现的更多相关文章
- 魔方阵算法及C语言实现
1 魔方阵概念 填充的,每一行.每一列.对角线之和均相等的方阵,阶数n = 3,4,5….魔方阵也称为幻方阵. 例如三阶魔方阵为: 魔方阵有什么的规律呢? 魔方阵分为奇幻方和偶幻方.而偶幻方又分为是4 ...
- 一个UUID生成算法的C语言实现 --- WIN32版本 .
一个UUID生成算法的C语言实现——WIN32版本 cheungmine 2007-9-16 根据定义,UUID(Universally Unique IDentifier,也称GUID)在时 ...
- 无限大整数相加算法的C语言源代码
忙里偷闲,终于完成了无限大整数相加算法的C语言代码,无限大整数相加算法的算法分析在这里. 500位的加法运行1000次,不打印结果的情况下耗时0.036秒,打印结果的情况下耗时16.285秒. 下面是 ...
- 数据结构算法集---C++语言实现
//数据结构算法集---C++语言实现 //各种类都使用模版设计,可以对各种数据类型操作(整形,字符,浮点) /////////////////////////// // // // 堆栈数据结构 s ...
- 1164: 零起点学算法71——C语言合法标识符(存在问题)
1164: 零起点学算法71——C语言合法标识符 Time Limit: 1 Sec Memory Limit: 64 MB 64bit IO Format: %lldSubmitted: 10 ...
- 【最全】经典排序算法(C语言)
算法复杂度比较: 算法分类 一.直接插入排序 一个插入排序是另一种简单排序,它的思路是:每次从未排好的序列中选出第一个元素插入到已排好的序列中. 它的算法步骤可以大致归纳如下: 从未排好的序列中拿出首 ...
- PID算法(c 语言)(转)
PID算法(c 语言)(来自老外) #include <stdio.h> #include<math.h> //定义PID 的结构体 struct _pid { int pv; ...
- 一个UUID生成算法的C语言实现——WIN32版本
源: 一个UUID生成算法的C语言实现——WIN32版本
- 排序算法总结(C语言版)
排序算法总结(C语言版) 1. 插入排序 1.1 直接插入排序 1.2 Shell排序 2. 交换排序 2.1 冒泡排序 2.2 快速排序 3. 选择 ...
随机推荐
- *Android 多线程下载 仿下载助手
今天带来一个多线程下载的 样例.先看一下效果.点击 下载 開始下载,同一时候显示下载进度.完成下载,变成程 安装,点击安装 提示 安装应用. 界面效果 线程池 ThreadPoolExecutor , ...
- 如何创建RESTFul Web服务
想写这篇文章很久了,这是个大话题,不是一时半会就能说清楚的. 所以准备花个一星期整理资料,把思路理清楚,然后再在Team里做个sharing:) 其实RESTFul是架构风格,并不是实现规范,也不一定 ...
- 宜人贷PaaS数据服务平台Genie:技术架构及功能
上篇:架构及组件 一.数据平台的发展 1.1 背景介绍 随着数据时代的到来,数据量和数据复杂度的增加推动了数据工程领域的快速发展.为了满足各类数据获取/计算等需求,业内涌现出了诸多解决方案.但大部分方 ...
- 基于RedHat发行的Apache Tomcat本地提权漏洞
描述 Tomcat最近总想搞一些大新闻,一个月都没到,Tomcat又爆出漏洞.2016年10月11日,网上爆出Tomcat本地提权漏洞,漏洞编号为CVE-2016-5425.此次受到影响的主要是基于R ...
- 触发器 (Delete Update)
--delete触发器IF(EXISTS(SELECT * FROM sysobjects WHERE name='T_PlanQtyDelete'))DROP TRIGGER T_PlanQtyDe ...
- 身份证归属地查询免费api接口代码
描写叙述 :依据身份证编号 查询归属地信息. 身份证实体类: package org.wx.xhelper.model; /** * 身份证实体类 * @author wangxw * @versio ...
- Rider
听说你开发.NET还在用VS,小哥哥给你推荐全平台的Rider 本文地址:http://www.cnblogs.com/likeli/p/8461010.html 前言 .NET平台的开发一直都只 ...
- Android App 启动页(Splash)黑/白闪屏现象产生原因与解决办法(转)
转载: Android App 启动页(Splash)黑/白闪屏现象产生原因与解决办法 首先感谢博主分享,本文作为学习记录 惊鸿一瞥 微信的启动页,相信大家都不陌生. 不知道大家有没有发现一个现象 ...
- 嵌入式开发之davinci--- 8148/8168/8127 中的xdc 简介
XDC是TI公司为嵌入式实时系统可重用软件组件(在XDC里被成为packages,以下成为包)制定的一套标准.它包括一些有用的工具,标准的API函数,静态配置文件和打包(packaging)操作.XD ...
- react build和server start
先到项目目录build项目 npm run build 项目会打包到dist文件夹下 index.html和index.js等 react的项目build后不能直接访问的问题 先执行 npm inst ...