二叉树是数据结构中比较有意思的部分
二叉树有两种存储形式
1: 线性表
2:指针
其实链表是很重要的,二叉树就可以看为多条链表组合在一块。
在这里主要是指针来实现的。 这里基本的算法都用到了递归实现
那在二叉树 中重要的算法如下:
a:创建一个二叉树(采用前序,活着中序,活着后序)
b:遍历二叉树(前序,中序,后序)
c:叶子结点的个数
d:树的高度
e:度为一的节点数
f:度为二的节点数
g:有分枝的节点数
h:查找某个节点
可能刚开始不能理解递归,找一个二叉树的图像,根据程序走一遍就基本能理解。
image.png
那这个二叉树的前序遍历为。fcadbehgm
中序遍历为:acbdfehmg
后序遍历为:abdchmgef
//
// main.cpp
// 二叉树,中序遍历
//
// Created by 刘小成 on 2018/10/20.
// Copyright © 2018 刘晨. All rights reserved.
//
include <iostream>
using namespace std;
typedef struct bitNode{
char data;
bitNode *lChild;
bitNode *rChild;
}bitNode;
class Tree{
private:
bitNode *head;
void creatBitNode(bitNode *& t);//创建一棵树
void orderBitNode(bitNode *t);//中序遍历
void inorderBitNode(bitNode *t);//后序遍历
int countLeaf(bitNode *t);//叶子数量
int heightBitNodeTree(bitNode *t);//树高
int oneBitNode(bitNode *t);//度为一 的节点
int twoBitNode(bitNode *t);//度为二的节点
int branchBitNode(bitNode *t);//有分枝的节点
public:
Tree(){head = NULL;}
void creatTree(){
bitNode *temp;
creatBitNode(temp);
head = temp;
}
void orderTree(){
bitNode *t = head;
cout<<"后序遍历的结果是: \t";
orderBitNode(t);
cout<<endl;
}
void inorderTree(){
bitNode *t = head;
cout<<"中序遍历的结果是: \t";
inorderBitNode(t);
cout<<endl;
}
void countLeafTree(){
bitNode *t = head;
cout<<"叶子节点的个数是:\t"<< countLeaf(t)<<endl;
}
void heightTree(){
bitNode *t = head;
cout<<"树的高度是:\t"<< heightBitNodeTree(t)<<endl;
}
void oneBitNodeTree(){
bitNode *t = head;
cout<<"度为一的节点个数是:\t"<<oneBitNode(t)<<endl;
}
void twoBitNodeTree(){
bitNode *t = head;
cout<<"度为二的节点个数是:\t"<<twoBitNode(t)<<endl;
}
void branchTree(){
bitNode *t = head;
cout<<"有分枝的节点个数是:\t"<<branchBitNode(t)<<endl;
}
};
void Tree::creatBitNode(bitNode *&t){
char data;
cin>>data;
if(data == '.') t=NULL;
if(data != '.'){
t = new bitNode;
t->data = data;
creatBitNode(t->lChild);
creatBitNode(t->rChild);
}
}
void Tree::orderBitNode(bitNode *t){
if(t == NULL) return;
else {
orderBitNode(t->lChild);
orderBitNode(t->rChild);
cout<<t->data;
}
}
void Tree::inorderBitNode(bitNode *t){
if (t == NULL) return ;
if(t != NULL){
inorderBitNode(t->lChild);
cout<<t->data;
inorderBitNode(t->rChild);
}
}
int Tree::countLeaf(bitNode *t){
if(t == NULL) return 0;
else {
int m = countLeaf(t->lChild);
int n = countLeaf(t->rChild);
if( m+n == 0) return 1;
else return m+n;
}
}
int Tree::heightBitNodeTree(bitNode *t){
if(t == NULL) return 0;
else{
int m = 1+heightBitNodeTree(t->lChild);
int n = 1+heightBitNodeTree(t->rChild);
return m>n ? m:n;
}
}
int Tree::oneBitNode(bitNode *t){
if(t==NULL) return 0;
else {
if( (t->lChild !=NULL && t->rChild == NULL) || (t->lChild == NULL && t->rChild !=NULL) ){
int m = oneBitNode(t->lChild);
int n = oneBitNode(t->rChild);
return 1+m+n;
}
else{
int m = oneBitNode(t->lChild);
int n = oneBitNode(t->rChild);
return m+n;
}
}
}
int Tree::twoBitNode(bitNode *t){
if( t== NULL) return 0;
else{
if( t->lChild != NULL && t->rChild != NULL){
int m = twoBitNode(t->lChild);
int n = twoBitNode(t->rChild);
return 1+m+n;
}
else{
int m = twoBitNode(t->lChild);
int n = twoBitNode(t->rChild);
return m+n;
}
}
}
int Tree:: branchBitNode(bitNode *t){
if (t == NULL) return 0;
else{
if(t->lChild != NULL || t->rChild != NULL){
int m = branchBitNode(t->lChild);
int n = branchBitNode(t->rChild);
return 1+m+n;
}
else{
int m = branchBitNode(t->lChild);
int n = branchBitNode(t->rChild);
return m+n;
}
}
}
int main(int argc, const char * argv[]) {
cout<<"先序创建一棵树\t\t 用"."表示NULL \n";
cout<<"输入\n";
Tree a ;
a.creatTree();
a.inorderTree();
a.orderTree();
a.countLeafTree();
a.heightTree();
a.oneBitNodeTree();
a.twoBitNodeTree();
a.branchTree();
return 0;
}
在私有方法里面创建递归函数,在公有函数里面调用递归函数。这样做的目的是不会产生多余的变量,变量连接紧密。
在创建递归函数的时候要考虑好函数的出口,好让函数可以返回。然后就要考虑递归函数里面递归的内容,将问题细小化。比如在统计叶子结点有多少个,
那函数的出口就是 这个节点是不是为空,若是空 ,就返回,
函数的递归内容就是。 对一个节点来说,先统计一个它的左子树的节点,在统计一下右子树的节点, 如果两边都是0,那他就是叶子结点,那就叶子结点,返回1,否则就不是叶子结点, 那就返回这个树的左边叶子结点数+右边的节点数。
那在对于树的高度函数来讲
image.png
在创建二叉树的时候要规定一个输入值,当这个值输入的时候那他就NULL。在上面中 作者规定的是“.”,
二叉的这些算法中对于递归的要求比较高。
那对于二叉树的度为一的节点的递归函数思想如下:
image.png那度为二的节点其实和上面的思路是一样的。还有有分枝的节点。
网友评论