c++(排序二叉树)
前面我们讲过双向链表的数据结构。每一个循环节点有两个指针,一个指向前面一个节点,一个指向后继节点,这样所有的节点像一颗颗珍珠一样被一根线穿在了一起。然而今天我们讨论的数据结构却有一点不同,它有三个节点。它是这样定义的:
typedef struct _TREE_NODE
{
int data;
struct _TREE_NODE* parent;
struct _TREE_NODE* left_child;
struct _TREE_NODE* right_child;
}TREE_NODE;
根据上面的数据结构,我们看到每一个数据节点都有三个指针,分别是:指向父母的指针,指向左孩子的指针,指向右孩子的指针。每一个节点都是通过指针相互连接的。相连指针的关系都是父子关系。那么排序二叉树又是什么意思呢?其实很简单,只要在二叉树的基本定义上增加两个基本条件就可以了:(1)所有左子树的节点数值都小于此节点的数值;(2)所有右节点的数值都大于此节点的数值。
既然看到了节点的定义,那么我们并可以得到,只要按照一定的顺序遍历,可以把二叉树中的节点按照某一个顺序打印出来。那么,节点的创建、查找、遍历是怎么进行的呢,二叉树的高度应该怎么计算呢?我们一一道来。
1)创建二叉树节点
TREE_NODE* create_tree_node(int data)
{
TREE_NODE* pTreeNode = NULL;
pTreeNode = (TREE_NODE*)malloc(sizeof(TREE_NODE));
assert(NULL != pTreeNode); memset(pTreeNode, 0, sizeof(TREE_NODE));
pTreeNode->data = data;
return pTreeNode;
}
分析:我们看到,二叉树节点的创建和我们看到的链表节点、堆栈节点创建没有什么本质的区别。首先需要为节点创建内存,然后对内存进行初始化处理。最后将输入参数data输入到tree_node当中即可。
2)数据的查找
TREE_NODE* find_data_in_tree_node(const TREE_NODE* pTreeNode, int data)
{
if(NULL == pTreeNode)
return NULL; if(data == pTreeNode->data)
return (TREE_NODE*)pTreeNode;
else if(data < pTreeNode->data)
return find_data_in_tree_node(pTreeNode->left_child, data);
else
return find_data_in_tree_node(pTreeNode->right_child, data);
}
分析:我们的查找是按照递归迭代进行的。因为整个二叉树是一个排序二叉树,所以我们的数据只需要和每一个节点依次比较就可以了,如果数值比节点数据小,那么向左继续遍历;反之向右继续遍历。如果遍历下去遇到了NULL指针,只能说明当前的数据在二叉树中还不存在。
3)数据统计
int count_node_number_in_tree(const TREE_NODE* pTreeNode)
{
if(NULL == pTreeNode)
return 0; return 1 + count_node_number_in_tree(pTreeNode->left_child)
+ count_node_number_in_tree(pTreeNode->right_child);
}
分析:和上面查找数据一样,统计的工作也比较简单。如果是节点指针,那么直接返回0即可,否则就需要分别统计左节点树的节点个数、右节点树的节点个数,这样所有的节点总数加起来就可以了。
4)按照从小到大的顺序打印节点的数据
void print_all_node_data(const TREE_NODE* pTreeNode)
{
if(pTreeNode){
print_all_node_data(pTreeNode->left_child);
printf("%d\n", pTreeNode->data);
print_all_node_data(pTreeNode->right_child);
}
}
分析:因为二叉树本身的特殊性,按顺序打印二叉树的函数本身也比较简单。首先打印左子树的节点,然后打印本节点的数值,最后打印右子树节点的数值,这样所有节点的数值就都可以打印出来了。
5)统计树的高度
int calculate_height_of_tree(const TREE_NODE* pTreeNode)
{
int left, right;
if(NULL == pTreeNode)
return 0; left = calculate_height_of_tree(pTreeNode->left_child);
right = calculate_height_of_tree(pTreeNode->right_child);
return (left > right) ? (left + 1) : (right + 1);
}
分析:树的高度其实是指所有叶子节点中,从根节点到叶子节点的最大高度可以达到多少。当然,程序中表示得已经很明白了,如果节点为空,那么很遗憾,节点的高度为0;反之如果左子树的高度大于右子树的高度,那么整个二叉树的节点高度就是左子树的高度加上1;如果右子树的高度大于左子树的高度,那么整个二叉树的高度就是右子树的高度加上1。计算树的高度在我们设计平衡二叉树的时候非常有用,特别是测试的时候,希望大家多多理解,熟练掌握。
总结:
1)二叉树是所有树的基础,后续的平衡二叉树、线性二叉树、红黑树、复合二叉树、b树、b+树都以此为基础,希望大家好好学习;
2)二叉树很多的操作是和堆栈紧密联系在一起的,如果大家暂时理解不了递归,可以用循环或者堆栈代替;
3)实践出真知,大家可以自己对排序二叉树的代码多多练习。不瞒大家说,我个人写平衡二叉树不下20多遍,即使这样也不能保证每次都正确;即使这样,我每次写代码的都有不同的感觉。
c++(排序二叉树)的更多相关文章
- C++11 智能指针unique_ptr使用 -- 以排序二叉树为例
用智能指针可以简化内存管理.以树为例,如果用普通指针,通常是在插入新节点时用new,在析构函数中调用delete:但有了unique_ptr类型的智能指针,就不需要在析构函数中delete了,因为当u ...
- 记忆化搜索 codevs 2241 排序二叉树
codevs 2241 排序二叉树 ★ 输入文件:bstree.in 输出文件:bstree.out 简单对比时间限制:1 s 内存限制:128 MB [问题描述] 一个边长为n的正三 ...
- 数据结构与算法系列研究五——树、二叉树、三叉树、平衡排序二叉树AVL
树.二叉树.三叉树.平衡排序二叉树AVL 一.树的定义 树是计算机算法最重要的非线性结构.树中每个数据元素至多有一个直接前驱,但可以有多个直接后继.树是一种以分支关系定义的层次结构. a.树是n ...
- c++(排序二叉树线索化)
前面我们谈到了排序二叉树,还没有熟悉的同学可以看一下这个,二叉树基本操作.二叉树插入.二叉树删除1.删除2.删除3.但是排序二叉树也不是没有缺点,比如说,如果我们想在排序二叉树中删除一段数据的节点怎么 ...
- c++(排序二叉树删除)
相比较节点的添加,平衡二叉树的删除要复杂一些.因为在删除的过程中,你要考虑到不同的情况,针对每一种不同的情况,你要有针对性的反应和调整.所以在代码编写的过程中,我们可以一边写代码,一边写测试用例.编写 ...
- JavaScript实现排序二叉树的相关算法
1.创建排序二叉树的构造函数 /** * 创建排序二叉树的构造函数 * @param valArr 排序二叉树中节点的值 * @constructor */ function BinaryTree(v ...
- Java编程的逻辑 (42) - 排序二叉树
本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...
- (原创)像极了爱情的详解排序二叉树,一秒get
排序二叉树(建立.查找.删除) 二叉树我们已经非常熟悉了,但是除了寻常的储存数据.遍历结构,我们还能用二叉树做什么呢? 我们都知道不同的遍历方式会对相同的树中产生不同的序列结果,排序二叉树就是利用二叉 ...
- 并查集&线段树&树状数组&排序二叉树
超级无敌巨牛逼并查集(带权并查集)https://vjudge.net/problem/UVALive-4487 带删点的加权并查集 https://vjudge.net/problem/UVA-11 ...
随机推荐
- C#中MessageBox用法大全(转)
我们在程序中经常会用到MessageBox. MessageBox.Show()共有21中重载方法.现将其常见用法总结如下: 1.MessageBox.Show("Hello~~~~&quo ...
- 正确使用volatile场景--状态标志
同步机制:volatile 特点:可见性:不具备原子性 每个线程有自己单独的内存:如果线程1和线程2公用一个变量name:如果两个线程并发进行,并且需要访问变量name:如果这个变量具有了可见性,线程 ...
- xampp的安装和配置
这几天一直在做一个网站,客户要求要用PHP修改WordPress的themes,目的是交付完成后,客户自己管理方便. 以前从没有涉及过PHP,用的是jsp,但是,既然已经选择接受,就只能让自己去适应客 ...
- C# DataGridView 列的显示顺序
this.dataGridView1.Columns["列名"].DisplayIndex=Convert.ToInt32("你要放置的位置")
- MySQL查询(进阶)(每个标点都是重点)
MySQL 是工作中很普遍的需要用到的,所以必须掌握,而 之前我们一直说的都是怎么存. 你只会存不会取有个屁用.所以希望大家在如何查询读取数据这方面多下点功夫. 这篇和上一篇都是干货,我也是第一次学. ...
- zookeeper部署到linux操作步骤
安装zookeeper1. 上传上传zookeeper,在\01课前资料\02技术资料2. 移动[root@itcast-01 ~]# mv zookeeper-3.4.6.tar.gz /usr/l ...
- tophat安装
1 依赖软件:bowtie,bowtie2,samtools,boost c++ library 2 建立索引文件: bowtie包括bowtie,bowtie-build, ...
- linux系统中,文件的三种特殊权限
背景介绍 在linux系统中,我们熟知有rwx三种权限,对应所有者,同组用户,其他用户三种用户的权限,一共9个位来指定一个文件的权限情况,通过chmod xxx 来更改权限属性,其中xxx是已八进制表 ...
- ngx-bootstrap使用02 Accordion组件的使用
1 Accordion组件 该组件通过一个可折叠的控制面板去在有限空间内显示更多的信息 according组件在可折叠指令的最外层,该组件提供了一些列的项目列表去显示被折叠的内容,这些项目列表包含he ...
- while100以内的偶数
#显示100以内的偶数 #声明i i = 1 #开始循环条件为i不等于100,执行while代码块 while i != 100: #给i加1 i +=1 #如果循环到此时i的取余运算为0则打印i i ...