zoukankan      html  css  js  c++  java
  • 算法之路——二叉查找树

      二叉查找树是很简单的数据结构,不过却很有用。因为它是篇要写的红黑树的基础。所以还是简单的谈谈,并且把实现代码贴一下。

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

      具体的实现的算法就不多说了,直接贴代码:

    #include <stdio.h>
    #include <time.h>
    #include <stdlib.h>
    #define MAXSIZE 1000
    typedef int ElemType;
    //二叉搜索树的节点
    typedef struct BSNode
    {
    ElemType data;
    struct BSNode * p;
    struct BSNode * left;
    struct BSNode * right;
    }BSNode, * PBSNode;
    //二叉搜索树
    typedef struct BSTree
    {
    PBSNode root;
    }BSTree,* PBSTree;

    int createBSTree (PBSTree tree, ElemType d[], int n);
    PBSNode deleteBSTree (PBSTree tree, PBSNode t);
    int inOrderWalk (PBSNode p);
    PBSNode insertBSTree (PBSTree tree, ElemType d);
    int isEmpty (PBSTree tree);
    PBSNode maximum (PBSNode t);
    PBSNode minimum (PBSNode t);
    PBSNode next (PBSNode t);
    PBSNode precursor (PBSNode t);
    PBSNode search (PBSNode t, ElemType d);
    int walkNext (PBSTree tree);
    int main ()
    {
    ElemType d[MAXSIZE];
    int i;
    int n;
    BSTree tree;
    PBSNode result; //search的结果

    tree.root = NULL; //初始化,这步是必要的。变量的出事值是不确定的。
    srand(time(NULL));

    puts("请输入数据的个数:");
    scanf("%d",&n);
    printf("随机生成的%d个数据是:\n",n);
    for (i = 0; i < n; i++)
    {
    d[i] = rand()%1000;
    printf("%d ",d[i]);
    }
    puts("");
    puts("建树开始");
    createBSTree(&tree, d, n);

    puts("树的内容为:");
    walkNext(&tree); //测试遍历功能
    putchar('\n');

    //测试后继和前驱功能
    if (result = next(tree.root))
    printf("数据%d的后继是%d\n",tree.root->data,result->data);
    else
    printf("数据%d没有后继\n",tree.root->data);

    if (result = precursor(tree.root))
    printf("数据%d的前驱是%d\n",tree.root->data,result->data);
    else
    printf("数据%d没有前驱\n",tree.root->data);

    //测试查询
    result = search (tree.root, d[1]);
    if (result != NULL)
    printf("找到数据%d\n",result->data);
    else
    printf("没有这个数据!\n");

    result = deleteBSTree (&tree, tree.root); //测试删除
    if (result != NULL)
    {
    printf("删除节点%d后,树是:\n",result->data);
    free(result);
    }
    else
    puts("没有删除节点,因为要删除的节点不存在");
    walkNext(&tree);
    puts("");
    return 0;
    }


    PBSNode insertBSTree (PBSTree tree, ElemType d)
    {//插入元素
    //!!!记得插入的元素的初始化,p指向为父母节点,left和right复制为NULL。
    PBSNode t = NULL;
    PBSNode p = NULL;
    int flag = 0; //用来表示插入在左边的树还是右边的树
    t = tree->root;

    if (tree->root == NULL)
    {
    tree->root = (PBSNode)malloc(sizeof(BSNode));
    tree->root->data = d;
    tree->root->p = tree->root->left =tree->root->right = NULL;

    return tree->root;
    }

    while (t != NULL)
    {
    p = t;
    if (d < t->data) //小于
    {
    flag = 0;
    t = t->left;
    }
    else
    {
    if (d > t->data) //大于
    {
    flag = 1;
    t = t->right;
    }
    else //等于,这里用随机化的方法,插入与t的data相等的元素。用flag表示,如果flag == 0 插在left,如果flag == 1插入right
    {
    if ( (flag=rand()%2) == 0)
    t = t->left;
    else
    t = t->right;
    }
    }
    }

    t = (PBSNode)malloc(sizeof(BSNode));
    t->data = d;
    t->p = p;
    t->left = t->right = NULL;

    if (!flag)
    p->left = t;
    else
    p->right = t;

    return t;
    }//insertBSTree

    PBSNode next (PBSNode t)
    {//给出t的后继的节点。如果没有后继,就返回NULL
    PBSNode p; //指示父节点
    if (t->right == NULL)
    {
    p = t->p;
    while (p !=NULL && p->right == t)
    {
    t = p;
    p = t->p;
    }
    return p; //如果是最后一个元素,p的值为NULL
    }
    else
    return minimum(t->right);
    }//next

    PBSNode precursor (PBSNode t)
    {//返回节点t前驱,如果没有前驱,就返回NULL
    PBSNode p;
    if (t->left == NULL)
    {
    p = t->p;
    while (p != NULL && p->left == t)
    {
    t = p;
    p = t->p;
    }
    return p;
    }
    else
    return maximum(t->left);
    }//precusor


    PBSNode deleteBSTree (PBSTree tree, PBSNode t)
    {//删除数据。要求给处数据节点的指针
    PBSNode c = NULL; //c指向要取代被删除节点的子节点
    PBSNode d = NULL;
    ElemType tmp;
    if (t == NULL)
    return NULL;

    //d指向真正要删除的元素的下标。如果t的left和right都有值,则转化为删除t的后继节点,并把后继节点的内容复制给t指向的节点。
    //而其他情况则直接删除t指向的节点
    if (t->left != NULL && t->right != NULL)
    {
    d = next(t);
    //因为实际操作要删除的是d指向的节点,所以先交换data
    tmp = d->data;
    d->data = t->data;
    t->data = tmp;
    }
    else
    d = t;

    //确定c的指向
    if (d->left == NULL)
    c = d->right;
    else
    c = d->left;

    //将c的父亲指针设为d的父亲指针
    if (c != NULL) //c有可能是空的指针
    c->p = d->p;
    if (d->p != NULL)
    {
    if (d->p->left == d)
    d->p->left = c;
    else
    d->p->right = c;
    }
    else
    tree->root = c;

    return d;
    }
    int createBSTree (PBSTree tree, ElemType d[], int n)
    {//用元素的插入建树
    int index = -1;
    int tmp = -1;

    srand(time(NULL));

    while (n--)
    {
    index =(int) rand()%(n+1);//此时共有n+1个数据
    tmp = d[index];
    d[index] = d[n];
    d[n] = tmp;
    insertBSTree(tree, d[n]);
    printf("插入%d\t",d[n]);
    }
    puts("");
    return 0;
    }//createBSTree

    int inOrderWalk (PBSNode p)
    {//中序遍历数组
    if (p == NULL)
    return 0;
    inOrderWalk (p->left);
    printf("%d ",p->data);
    inOrderWalk (p->right);
    return 0;
    }
    PBSNode search (PBSNode t, ElemType d)
    {//在节点t和t的子树中查找d,找到了返回树中该节点的指针
    while (t != NULL &&t->data !=d)
    {
    if (d < t->data)
    t = t->left;
    else
    t = t->right;
    }
    return t;
    }
    PBSNode minimum (PBSNode t)
    {//返回最小值,如果t是NULL返回NULL

    if (t == NULL)
    return NULL;
    while (t->left != NULL)
    t = t->left;
    return t;
    }//minimum

    PBSNode maximum (PBSNode t)
    {//返回最大值,如果t是NULL返回NULL
    if (t == NULL)
    return NULL;
    while (t->right != NULL)
    t = t->right;
    return t;
    }//maximum


    int isEmpty (PBSTree tree)
    {//检查树是否为空
    return tree->root == NULL;
    }//isEmpty

    int walkNext (PBSTree tree)
    {//遍历二叉搜索树。先找到最小的元素,再通过用next()求后继来遍历树
    PBSNode t;
    t = minimum(tree->root);
    while (t != NULL)
    {
    printf("%d\t",t->data);
    t = next(t);
    }
    return 0;
    }//walkNext



  • 相关阅读:
    P1119 灾后重建
    P1824 进击的奶牛
    P3743 kotori的设备
    【MM配置】SAP MM模块配置目录(转)
    【SAP参数文件】SAP参数文件(转)
    【MM】供应商删除
    【Debug】修改数据库表数据的方法
    【MM 单位换算】物料基本单位换算
    EDI RFC IDOC
    【打印配置】SAP打印机配置
  • 原文地址:https://www.cnblogs.com/svking/p/BSTree.html
Copyright © 2011-2022 走看看