⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bt_code.c

📁 b树的实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/*- * Copyright 1997-1999, 2001 John-Mark Gurney. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *	$Id: bt_code.c,v 1.10.2.2 2001/03/28 06:18:30 jmg Exp $ * * Pseudo code used to implement this data structure was obtained from: * Introduction to Algorithms / Thomas H. Cormen, Charles E. Leiserson, *     Ronald L. Rivest. * * The delete key routine was not provided in pseudo code and is my own * creation following their cases to maintain balance. * */#include <btree.h>#include <btreepriv.h>#include <stdlib.h>#include <string.h>#define	FREE(p)		(free(p), (void *) NULL)#ifdef NO_INLINE#define inline#endifstatic inline int findkindex(struct btree *btr, struct btreenode *x,			     bt_data_t k, int *r);static struct btree *allocbtree(void);static struct btreenode *allocbtreenode(int n);static void btreesplitchild(struct btree *btr, struct btreenode *x, int i,			    struct btreenode *y);static void btreeinsertnonfull(struct btree *btr, struct btreenode *x,			       bt_data_t k);static bt_data_t nodedeletekey(struct btree *btr, struct btreenode *x,			       bt_data_t k, int s);static struct btreenode *freebtreenode(struct btreenode *);static bt_data_t findmaxnode(struct btree *btr, struct btreenode *x);static bt_data_t findminnode(struct btree *btr, struct btreenode *x);static bt_data_t findnodekey(struct btree *, struct btreenode *x, bt_data_t k);static int log2(unsigned int, int) __attribute__ ((const));#if 0/* we would use this, but even unoptimized C code is faster than bsr! */static inline intlog2(unsigned int a, int nbits){	int r;	asm volatile ("bsrl %1,%0" : "=r" (r) : "rm" (a) : "cc");	return r;}#else/* * This is the real log2 function.  It is only called when we don't have * a value in the table. */static inline intreal_log2(unsigned int a, int nbits){	int i;	int b;	/* divide in half rounding up */	b = (nbits + 1) / 2;	i = 0;	while (b) {		i = (i << 1);		if (a >= (1 << b)) {			/* select the top half and mark this bit */			a /= (1 << b);			i = i | 1;		} else			/* select the bottom half and don't set the bit */			a &= (1 << b) - 1;		b /= 2;	}	return i;}#endif/* * Implement a lookup table for the log values.  This will only allocate * memory that we need.  This is much faster than calling the log2 routine * every time.  Doing 1 million insert, searches, and deletes will generate * ~58 million calls to log2.  Using a lookup table IS NECESSARY! */static inline intlog2(unsigned int a, int nbits){	static signed char *table;	static int alloced;	int i;	if (a > alloced) {		table = realloc(table, (a + 1) * sizeof *table);		for (i = alloced; i < a + 1; i++)			table[i] = -1;		alloced = a + 1;	}	if (table[a] == -1)		table[a] = real_log2(a, nbits);	return table[a];}#ifndef SAFE_BTREE/* * Finally get this code working properly.  It now works great.  I don't * have any problems with this.  Leave the old code in incase I need it * again. */static inline intfindkindex(struct btree *btr, struct btreenode *x, bt_data_t k, int *r){	int a, b, i;	int tr;	int *rr;	if (r == NULL)		rr = &tr;	else		rr = r;	if (x->n == 0)		return -1;	a = x->n - 1;	i = 0;	while (a > 0) {		b = log2(a, btr->nbits);		if ((*rr = btr->cmp(k, KEYS(btr, x)[(1 << b) + i])) < 0)			a = (1 << b) - 1;		else {			a -= (1 << b);			i |= (1 << b);		}	}	if ((*rr = btr->cmp(k, KEYS(btr, x)[i])) < 0)		i--;	return i;}#elsestatic inline intfindkindex(struct btree *btr, struct btreenode *x, bt_data_t k, int *r){	int tr;	int *rr;	int n;	if (r != NULL)		rr = r;	else		rr = &tr;	/* hmmm, doesn't really matter which way we go through the node */	n = x->n - 1;	while (n >= 0 && (*rr = btr->cmp(k, KEYS(btr, x)[n])) < 0)		n--;	return n;}#endifstatic struct btree *allocbtree(void){	struct btree *btr;	if ((btr = malloc(sizeof *btr)) != NULL) {		btr->root = NULL;		btr->cmp = NULL;		btr->keyoff = 0;		btr->nodeptroff = 0;		btr->nkeys = 0;		btr->t = 0;		btr->nbits = 0;		btr->textra = 0;#ifdef STATS		btr->numkeys = 0;		btr->numnodes = 0;#endif	}	return btr;}static struct btreenode *allocbtreenode(int n){	struct btreenode *btn;	if ((btn = malloc(sizeof *btn + n)) != NULL) {		bzero(btn, sizeof *btn + n);		btn->leaf = 1;	}	return btn;}struct btree *bt_create(bt_cmp_t cmp, int size){	struct btree *btr;	int n, t;	int textra;	textra = 0;	btr = NULL;	size -= sizeof *btr->root;	size -= sizeof btr->root;	/*	 * calculate maximum t that will fix in size, and that t >= 2	 */	if ((n = size / (sizeof btr->root + sizeof(bt_data_t))) > 0 &&	    ( t = (n + 1) / 2) >= 2) {		n = 2 * t - 1;		textra += sizeof btr->root + n * (sizeof btr->root +		    sizeof(bt_data_t));		if ((btr = allocbtree()) != NULL) {			btr->cmp = cmp;			btr->keyoff = sizeof *btr->root;			btr->nodeptroff = btr->keyoff + n * sizeof(bt_data_t);			btr->nkeys = n;			btr->t = t;			btr->nbits = log2(btr->nkeys, sizeof(int) * 8) + 1;			/* make nbits a power of 2 */			btr->nbits = 1 <<			    (log2(btr->nbits, sizeof(int) * 8) + 1);			btr->textra = textra;#ifdef STATS			btr->numnodes++;#endif			if ((btr->root = allocbtreenode(textra)) == NULL)				btr = FREE(btr);		}	}	return btr;}static voidbtreesplitchild(struct btree *btr, struct btreenode *x, int i,    struct btreenode *y){	struct btreenode *z;	int j;#ifdef STATS	btr->numnodes++;#endif	if ((z = allocbtreenode(btr->textra)) == NULL)		exit(1);	/* duplicate leaf setting, and store number of nodes */	z->leaf = y->leaf;	z->n = btr->t - 1;	/* copy the last half of y into z */	for (j = 0; j < btr->t - 1; j++)		KEYS(btr, z)[j] = KEYS(btr, y)[j + btr->t];	/* if it's an internal node, copy the ptr's too */	if (!y->leaf)		for (j = 0; j < btr->t; j++)			NODES(btr, z)[j] = NODES(btr, y)[j + btr->t];	/* store resulting number of nodes in old part */	y->n = btr->t - 1;	/* move node ptrs in parent node down one, and store new node */	for (j = x->n; j > i; j--)		NODES(btr, x)[j + 1] = NODES(btr, x)[j];	NODES(btr, x)[i + 1] = z;	/* adjust the keys from previous move, and store new key */	for (j = x->n - 1; j >= i; j--)		KEYS(btr, x)[j + 1] = KEYS(btr, x)[j];	KEYS(btr, x)[i] = KEYS(btr, y)[btr->t - 1];	x->n++;}voidbt_insert(struct btree *btr, bt_data_t k){	struct btreenode *r, *s;#ifdef STATS	btr->numkeys++;#endif	r = btr->root;	if (r->n == 2 * btr->t - 1) {		/*		 * this is the ONLY place that the tree can grown in		 * height		 */#ifdef STATS		btr->numnodes++;#endif		if ((s = allocbtreenode(btr->textra)) == NULL)			exit(1);		btr->root = s;		s->leaf = 0;		s->n = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -