Linux环境下BST树算法的具体实现方法有哪些?

2026-05-22 12:291阅读0评论SEO资源
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计2646个文字,预计阅读时间需要11分钟。

Linux环境下BST树算法的具体实现方法有哪些?

本文介绍了BST(二叉搜索树)的基本概念和算法实现,并提供了示例。

BST简介:BST(二叉搜索树)是一种特殊的二叉树,其特点是左子树上所有节点的值均小于根节点的值,右子树上所有节点的值均大于根节点的值。BST的这种特性使得它在插入、删除和查找等操作上具有高效性,与线性表的实现类似。

本文讲述了BST树的基本概念和算法实现,并且提供了示例。 简介

BST就是二叉搜索树(Binary Search Tree)的简称,因此毫无疑问BST也是二叉树,对于二叉树而言,和线性表的实现一样,我们也必须设计其数据节点,而且也必须设计其诸如插入、删除等操作。由于一般二叉树使用顺序存储会不可避免地浪费存储空间,因此我们一般都采用链式存储来表达一棵二叉树。

BST之所以称为二叉搜索树,是因为我们对其节点的存放位置做了严格的规定,从而来提高其搜索性能。BST规定:在任何子树中,根节点必须大于其左子树中任意的节点,且必须小于其右子树中任意的节点,换句话说必须满足“小 ---- 中 ----- 大”的逻辑次序。

树节点的设计,包括了三个要素:数据域、左孩子指针和右孩子指针,其代码如下:

struct node { datatype data; struct node *lchild; struct node *rchild; };

有了树的结构体,我们就可以写出初始化一棵空BST和产生一个新节点的代码了。如下:

struct node * init_tree(void) //初始化一棵空BST { return NULL; } struct node * new_node(datatype data) //产生一个新节点 { struct node *new = malloc(sizeof(struct node)); if(NULL != new) { new->data = data; new->lchild = NULL; new->rchild = NULL; } return new; }

由于树本身是一种递归的结构,因此它的操作算法都可以用递归来实现。

算法实现和示例

下面给出完整的代码实现,包括头文件和c文件。

首先是头文件: head4tree.h、head4queue.h、commonheader.h、drawtree.h

head4tree.h

////////////////////////////////////////////////////////////////// // Description: 本文件为二叉树核心头文件。 // 任何使用本二叉树结构算法的程序,在包含本头文件之前 // 都需要将如下宏定义成二叉树节点需要表达的数据类型: // // TREE_NODE_DATATYPE // // 否则二叉树的节点数据类型一律默认为 int // ////////////////////////////////////////////////////////////////// #ifndef _HEAD4TREE_H_ #define _HEAD4TREE_H_ /* * Any application applying this linked-tree data structure should * define the macro "TREE_NODE_DATATYPE" before include this head * file, otherwise, the macro will be defined to 'int' as follow. * */ #ifndef TREE_NODE_DATATYPE #define TREE_NODE_DATATYPE int #endif #include "commonheader.h" #define MAX(a, b) ({ \ typeof(a) _a = a; \ typeof(b) _b = b; \ (void)(&_a == &_b);\ _a > _b? _a : _b; \ }) typedef TREE_NODE_DATATYPE tn_datatype; #ifdef RB #define RED 0 #define BLACK 1 #endif typedef struct _tree_node { tn_datatype data; struct _tree_node *lchild; struct _tree_node *rchild; #ifdef AVL int height; #endif #ifdef RB struct _tree_node *parent; int color; #endif }treenode, *linktree; void pre_travel(linktree, void (*handler)(linktree)); void mid_travel(linktree, void (*handler)(linktree)); void post_travel(linktree, void (*handler)(linktree)); void level_travel(linktree, void (*handler)(linktree)); linktree bst_insert(linktree root, linktree new); linktree bst_remove(linktree root, tn_datatype data); linktree bst_find(linktree root, tn_datatype data); #ifdef AVL linktree avl_insert(linktree root, linktree new); linktree avl_remove(linktree root, tn_datatype data); linktree avl_rotate_left (linktree root); linktree avl_rotate_right(linktree root); linktree avl_rotate_leftright(linktree root); linktree avl_rotate_rightleft(linktree root); static int height(linktree root) { return root==NULL ? 0 : root->height; } #endif static linktree new_node(tn_datatype data) { linktree new = malloc(sizeof(treenode)); if(new != NULL) { new->data = data; new->lchild = NULL; new->rchild = NULL; #ifdef AVL new->height = 1; #endif #ifdef RB new->parent = NULL; new->color = RED; #endif } return new; } #endif

head4queue.h

////////////////////////////////////////////////////////////////// // Description: 本文件为队列核心头文件。 // 任何使用本队列算法的程序,在包含本头文件之前都需要 // 将如下宏定义成队列节点需要表达的数据类型: // // QUEUE_NODE_DATATYPE // // 否则队列的节点数据类型一律默认为 int // ////////////////////////////////////////////////////////////////// #ifndef _HEAD4QUEUE_H__ #define _HEAD4QUEUE_H__ #include "commonheader.h" #ifndef QUEUE_NODE_DATATYPE #define QUEUE_NODE_DATATYPE int #endif typedef QUEUE_NODE_DATATYPE qn_datatype; struct _queue_node { qn_datatype data; struct _queue_node *next; }; typedef struct _queuenode { struct _queue_node *front; struct _queue_node *rear; #ifdef QUEUE_SIZE int size; #endif }queuenode, *linkqueue; bool is_empty_q(linkqueue); bool out_queue(linkqueue, qn_datatype *); bool en_queue(linkqueue, qn_datatype); linkqueue init_queue(void); #ifdef QUEUE_SIZE int queue_size(linkqueue *); #endif #endif

commonheader.h

#ifndef _COMMONHEADER_H_ #define _COMMONHEADER_H_ #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <unistd.h> #include <string.h> #include <strings.h> #include <time.h> #include <errno.h> #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> #include <sys/ipc.h> #include <sys/sem.h> #include <sys/shm.h> #include <sys/msg.h> #include <semaphore.h> #include <fcntl.h> #include <pthread.h> #endif

drawtree.h

////////////////////////////////////////////////////////////////// // Description: 使用C语言写一页webpage ////////////////////////////////////////////////////////////////// #ifndef _DRAWTREE_H_ #define _DRAWTREE_H_ #include "commonheader.h" #include "head4tree.h" #ifndef QUEUE_NODE_DATATYPE #define QUEUE_NODE_DATATYPE linktree #endif #include "head4queue.h" static char page_begin[] = "<html><head><title>tree map" "</title></head><body>" "<table border=0 cellspacing" "=0 cellpadding=0>"; static char line_begin[] = "<tr>"; static char line_end [] = "</tr>"; static char space [] = "<td>&nbsp;</td>"; static char underline [] = "<td style=\"border-bottom:" "1px solid #58CB64\">&nbsp;" "</td>"; #ifdef RB static char data_begin_red[] = "<td bgcolor=\"#FF0000\";style=" "\"border:1px sol" "id #58CB64;background-colo" "r:#DDF1D8;PADDING:2px;\" t" "itle=\"level: 1\">"; static char data_begin_blk[] = "<td bgcolor=\"#000000\";style=" "\"border:1px sol" "id #58CB64;background-colo" "r:#DDF1D8;PADDING:2px;\" t" "itle=\"level: 1\"><font color" "=\"#FFFFFF\">"; static char data_end_red[] = "</td>"; static char data_end_blk[] = "</font></td>"; #else static char data_begin[] = "<td style=\"border:1px sol" "id #58CB64;background-colo" "r:#DDF1D8;PADDING:2px;\" t" "itle=\"level: 1\">"; static char data_end [] = "</td>"; #endif static char page_end [] = "</table></body></html>"; #define MAX_NODES_NUMBER 100 #define FILENAME 32 static tn_datatype central_order[MAX_NODES_NUMBER]; void putunderline(int fd, int num); void putspace(int fd, int num); #ifdef RB void putdata(int fd, linktree p); #else void putdata(int fd, int data); #endif int get_index(tn_datatype data); void create_index(linktree root); void data_leftside(int fd, linktree root, int spaces); int data_rightside(int fd, linktree root); void start_page(int fd); void end_page(int fd); void draw(linktree root); #endif

drawtree提供的draw函数用来在webpage上面把树画出来。

然后是c文件:queue.c drawtree.c bst.c

queue.c

//////////////////////////////////////////////////////////////////// // Description: 链队列 //////////////////////////////////////////////////////////////////// #include "head4queue.h" linkqueue init_queue(void) { linkqueue q = (linkqueue)malloc(sizeof(queuenode)); q->front = q->rear = (struct _queue_node *)malloc(sizeof(struct _queue_node)); q->rear->next = NULL; return q; } bool is_empty_q(linkqueue q) { return (q->front == q->rear); } bool out_queue(linkqueue q, qn_datatype *pdata) { if(is_empty_q(q)) return false; struct _queue_node *p = q->front; q->front = q->front->next; free(p); *pdata = q->front->data; return true; } bool en_queue(linkqueue q, qn_datatype data) { struct _queue_node *pnew; pnew = (struct _queue_node *)malloc(sizeof(struct _queue_node)); if(pnew == NULL) return false; pnew->data = data; pnew->next = NULL; q->rear->next = pnew; q->rear = pnew; return true; } #ifdef QUEUE_SIZE int queue_size(linkqueue *q) { return q->size; } #endif

drawtree.c

//////////////////////////////////////////////////////////////////// // Description: 将二叉树的逻辑层次结构,用网页展示出来 //////////////////////////////////////////////////////////////////// #include "head4tree.h" #include "drawtree.h" void putunderline(int fd, int num) { int i; for(i=0; i<num; i++) { write(fd, underline, strlen(underline)); } } void putspace(int fd, int num) { int i; for(i=0; i<num; i++) { write(fd, space, strlen(space)); } } #ifdef RB void putdata(int fd, linktree p) { char s[50]; bzero(s, 50); snprintf(s, 50, "%d", p->data); switch(p->color) { case RED: write(fd, data_begin_red, strlen(data_begin_red)); write(fd, s, strlen(s)); write(fd, data_end_red, strlen(data_end_red)); break; case BLACK: write(fd, data_begin_blk, strlen(data_begin_blk)); write(fd, s, strlen(s)); write(fd, data_end_blk, strlen(data_end_blk)); } } #else void putdata(int fd, int data) { char s[50]; bzero(s, 50); snprintf(s, 50, "%d", data); write(fd, data_begin, strlen(data_begin)); write(fd, s, strlen(s)); write(fd, data_end, strlen(data_end)); } #endif static int Index = 0; void create_index(linktree root) { if(Index >= MAX_NODES_NUMBER-1) return; central_order[Index++] = root->data; } int get_index(tn_datatype data) { int i; for(i=0; i<100; i++) { if(central_order[i] == data) return i; } return -1; } void data_leftside(int fd, linktree root, int spaces) { if(root == NULL) return; int s_line=0; if(root->lchild != NULL) { s_line = get_index(root->data)- get_index(root->lchild->data)-1; } putspace(fd, spaces-s_line); putunderline(fd, s_line); } int data_rightside(int fd, linktree root) { if(root == NULL) return 0; int s_line=0; if(root->rchild != NULL) { s_line = get_index(root->rchild->data)- get_index(root->data)-1; } putunderline(fd, s_line); return s_line; } void start_page(int fd) { write(fd, page_begin, strlen(page_begin)); } void end_page(int fd) { write(fd, page_end, strlen(page_end)); } void draw(linktree root) { if(root == NULL) return; time_t t; time(&t); static char filename[FILENAME]; bzero(filename, FILENAME); snprintf(filename, FILENAME, "%u.html", (unsigned)t); int fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, 0644); if(fd == -1) { perror("open() failed"); exit(1); } Index = 0; mid_travel(root, create_index); linkqueue q = init_queue(); linktree tmp = root; int ndata = 1; start_page(fd); while(1) { write(fd, line_begin, strlen(line_begin)); int i, n = 0; int nextline = 0; for(i=0; i<ndata; i++) { int index = get_index(tmp->data); data_leftside(fd, tmp, index-n); #ifdef RB putdata(fd, tmp); #else putdata(fd, tmp->data); #endif int rightline = data_rightside(fd, tmp); if(tmp->lchild != NULL) { nextline++; en_queue(q, tmp->lchild); } if(tmp->rchild != NULL) { nextline++; en_queue(q, tmp->rchild); } if(!out_queue(q, &tmp)) return; n = index + rightline; n++; } write(fd, line_end, strlen(line_end)); ndata = nextline; } end_page(fd); close(fd); }

bst.c

//////////////////////////////////////////////////////////////////// // Description: BST算法实现代码 //////////////////////////////////////////////////////////////////// #include "head4tree.h" #include "drawtree.h" linktree bst_insert(linktree root, linktree new) { if(new == NULL) return root; if(root == NULL) return new; if(new->data > root->data) { root->rchild = bst_insert(root->rchild, new); } else if(new->data < root->data) { root->lchild = bst_insert(root->lchild, new); } else { printf("%d is already exist.\n", new->data); } return root; } linktree bst_find(linktree root, tn_datatype data) { if(root == NULL) return NULL; if(data < root->data) return bst_find(root->lchild, data); else if(data > root->data) return bst_find(root->rchild, data); else return root; } linktree bst_remove(linktree root, tn_datatype n) { if(root == NULL) return NULL; if(n < root->data) root->lchild = bst_remove(root->lchild, n); else if(n > root->data) root->rchild = bst_remove(root->rchild, n); else { linktree tmp; if(root->lchild != NULL) { for(tmp=root->lchild; tmp->rchild!=NULL; tmp=tmp->rchild); root->data = tmp->data; root->lchild = bst_remove(root->lchild, tmp->data); } else if(root->rchild != NULL) { for(tmp=root->rchild; tmp->lchild!=NULL; tmp=tmp->lchild); root->data = tmp->data; root->rchild = bst_remove(root->rchild, tmp->data); } else { free(root); return NULL; } } return root; } int main(void) { linktree root; root = NULL; printf("输入大于0的数插入节点\n"); printf("输入小于0的数删除节点\n"); printf("输入0退出程序\n"); int n; while(1) { scanf("%d", &n); if(n > 0) { linktree new = new_node(n); root = bst_insert(root, new); } else if(n < 0) { root = bst_remove(root, -n); } if(n == 0) break; draw(root); system("firefox -new-tab *.html &"); } system("rm *.html"); return 0; }

该文件里面包含了测试入口函数main,实现了以下功能:
1、输入大于0的整数就插入节点
2、输入小于0的整数就删除其绝对值对应的节点
3、输入0就退出程序
4、退出程序之前用网页把这棵树画出来

运行效果如下:

延伸

目前实现了最很简单的二叉搜索树,但是存在一个问题:这颗树可能会由于插入或删除的节点的随机性导致不平衡,从而影响BST的搜索性能。

什么是二叉树的不平衡?平衡树?红黑树?后面我有时间再一一道来。

总结

本文简单介绍了BST树的概念,并提供了相关的算法实现,演示了运行效果。
后面我有时间会把平衡树和红黑树的知识点及算法实现补充进来,以便日后使用。

Linux环境下BST树算法的具体实现方法有哪些?

本文共计2646个文字,预计阅读时间需要11分钟。

Linux环境下BST树算法的具体实现方法有哪些?

本文介绍了BST(二叉搜索树)的基本概念和算法实现,并提供了示例。

BST简介:BST(二叉搜索树)是一种特殊的二叉树,其特点是左子树上所有节点的值均小于根节点的值,右子树上所有节点的值均大于根节点的值。BST的这种特性使得它在插入、删除和查找等操作上具有高效性,与线性表的实现类似。

本文讲述了BST树的基本概念和算法实现,并且提供了示例。 简介

BST就是二叉搜索树(Binary Search Tree)的简称,因此毫无疑问BST也是二叉树,对于二叉树而言,和线性表的实现一样,我们也必须设计其数据节点,而且也必须设计其诸如插入、删除等操作。由于一般二叉树使用顺序存储会不可避免地浪费存储空间,因此我们一般都采用链式存储来表达一棵二叉树。

BST之所以称为二叉搜索树,是因为我们对其节点的存放位置做了严格的规定,从而来提高其搜索性能。BST规定:在任何子树中,根节点必须大于其左子树中任意的节点,且必须小于其右子树中任意的节点,换句话说必须满足“小 ---- 中 ----- 大”的逻辑次序。

树节点的设计,包括了三个要素:数据域、左孩子指针和右孩子指针,其代码如下:

struct node { datatype data; struct node *lchild; struct node *rchild; };

有了树的结构体,我们就可以写出初始化一棵空BST和产生一个新节点的代码了。如下:

struct node * init_tree(void) //初始化一棵空BST { return NULL; } struct node * new_node(datatype data) //产生一个新节点 { struct node *new = malloc(sizeof(struct node)); if(NULL != new) { new->data = data; new->lchild = NULL; new->rchild = NULL; } return new; }

由于树本身是一种递归的结构,因此它的操作算法都可以用递归来实现。

算法实现和示例

下面给出完整的代码实现,包括头文件和c文件。

首先是头文件: head4tree.h、head4queue.h、commonheader.h、drawtree.h

head4tree.h

////////////////////////////////////////////////////////////////// // Description: 本文件为二叉树核心头文件。 // 任何使用本二叉树结构算法的程序,在包含本头文件之前 // 都需要将如下宏定义成二叉树节点需要表达的数据类型: // // TREE_NODE_DATATYPE // // 否则二叉树的节点数据类型一律默认为 int // ////////////////////////////////////////////////////////////////// #ifndef _HEAD4TREE_H_ #define _HEAD4TREE_H_ /* * Any application applying this linked-tree data structure should * define the macro "TREE_NODE_DATATYPE" before include this head * file, otherwise, the macro will be defined to 'int' as follow. * */ #ifndef TREE_NODE_DATATYPE #define TREE_NODE_DATATYPE int #endif #include "commonheader.h" #define MAX(a, b) ({ \ typeof(a) _a = a; \ typeof(b) _b = b; \ (void)(&_a == &_b);\ _a > _b? _a : _b; \ }) typedef TREE_NODE_DATATYPE tn_datatype; #ifdef RB #define RED 0 #define BLACK 1 #endif typedef struct _tree_node { tn_datatype data; struct _tree_node *lchild; struct _tree_node *rchild; #ifdef AVL int height; #endif #ifdef RB struct _tree_node *parent; int color; #endif }treenode, *linktree; void pre_travel(linktree, void (*handler)(linktree)); void mid_travel(linktree, void (*handler)(linktree)); void post_travel(linktree, void (*handler)(linktree)); void level_travel(linktree, void (*handler)(linktree)); linktree bst_insert(linktree root, linktree new); linktree bst_remove(linktree root, tn_datatype data); linktree bst_find(linktree root, tn_datatype data); #ifdef AVL linktree avl_insert(linktree root, linktree new); linktree avl_remove(linktree root, tn_datatype data); linktree avl_rotate_left (linktree root); linktree avl_rotate_right(linktree root); linktree avl_rotate_leftright(linktree root); linktree avl_rotate_rightleft(linktree root); static int height(linktree root) { return root==NULL ? 0 : root->height; } #endif static linktree new_node(tn_datatype data) { linktree new = malloc(sizeof(treenode)); if(new != NULL) { new->data = data; new->lchild = NULL; new->rchild = NULL; #ifdef AVL new->height = 1; #endif #ifdef RB new->parent = NULL; new->color = RED; #endif } return new; } #endif

head4queue.h

////////////////////////////////////////////////////////////////// // Description: 本文件为队列核心头文件。 // 任何使用本队列算法的程序,在包含本头文件之前都需要 // 将如下宏定义成队列节点需要表达的数据类型: // // QUEUE_NODE_DATATYPE // // 否则队列的节点数据类型一律默认为 int // ////////////////////////////////////////////////////////////////// #ifndef _HEAD4QUEUE_H__ #define _HEAD4QUEUE_H__ #include "commonheader.h" #ifndef QUEUE_NODE_DATATYPE #define QUEUE_NODE_DATATYPE int #endif typedef QUEUE_NODE_DATATYPE qn_datatype; struct _queue_node { qn_datatype data; struct _queue_node *next; }; typedef struct _queuenode { struct _queue_node *front; struct _queue_node *rear; #ifdef QUEUE_SIZE int size; #endif }queuenode, *linkqueue; bool is_empty_q(linkqueue); bool out_queue(linkqueue, qn_datatype *); bool en_queue(linkqueue, qn_datatype); linkqueue init_queue(void); #ifdef QUEUE_SIZE int queue_size(linkqueue *); #endif #endif

commonheader.h

#ifndef _COMMONHEADER_H_ #define _COMMONHEADER_H_ #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <unistd.h> #include <string.h> #include <strings.h> #include <time.h> #include <errno.h> #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> #include <sys/ipc.h> #include <sys/sem.h> #include <sys/shm.h> #include <sys/msg.h> #include <semaphore.h> #include <fcntl.h> #include <pthread.h> #endif

drawtree.h

////////////////////////////////////////////////////////////////// // Description: 使用C语言写一页webpage ////////////////////////////////////////////////////////////////// #ifndef _DRAWTREE_H_ #define _DRAWTREE_H_ #include "commonheader.h" #include "head4tree.h" #ifndef QUEUE_NODE_DATATYPE #define QUEUE_NODE_DATATYPE linktree #endif #include "head4queue.h" static char page_begin[] = "<html><head><title>tree map" "</title></head><body>" "<table border=0 cellspacing" "=0 cellpadding=0>"; static char line_begin[] = "<tr>"; static char line_end [] = "</tr>"; static char space [] = "<td>&nbsp;</td>"; static char underline [] = "<td style=\"border-bottom:" "1px solid #58CB64\">&nbsp;" "</td>"; #ifdef RB static char data_begin_red[] = "<td bgcolor=\"#FF0000\";style=" "\"border:1px sol" "id #58CB64;background-colo" "r:#DDF1D8;PADDING:2px;\" t" "itle=\"level: 1\">"; static char data_begin_blk[] = "<td bgcolor=\"#000000\";style=" "\"border:1px sol" "id #58CB64;background-colo" "r:#DDF1D8;PADDING:2px;\" t" "itle=\"level: 1\"><font color" "=\"#FFFFFF\">"; static char data_end_red[] = "</td>"; static char data_end_blk[] = "</font></td>"; #else static char data_begin[] = "<td style=\"border:1px sol" "id #58CB64;background-colo" "r:#DDF1D8;PADDING:2px;\" t" "itle=\"level: 1\">"; static char data_end [] = "</td>"; #endif static char page_end [] = "</table></body></html>"; #define MAX_NODES_NUMBER 100 #define FILENAME 32 static tn_datatype central_order[MAX_NODES_NUMBER]; void putunderline(int fd, int num); void putspace(int fd, int num); #ifdef RB void putdata(int fd, linktree p); #else void putdata(int fd, int data); #endif int get_index(tn_datatype data); void create_index(linktree root); void data_leftside(int fd, linktree root, int spaces); int data_rightside(int fd, linktree root); void start_page(int fd); void end_page(int fd); void draw(linktree root); #endif

drawtree提供的draw函数用来在webpage上面把树画出来。

然后是c文件:queue.c drawtree.c bst.c

queue.c

//////////////////////////////////////////////////////////////////// // Description: 链队列 //////////////////////////////////////////////////////////////////// #include "head4queue.h" linkqueue init_queue(void) { linkqueue q = (linkqueue)malloc(sizeof(queuenode)); q->front = q->rear = (struct _queue_node *)malloc(sizeof(struct _queue_node)); q->rear->next = NULL; return q; } bool is_empty_q(linkqueue q) { return (q->front == q->rear); } bool out_queue(linkqueue q, qn_datatype *pdata) { if(is_empty_q(q)) return false; struct _queue_node *p = q->front; q->front = q->front->next; free(p); *pdata = q->front->data; return true; } bool en_queue(linkqueue q, qn_datatype data) { struct _queue_node *pnew; pnew = (struct _queue_node *)malloc(sizeof(struct _queue_node)); if(pnew == NULL) return false; pnew->data = data; pnew->next = NULL; q->rear->next = pnew; q->rear = pnew; return true; } #ifdef QUEUE_SIZE int queue_size(linkqueue *q) { return q->size; } #endif

drawtree.c

//////////////////////////////////////////////////////////////////// // Description: 将二叉树的逻辑层次结构,用网页展示出来 //////////////////////////////////////////////////////////////////// #include "head4tree.h" #include "drawtree.h" void putunderline(int fd, int num) { int i; for(i=0; i<num; i++) { write(fd, underline, strlen(underline)); } } void putspace(int fd, int num) { int i; for(i=0; i<num; i++) { write(fd, space, strlen(space)); } } #ifdef RB void putdata(int fd, linktree p) { char s[50]; bzero(s, 50); snprintf(s, 50, "%d", p->data); switch(p->color) { case RED: write(fd, data_begin_red, strlen(data_begin_red)); write(fd, s, strlen(s)); write(fd, data_end_red, strlen(data_end_red)); break; case BLACK: write(fd, data_begin_blk, strlen(data_begin_blk)); write(fd, s, strlen(s)); write(fd, data_end_blk, strlen(data_end_blk)); } } #else void putdata(int fd, int data) { char s[50]; bzero(s, 50); snprintf(s, 50, "%d", data); write(fd, data_begin, strlen(data_begin)); write(fd, s, strlen(s)); write(fd, data_end, strlen(data_end)); } #endif static int Index = 0; void create_index(linktree root) { if(Index >= MAX_NODES_NUMBER-1) return; central_order[Index++] = root->data; } int get_index(tn_datatype data) { int i; for(i=0; i<100; i++) { if(central_order[i] == data) return i; } return -1; } void data_leftside(int fd, linktree root, int spaces) { if(root == NULL) return; int s_line=0; if(root->lchild != NULL) { s_line = get_index(root->data)- get_index(root->lchild->data)-1; } putspace(fd, spaces-s_line); putunderline(fd, s_line); } int data_rightside(int fd, linktree root) { if(root == NULL) return 0; int s_line=0; if(root->rchild != NULL) { s_line = get_index(root->rchild->data)- get_index(root->data)-1; } putunderline(fd, s_line); return s_line; } void start_page(int fd) { write(fd, page_begin, strlen(page_begin)); } void end_page(int fd) { write(fd, page_end, strlen(page_end)); } void draw(linktree root) { if(root == NULL) return; time_t t; time(&t); static char filename[FILENAME]; bzero(filename, FILENAME); snprintf(filename, FILENAME, "%u.html", (unsigned)t); int fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, 0644); if(fd == -1) { perror("open() failed"); exit(1); } Index = 0; mid_travel(root, create_index); linkqueue q = init_queue(); linktree tmp = root; int ndata = 1; start_page(fd); while(1) { write(fd, line_begin, strlen(line_begin)); int i, n = 0; int nextline = 0; for(i=0; i<ndata; i++) { int index = get_index(tmp->data); data_leftside(fd, tmp, index-n); #ifdef RB putdata(fd, tmp); #else putdata(fd, tmp->data); #endif int rightline = data_rightside(fd, tmp); if(tmp->lchild != NULL) { nextline++; en_queue(q, tmp->lchild); } if(tmp->rchild != NULL) { nextline++; en_queue(q, tmp->rchild); } if(!out_queue(q, &tmp)) return; n = index + rightline; n++; } write(fd, line_end, strlen(line_end)); ndata = nextline; } end_page(fd); close(fd); }

bst.c

//////////////////////////////////////////////////////////////////// // Description: BST算法实现代码 //////////////////////////////////////////////////////////////////// #include "head4tree.h" #include "drawtree.h" linktree bst_insert(linktree root, linktree new) { if(new == NULL) return root; if(root == NULL) return new; if(new->data > root->data) { root->rchild = bst_insert(root->rchild, new); } else if(new->data < root->data) { root->lchild = bst_insert(root->lchild, new); } else { printf("%d is already exist.\n", new->data); } return root; } linktree bst_find(linktree root, tn_datatype data) { if(root == NULL) return NULL; if(data < root->data) return bst_find(root->lchild, data); else if(data > root->data) return bst_find(root->rchild, data); else return root; } linktree bst_remove(linktree root, tn_datatype n) { if(root == NULL) return NULL; if(n < root->data) root->lchild = bst_remove(root->lchild, n); else if(n > root->data) root->rchild = bst_remove(root->rchild, n); else { linktree tmp; if(root->lchild != NULL) { for(tmp=root->lchild; tmp->rchild!=NULL; tmp=tmp->rchild); root->data = tmp->data; root->lchild = bst_remove(root->lchild, tmp->data); } else if(root->rchild != NULL) { for(tmp=root->rchild; tmp->lchild!=NULL; tmp=tmp->lchild); root->data = tmp->data; root->rchild = bst_remove(root->rchild, tmp->data); } else { free(root); return NULL; } } return root; } int main(void) { linktree root; root = NULL; printf("输入大于0的数插入节点\n"); printf("输入小于0的数删除节点\n"); printf("输入0退出程序\n"); int n; while(1) { scanf("%d", &n); if(n > 0) { linktree new = new_node(n); root = bst_insert(root, new); } else if(n < 0) { root = bst_remove(root, -n); } if(n == 0) break; draw(root); system("firefox -new-tab *.html &"); } system("rm *.html"); return 0; }

该文件里面包含了测试入口函数main,实现了以下功能:
1、输入大于0的整数就插入节点
2、输入小于0的整数就删除其绝对值对应的节点
3、输入0就退出程序
4、退出程序之前用网页把这棵树画出来

运行效果如下:

延伸

目前实现了最很简单的二叉搜索树,但是存在一个问题:这颗树可能会由于插入或删除的节点的随机性导致不平衡,从而影响BST的搜索性能。

什么是二叉树的不平衡?平衡树?红黑树?后面我有时间再一一道来。

总结

本文简单介绍了BST树的概念,并提供了相关的算法实现,演示了运行效果。
后面我有时间会把平衡树和红黑树的知识点及算法实现补充进来,以便日后使用。

Linux环境下BST树算法的具体实现方法有哪些?