1. 程式人生 > >使用核心資料結構:紅黑樹 rbtree

使用核心資料結構:紅黑樹 rbtree

一、使用核心紅黑樹檔案rbtree

1.1 核心紅黑樹檔案

        rbtree.h:/usr/src/kernels/2.6.32-279.el6.x86_64/include/linux/rbtree.h

        rbtree.c:/usr/src/kernels/2.6.32-279.el6.x86_64/lib/rbtree.c

1.2 修改rbtree.h

修改包含標頭檔案,增加3個巨集定義:

//刪除以下兩行程式碼
//#include <linux/kernel.h>
//#include <linux/stddef.h>

//增加下面3個巨集定義
/* 2.6.32-279.el6.x86_64/include/linux/stddef.h  */
#undef NULL
#if defined(__cplusplus)
#define NULL 0
#else
#define NULL ((void *)0)
#endif

/* 2.6.32-279.el6.x86_64/include/linux/stddef.h  */
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

/* 2.6.32-279.el6.x86_64/include/linux/kernel.h  */
#define container_of(ptr, type, member) ({                      \
        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
        (type *)( (char *)__mptr - offsetof(type,member) );})

1.3 修改rbtree.c

修改包含標頭檔案的程式碼:

//刪除以下兩行程式碼
//#include <linux/rbtree.h>
//#include <linux/module.h>

//增加包含標頭檔案的程式碼
#include "rbtree.h"
刪除所有的EXPORT_SYMBOL巨集:
//EXPORT_SYMBOL(rb_insert_color);
//EXPORT_SYMBOL(rb_erase);
//EXPORT_SYMBOL(rb_first);
//EXPORT_SYMBOL(rb_last);
//EXPORT_SYMBOL(rb_next);
//EXPORT_SYMBOL(rb_prev);
//EXPORT_SYMBOL(rb_replace_node);

二、程式碼

2.1 test.c

#include <stdio.h>
#include <stdlib.h>
#include "rbtree.h"

struct rbt_data
{
    struct rb_node data_node;
	int num;
};

struct rbt_data* rbt_search(struct rb_root *root, int num)
{
    struct rb_node *node = root->rb_node;

    while(node)
    {
        struct rbt_data *data = container_of(node, struct rbt_data, data_node);

		if (num < data->num)
			node = node->rb_left;
		else if (num > data->num)
			node = node->rb_right;
		else
			return data;
    }
	
    return NULL;
}

int rbt_insert(struct rb_root *root, struct rbt_data *data)
{
    struct rb_node **tmp = &(root->rb_node);
	struct rb_node *parent = NULL;

	while (*tmp)
	{
	    struct rbt_data *cur = container_of(*tmp, struct rbt_data, data_node);

		parent = *tmp;
		if(data->num < cur->num)
			tmp = &((*tmp)->rb_left);
		else if(data->num > cur->num)
			tmp = &((*tmp)->rb_right);
		else
			return -1;
	}

	rb_link_node(&(data->data_node), parent, tmp);
	rb_insert_color(&(data->data_node), root);

    return 0;
}

void rbt_delete(struct rb_root *root, int num)
{
	struct rbt_data *data = rbt_search(root, num);
	if (!data)
	{
	    fprintf(stderr, "Not fount %d.\n", num);
		return;
	}

	rb_erase(&(data->data_node), root);
	free(data);
	
}

void print_rbtree(struct rb_root *root)
{
    struct rb_node *node;

	for(node = rb_first(root); node; node = rb_next(node))
		printf("%d ", rb_entry(node, struct rbt_data, data_node)->num);

	printf("\n");
}

int main(int argc, char*argv[])
{
	struct rb_root root = RB_ROOT;

	struct rbt_data *data;
	int i;

	printf("please enter 5 integers:\n");
	for(i=0; i<5; i++)
	{
	    data = malloc(sizeof(struct rbt_data));
		if(!data)
		{
			perror("fail to malloc.");
		}

		scanf("%d", &data->num);

		int ret = rbt_insert(&root, data);
		if (ret < 0)
		{
		    fprintf(stderr, "the %d already exists.\n", data->num);
			i--;
			free(data);
		}
	}

	printf("\nthe first output:\n");
	print_rbtree(&root);

    int num;
	printf("\nplease enter the num to delete:\n");
	scanf("%d", &num);
	rbt_delete(&root, num);

    printf("\nthe second output:\n");
	print_rbtree(&root);
    
	return 0;
}

三、編譯執行

3.1 編譯

         gcc test.c rbtree.c -o test

3.2 執行結果


參考資料: