按照数据结构的课本,栈和队列的下一章知识应该是串,但是c语言中对于字符串都是字符数组的概念,且基本的方法都已经封装了,对于c++来说,直接有string这种数据类型,唯一能讲的应该是KMP算法, 但是没有研究过,数组和广义表也用的很少,都跳过,所以这章将重点介绍二叉树,二叉树讲解讲覆盖二叉树的创建和遍历、线索二叉树、哈夫曼树等,二叉树这一章基本都是递归,对于我来说应该是个挑战,尽量专心研究吧。
树这一节概念比较多,如果光介绍概念和各种不同的二叉树的性质都需要几页纸,但是有一个性质非常重要,就是对于任何一颗二叉树T,如果其终端结点数为n,度为2的结点树为m,则n=m+1(由于没法下标,书上带下标的公式更方便理解),树也是数据结构的常考题和笔试的基本题。
1.有很多题都是这个公式的延伸,如阿里笔试的第12题,原题如下:在一棵度为4的树T中,若有20个度为4的结点,10个度为3的结点,1个度为2的结点,10个度为1的结点,则树T的叶子结点有多少个?
树的度数之和+1=树的总结点数:20*4+10*3+1*2+10*1+n*0+1=20+10+1+10+n =>n=82
2.还有一种题,就是求n个结点的不同形态的二叉树的数目,例如最简单的n=3,当然你可以自己一个一个枚举,但是有数学公式就是1/(n+1)*C(2n,n),可求得答案是1/4*C(6,3)=5,是不是感觉似曾相识,bingo,在介绍n个元素的出栈顺序时也使用的这个,其实都是卡特兰数,具体的可以参看数据结构课本P155页(绿皮书那个),就是图那一章的前一页
3.对于就是求二叉树的的前序(根左右)、中序(左根右)、后序(左右根)遍历也是常见的题目,还有什么已知前序和中序求后序,但是需要记住的是已知前序和后序,不能求出唯一的二叉树,更不用说求中序了
二叉树也有顺序储存结构和链式存储结构,但是大部分的程序都是使用链式存储结构。二叉树链式的存储结构是
struct BiTree{
struct BiTree *lchild,*rchild;
char data;
};
二叉树的代码这块基本都是递归,方便理解,但是递归本身不好理解,多加上断点看看,然后递归的过程需要看成栈的模拟过程,创建二叉树的代码如下:
struct BiTree* createTree(){
char ch;
scanf("%c",&ch); //实际输入是一个字符串,书上的例子是ABC##DE#G##F###,让scanf自动读入洗一个字符
struct BiTree *root;
if(ch=='#') root=NULL;
else{
if(!(root=(struct BiTree*)malloc(sizeof(struct BiTree)))) return NULL;
root->data=ch;
root->lchild=createTree();
root->rchild=createTree();
}
return root;
}
先序、中序和后序的代码基本都一样,也是递归,理解了一个也就是三个了
void preOrder(struct BiTree *root){
if(root==NULL) return;
printf("%c",root->data);
preOrder(root->lchild);
preOrder(root->rchild);
}
void inOrder(struct BiTree *root){
if(root==NULL) return;
inOrder(root->lchild);
printf("%c",root->data);
inOrder(root->rchild);
}
void postOrder(struct BiTree *root){
if(root==NULL) return;
postOrder(root->lchild);
postOrder(root->rchild);
printf("%c",root->data);
}
但是书还有另外一种遍历,就是层次遍历,但是需要借助数据结构队列的知识,例如一个节点为8个的完全二叉树,按找英文字母顺序表示这8个结点,遍历的过程是:先把A入队,然后A的左右结点BC入队,然后A出对,然后B的左右结点入队,B出对,然后C入队……(shift+^=省略号)
代码如下:
void levelOrder(struct BiTree *root){
queue<struct BiTree *>q;
q.push(root);
while(!q.empty()){
if(q.front()->lchild!=NULL) q.push(q.front()->lchild);
if(q.front()->rchild!=NULL) q.push(q.front()->rchild);
printf("%c",q.front()->data);
q.pop();
}
}
总的代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <queue>
using namespace std;
#define MAXN 80
struct BiTree{
struct BiTree *lchild,*rchild;
char data;
};
struct BiTree* createTree(){
char ch;
scanf("%c",&ch);
struct BiTree *root;
if(ch=='#') root=NULL;
else{
if(!(root=(struct BiTree*)malloc(sizeof(struct BiTree)))) return NULL;
root->data=ch;
root->lchild=createTree();
root->rchild=createTree();
}
return root;
}
void preOrder(struct BiTree *root){
if(root==NULL) return;
printf("%c",root->data);
preOrder(root->lchild);
preOrder(root->rchild);
}
void inOrder(struct BiTree *root){
if(root==NULL) return;
inOrder(root->lchild);
printf("%c",root->data);
inOrder(root->rchild);
}
void postOrder(struct BiTree *root){
if(root==NULL) return;
postOrder(root->lchild);
postOrder(root->rchild);
printf("%c",root->data);
}
void levelOrder(struct BiTree *root){
queue<struct BiTree *>q;
q.push(root);
while(!q.empty()){
if(q.front()->lchild!=NULL) q.push(q.front()->lchild);
if(q.front()->rchild!=NULL) q.push(q.front()->rchild);
printf("%c",q.front()->data);
q.pop();
}
}
int main(){
char str[MAXN];
struct BiTree *root=createTree();
preOrder(root);
printf("\n");
inOrder(root);
printf("\n");
postOrder(root);
printf("\n");
levelOrder(root);
printf("\n");
return 0;
}
未完待续 下一节 二叉树算法二之中序线索
如果文章有什么错误或者有什么建议,欢迎提出,大家共同交流,一起进步
文章转载请注明出处,请尊重知识产权