用链式结构实现二叉搜索树

先明确几个概念:

树:是一种重要的非线性数据结构,它是数据元素(在树中称为结点)按分支关系组织起来的结构。

二叉树:二叉树是每个节点最多有两个子树的有序树。(树和二叉树的2个主要差别:1. 树中结点的最大度数没有限制,而二叉树结点的最大度数为2;2. 树的结点无左、右之分,而二叉树的结点有左、右之分。)

满二叉树:除最后一层无任何子节点外,每一层上的所有结点都有两个子结点。

完全二叉树:若一棵二叉树至多只有最下面的两层上的结点的度数可以小于2,并且最下层上的结点都集中在该层最左边的若干位置上,则此二叉树成为完全二叉树。

二叉搜索树:又称为二叉排序树。Binary Search Tree,Binary Sort Tree,简写为BST。它或者是一棵空树;或者是具有下列性质的二叉树: (1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值; (2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值; (3)左、右子树也分别为二叉排序树。

下面用链式结构来实现二叉搜索树:

《tree.h》

/*二叉搜索树模块接口*/

#define TREE_TYPE int  //树的值类型

//向二叉搜索树中添加一个不重复的新值
void insert(TREE_TYPE value);

//查找特定值
TREE_TYPE *find(TREE_TYPE value);

//先根遍历二叉搜索树,传入一个函数指针,当遍历每个节点时调用。
void pre_order_traverse(void (*callback)(TREE_TYPE value)); 

//销毁二叉搜索树
void destroy_tree(void);

《l_tree.c》

/*********************使用动态内存分配的链式结构实现二叉搜索树***********************/
#include "tree.h" 
#include <stdio.h>
#include <assert.h>
#include <malloc.h>

typedef struct TREE_NODE
{
    TREE_TYPE value;
    struct TREE_NODE *left;
    struct TREE_NODE *right; 
} TreeNode;

static TreeNode *tree;  //声明指向树根节点的指针

/*插入*/
void insert(TREE_TYPE value)
{
    TreeNode *current;
    TreeNode **link;
    link=&tree; 
    //找到合适的插入位置
    while((current=*link)!=NULL)
    {
        //根据情况,选择进入左子树或又子树。并确认没有重复的值
        if(value<current->value)
        {
            link=&current->left;
        }
        else 
        {
            assert(value!=current->value);
            link=&current->right;
        }
    }
    //分配一个新节点,并链入到二叉搜索树中
    current=malloc(sizeof(TreeNode));
    assert(current!=NULL);
    current->value=value;
    current->left=NULL;    
    current->right=NULL;
    *link=current;
}

/*查询*/
TREE_TYPE *find(TREE_TYPE value)
{
    TreeNode *current;
    current=tree;
    while(current!=NULL&¤t->value!=value)
    {
        if(value<current->value)
        {
            current=current->left;
        }
        else {
            current=current->right;
        }
    }
    if(current!=NULL)
        return &current->value;
    else 
        return NULL;
}

/*
*此方法对每一个遍历到的节点执行一次由用户自定义的callback回调函数
*注意,这个函数并不是用户接口的一部分,故声明为static,即:只能在本文件内访问
*/
static void do_pre_order_traverse(TreeNode *current,void (*callback)(TREE_TYPE value))
{
    if(current!=NULL)
    {
        callback(current->value);
        do_pre_order_traverse(current->left,callback);
        do_pre_order_traverse(current->right,callback);
    }
}

/*遍历*/
void pre_order_traverse(void (*callback)(TREE_TYPE value))
{
    do_pre_order_traverse(tree,callback);
}

static void do_destroy_tree(TreeNode *current)
{
    if(current!=NULL)
    {
        do_destroy_tree(current->left);
        do_destroy_tree(current->right);
        free(current);
    }
}

/*销毁*/
void destroy_tree(void)
{
    do_destroy_tree(tree);
}

《test_tree.c》

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

void callback(TREE_TYPE);

int main(void)
{
    printf("test tree.\n");
    int i;
    int value,*ret;
    //插入6个节点
    for(i=0;i<6;i++)
    {
        printf("value:");
        scanf("%d",&value);
        insert(value);
    }
    printf("\n");
    //遍历输出
    pre_order_traverse(callback);
    printf("\n");
    //查找节点
   for(i=0;i<3;i++) 
    {
        printf("find value:");
        scanf("%d",&value);
        ret=find(value);
        if(ret==NULL)
            printf("not found\n");
        else 
            printf("ok,value:%d\n",*ret);
    }
    //销毁二叉树
    destroy_tree(); 
    return 0;
}

void callback(TREE_TYPE value)
{
    printf("%d,",value);
    //You can do something else here.
}


所需编译命令:

gcc -c l_tree.c -o l_tree.o

ar crv libmytree.a l_tree.o

gcc test_tree.c -o test_tree -L. -lmytree


测试结果如下图所示:




  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值