第51课 - 二叉排序树

1. 二分查找的回顾

(1)二分查找的特点

二分查找能够提高有序表中数据元素的查找速度。

二分查找的时间复杂度为O(log2n)。

二分查找是一种静态查找。

(2)二分查找的不足

当查找表经常变化时,二分查找的整体性能急剧下降。

2. 二分查找的硬伤

二分查找基于有序表。

当需要插入或者删除数据元素时,为了能够继续进行二分查找,需要大规模挪动有序表中的数据元素,使得插入或者删除后的线性表保持有序。

3. 二分查找的过程

二分查找的过程是一棵二叉树!

特点:

任意一个结点的值都大于其左子树的所有结点值。

任意一个结点的值都小于其右子树的所有结点值。

4. 新的想法

直接组织一棵具有二分查找特性的二叉树。二分查找过程即变换为对树结点的查找过程,由二分查找的特性可知树结点查找的时间复杂度为O(log2n),只在叶结点处插入新结点即可保持特性不变,删除树结点时也可以容易的保持特性不变

5. 二叉排序树

二叉排序树是一棵空树,或者若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左右子树也分别是二叉排序树。

插入:其插入操作总是在叶结点处进行。

删除:叶结点:直接删除;非叶结点:查找合适的替代者后删除。

如何为删除操作查找合适的替代者?

有一个孩子的结点:用孩子结点代替原结点。

有两个孩子的结点:用中序遍历下的直接前驱替换原结点。

6. 程序

main.c

#include <stdio.h>

#include <stdlib.h>

#include "BSTree.h"

/* run this program using the console pauser or add your own getch, system("pause") or input loop */

struct Node

{

BSTreeNode header;

char v;

};

void printf_data(BSTreeNode* node)

{

if( node != NULL )

{

printf("%c", ((struct Node*)node)->v);

}

}

int compare_key(BSKey* k1, BSKey* k2)

{

return (int)k1 - (int)k2;

}

int main(int argc, char *argv[])

{

BSTree* tree = BSTree_Create();

struct Node n1 = {{(BSKey*)1, NULL, NULL}, 'A'};

struct Node n2 = {{(BSKey*)2, NULL, NULL}, 'B'};

struct Node n3 = {{(BSKey*)3, NULL, NULL}, 'C'};

struct Node n4 = {{(BSKey*)4, NULL, NULL}, 'D'};

struct Node n5 = {{(BSKey*)5, NULL, NULL}, 'E'};

struct Node n6 = {{(BSKey*)6, NULL, NULL}, 'F'};

BSTree_Insert(tree, (BSTreeNode*)&n4, compare_key);

BSTree_Insert(tree, (BSTreeNode*)&n1, compare_key);

BSTree_Insert(tree, (BSTreeNode*)&n3, compare_key);

BSTree_Insert(tree, (BSTreeNode*)&n6, compare_key);

BSTree_Insert(tree, (BSTreeNode*)&n2, compare_key);

BSTree_Insert(tree, (BSTreeNode*)&n5, compare_key);

printf("Height: %d\n", BSTree_Height(tree));

printf("Degree: %d\n", BSTree_Degree(tree));

printf("Count: %d\n", BSTree_Count(tree));

printf("Search Key 5: %c\n", ((struct Node*)BSTree_Get(tree, (BSKey*)5, compare_key))->v);

printf("Full Tree: \n");

BSTree_Display(tree, printf_data, 4, '-');

BSTree_Delete(tree, (BSKey*)4, compare_key);

printf("After Delete Key 4: \n");

printf("Height: %d\n", BSTree_Height(tree));

printf("Degree: %d\n", BSTree_Degree(tree));

printf("Count: %d\n", BSTree_Count(tree));

printf("Full Tree: \n");

BSTree_Display(tree, printf_data, 4, '-');

BSTree_Clear(tree);

printf("After Clear: \n");

printf("Height: %d\n", BSTree_Height(tree));

printf("Degree: %d\n", BSTree_Degree(tree));

printf("Count: %d\n", BSTree_Count(tree));

BSTree_Display(tree, printf_data, 4, '-');

BSTree_Destroy(tree);

return 0;

}

BSTree.h

#ifndef _BSTREE_H_

#define _BSTREE_H_

typedef void BSTree;

typedef void BSKey;

typedef struct _tag_BSTreeNode BSTreeNode;

struct _tag_BSTreeNode

{

BSKey* key;

BSTreeNode* left;

BSTreeNode* right;

};

typedef void (BSTree_Printf)(BSTreeNode*);

typedef int (BSTree_Compare)(BSKey*, BSKey*);

BSTree* BSTree_Create();

void BSTree_Destroy(BSTree* tree);

void BSTree_Clear(BSTree* tree);

int BSTree_Insert(BSTree* tree, BSTreeNode* node, BSTree_Compare* compare);

BSTreeNode* BSTree_Delete(BSTree* tree, BSKey* key, BSTree_Compare* compare);

BSTreeNode* BSTree_Get(BSTree* tree, BSKey* key, BSTree_Compare* compare);

BSTreeNode* BSTree_Root(BSTree* tree);

int BSTree_Height(BSTree* tree);

int BSTree_Count(BSTree* tree);

int BSTree_Degree(BSTree* tree);

void BSTree_Display(BSTree* tree, BSTree_Printf* pFunc, int gap, char div);

#endif

BSTree.c

#include <stdio.h>

#include <malloc.h>

#include "BSTree.h"

typedef struct _tag_BSTree TBSTree;

struct _tag_BSTree

{

int count;

BSTreeNode* root;

};

static void recursive_display(BSTreeNode* node, BSTree_Printf* pFunc, int format, int gap, char div) // O(n)

{

int i = 0;

if( (node != NULL) && (pFunc != NULL) )

{

for(i=0; i<format; i++)

{

printf("%c", div);

}

pFunc(node);

printf("\n");

if( (node->left != NULL) || (node->right != NULL) )

{

recursive_display(node->left, pFunc, format + gap, gap, div);

recursive_display(node->right, pFunc, format + gap, gap, div);

}

}

else

{

for(i=0; i<format; i++)

{

printf("%c", div);

}

printf("\n");

}

}

static int recursive_count(BSTreeNode* root) // O(n)

{

int ret = 0;

if( root != NULL )

{

ret = recursive_count(root->left) + 1 + recursive_count(root->right);

}

return ret;

}

static int recursive_height(BSTreeNode* root) // O(n)

{

int ret = 0;

if( root != NULL )

{

int lh = recursive_height(root->left);

int rh = recursive_height(root->right);

ret = ((lh > rh) ? lh : rh) + 1;

}

return ret;

}

static int recursive_degree(BSTreeNode* root) // O(n)

{

int ret = 0;

if( root != NULL )

{

if( root->left != NULL )

{

ret++;

}

if( root->right != NULL )

{

ret++;

}

if( ret == 1 )

{

int ld = recursive_degree(root->left);

int rd = recursive_degree(root->right);

if( ret < ld )

{

ret = ld;

}

if( ret < rd )

{

ret = rd;

}

}

}

return ret;

}

static int recursive_insert(BSTreeNode* root, BSTreeNode* node, BSTree_Compare* compare)

{

int ret = 1;

int r = compare(node->key, root->key);

if( r == 0 )

{

ret = 0;

}

else if( r < 0 )

{

if( root->left != NULL )

{

ret = recursive_insert(root->left, node, compare);

}

else

{

root->left = node;

}

}

else if( r > 0 )

{

if( root->right != NULL )

{

ret = recursive_insert(root->right, node, compare);

}

else

{

root->right = node;

}

}

}

static BSTreeNode* recursive_get(BSTreeNode* root, BSKey* key, BSTree_Compare* compare)

{

BSTreeNode* ret = NULL;

if( root != NULL )

{

int r = compare(key, root->key);

if( r == 0 )

{

ret = root;

}

else if( r < 0 )

{

ret = recursive_get(root->left, key, compare);

}

else if( r > 0 )

{

ret = recursive_get(root->right, key, compare);

}

}

return ret;

}

static BSTreeNode* delete_node(BSTreeNode** pRoot)

{

BSTreeNode* ret = *pRoot;

if( (*pRoot)->right == NULL )

{

*pRoot = (*pRoot)->left;

}

else if( (*pRoot)->left == NULL )

{

*pRoot = (*pRoot)->right;

}

else

{

BSTreeNode* g = *pRoot;

BSTreeNode* c = (*pRoot)->left;

while( c->right != NULL )

{

g = c;

c = c->right;

}

if( g != *pRoot )

{

g->right = c->left;

}

else

{

g->left = c->left;

}

c->left = (*pRoot)->left;

c->right = (*pRoot)->right;

*pRoot = c;

}

return ret;

}

static BSTreeNode* recursive_delete(BSTreeNode** pRoot, BSKey* key, BSTree_Compare* compare)

{

BSTreeNode* ret = NULL;

if( (pRoot != NULL) && (*pRoot != NULL) )

{

int r = compare(key, (*pRoot)->key);

if( r == 0 )

{

ret = delete_node(pRoot);

}

else if( r < 0 )

{

ret = recursive_delete(&((*pRoot)->left), key, compare);

}

else if( r > 0 )

{

ret = recursive_delete(&((*pRoot)->right), key, compare);

}

}

return ret;

}

BSTree* BSTree_Create() // O(1)

{

TBSTree* ret = (TBSTree*)malloc(sizeof(TBSTree));

if( ret != NULL )

{

ret->count = 0;

ret->root = NULL;

}

return ret;

}

void BSTree_Destroy(BSTree* tree) // O(1)

{

free(tree);

}

void BSTree_Clear(BSTree* tree) // O(1)

{

TBSTree* btree = (TBSTree*)tree;

if( btree != NULL )

{

btree->count = 0;

btree->root = NULL;

}

}

int BSTree_Insert(BSTree* tree, BSTreeNode* node, BSTree_Compare* compare)

{

TBSTree* btree = (TBSTree*)tree;

int ret = (btree != NULL) && (node != NULL) && (compare != NULL);

if( ret )

{

node->left = NULL;

node->right = NULL;

if( btree->root == NULL )

{

btree->root = node;

}

else

{

ret = recursive_insert(btree->root, node, compare);

}

if( ret )

{

btree->count++;

}

}

return ret;

}

BSTreeNode* BSTree_Delete(BSTree* tree, BSKey* key, BSTree_Compare* compare)

{

TBSTree* btree = (TBSTree*)tree;

BSTreeNode* ret = NULL;

if( (btree != NULL) && (key != NULL) && (compare != NULL) )

{

ret = recursive_delete(&btree->root, key, compare);

if( ret != NULL )

{

btree->count--;

}

}

return ret;

}

BSTreeNode* BSTree_Get(BSTree* tree, BSKey* key, BSTree_Compare* compare)

{

TBSTree* btree = (TBSTree*)tree;

BSTreeNode* ret = NULL;

if( (btree != NULL) && (key != NULL) && (compare != NULL) )

{

ret = recursive_get(btree->root, key, compare);

}

return ret;

}

BSTreeNode* BSTree_Root(BSTree* tree) // O(1)

{

TBSTree* btree = (TBSTree*)tree;

BSTreeNode* ret = NULL;

if( btree != NULL )

{

ret = btree->root;

}

return ret;

}

int BSTree_Height(BSTree* tree) // O(n)

{

TBSTree* btree = (TBSTree*)tree;

int ret = 0;

if( btree != NULL )

{

ret = recursive_height(btree->root);

}

return ret;

}

int BSTree_Count(BSTree* tree) // O(1)

{

TBSTree* btree = (TBSTree*)tree;

int ret = 0;

if( btree != NULL )

{

ret = btree->count;

}

return ret;

}

int BSTree_Degree(BSTree* tree) // O(n)

{

TBSTree* btree = (TBSTree*)tree;

int ret = 0;

if( btree != NULL )

{

ret = recursive_degree(btree->root);

}

return ret;

}

void BSTree_Display(BSTree* tree, BSTree_Printf* pFunc, int gap, char div) // O(n)

{

TBSTree* btree = (TBSTree*)tree;

if( btree != NULL )

{

recursive_display(btree->root, pFunc, 0, gap, div);

}

}

小结:

(1)      二分查找仅适用于静态查找的情形。

(2)      二叉排序树是从二分查找的过程总结而来的一种数据结构。

(3)      二叉排序树的查找效率和二分查找相同。

(4)      二叉排序树是特殊的二叉树其插入和删除操作必须保证其二叉排序的性质不变。

转载于:https://www.cnblogs.com/free-1122/p/11336115.html

数据--第51课 - 二叉排序树相关推荐

  1. 当且仅当函数依赖a→b在r上成立_数据库第06章关系数据理习题课.ppt

    您所在位置:网站首页 > 海量文档 &nbsp>&nbsp计算机&nbsp>&nbsp数据结构与算法 数据库第06章关系数据理习题课.ppt36页 本 ...

  2. python逐笔输入数据_知到智慧树Python数据分析与数据可视化结课测验

    知到智慧树Python数据分析与数据可视化结课测验答案 更多相关问题 已知三角形三个顶点的坐标是A(-1,2,3),B(1,1,1),C(0,0,5),试证三角形ABC是直角三角形,并求角B-- Wh ...

  3. 大数据入门第一课 Hadoop基础知识与电商网站日志数据分析

    大数据入门第一课 Hadoop基础知识与电商网站日志数据分析 本课程从Hadoop核心技术入手,以电商项目为依托,带领你从0基础开始上手,逐步掌握大数据核心技术(如:HDFS.YARN.MapRedu ...

  4. 视频教程-大数据分析师实战课-大数据

    大数据分析师实战课 任老师,Cloudera管理/开发/分析认证讲师,华为高级特聘讲师,新华三大学高级特聘讲师,中国大数据技术与应用联盟高级讲师,全国高校大数据联盟特聘讲师,中国移动高级讲师,前IBM ...

  5. 大数据学习第一课:虚拟机安装配置

    本章主要内容 VirtualBox下安装CentOS7 Minimal版本 Minimal版本Centos7静态IP网络设置 ssh免密登录设置 我们现在身处数据时代,大数据和人工智能已经逐渐渗透到我 ...

  6. 【BLE MIDI】MIDI 文件速度设置识别 ( 查找 midi 文件中速度相关的二进制数据 | FF 51 03 速度设置指令 )

    文章目录 一.问题说明 二.查找 midi 文件中速度相关的二进制数据 一.问题说明 解析 midi 文件时 , 发现音符解析出现异常 ; 是根据 音符 微秒时长 , 统计音符时 , 发现音符解析出现 ...

  7. 串口发数据到android数据错误,51单片机通过蓝牙串口模块发送JSON数据给安卓手机故障解决办法...

    原标题:51单片机通过蓝牙串口模块发送JSON数据给安卓手机故障解决办法 JSON(Java Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式.它基于 ECMA (欧洲计 ...

  8. c语言spi发送12位数据,【51单片机】普通I/O口模拟SPI口C语言程序

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 89C51系列单片机都不带SPI口,所在在这种情况下,我们可以模拟SPI口来现实我们要的功能,程序如下: //---------------------- ...

  9. Python数据可视化(微课版)-简介

    前 言 当前,我们正处于大数据爆发的时代,涌现出大量不同类型的时空数据和非时空数据,信息激流使个人.企业和社会对大数据的依赖不断深化,与此同时,数据可视化研究已成为一个新的时代命题,与立体建模等方法相 ...

  10. 新概念英语1册51课

    Lesson 51 A pleasnt climate 气候宜人 Hans:Where do you come from? 你从哪里来? Dimitri:I come from Greece. 我来自 ...

最新文章

  1. 5分钟 NLP 系列: Word2Vec和Doc2Vec
  2. 每打一通AI骚扰电话,就会被罚款7万块,这是美国国会刚刚通过的法案
  3. 计算机会计的应用控制主要有哪些,计算机会计习题全多选
  4. OPNsense 18.7.X汉化包发布!
  5. CVPR 2018论文解读 | 基于域适应弱监督学习的目标检测
  6. 0420第一次团队合作
  7. 今日头条关键词排名怎么搜索_公众号搜索关键词排名、公众号怎么排名靠前
  8. 7-8 统计工龄 (20 分)
  9. 浅谈工业4.0时代,深信服adesk桌面云如何助力智能工厂.
  10. 计算机械公差什么软件好,Tolerance机械公差查询工具
  11. 中国居民消费价格指数(CPI)月度汇总数据集(1990.1.31--2020.2.29)
  12. Ember项目引入js依赖
  13. 模电数电EDA实验开发系统实验设备QY-MS301D
  14. FTP指的是什么协议?由什么组成?有什么作用?
  15. 各大手机厂商快应用入口
  16. 菜鸟驿站巴枪APP下载
  17. AS5047开发简介
  18. 推荐10个HTML5游戏网站
  19. 命令打开java控制面板
  20. 网易云信短信接口java,调用网易云短信验证码接口Demo

热门文章

  1. 如何设计信息安全领域的实时安全基线引擎
  2. 如何正确使用 Flink Connector?
  3. python基础篇——简单编码与解码的战争
  4. ipmi java sdk,IPMI Library for Java
  5. android快速充电实现_Android 8.0 慢充和快充提示语的实现原理
  6. mac perl dbd mysql_Install DBD::mysql for Perl in XAMPP in Mac , solving errors
  7. 学生选课系统代码-4c【interface】视图层代码【MVC--c】代码
  8. python excel案例导入jira_用Python脚本批量添加JIRA用户,python,jira
  9. 经典神经网络 -- DPN : 设计原理与pytorch实现
  10. SpringCloud Alibaba - Nacos 作为配置中心 读取Yaml配置信息