目录
2.2.1 前序遍历 void PreOrder(TNode* Root)
2.2.2 中序遍历 void InOrder(TNode* Root)
2.2.3 后序遍历 void BacOrder(TNode* Root)
2.2.4 求树的总节点数 int Treesize(TNode* root)
2.2.5 求叶子结点数 int Leafsize(TNode* root)
2.2.6 求树的高度 int Treeheight(TNode* root)
2.2.7 求二叉树第K层节点数 int Knum(TNode* root,int k)
2.2.8 查找节点为x值所在节点指针 TNode* Treefind(TNode* root, TreeType x)
2.2.9 二叉树的销毁 void TreeDestory(TNode* root)
2.2.10 层序遍历 void TreeLeveorder(TNode* root)
2.2.11 判断一棵树是否为完全二叉树 bool JudgeTree(TNode* root)
1.二叉树的遍历
前序遍历:根 左子树 右子树
中序遍历:左子树 根 右子树
后序遍历:左子树 右子树 根
1.1前序遍历:
(根左右)
图1 图2
首先我们要把所有子树空的地方写上N(代表NULL),如图2。
1.首先从1开始出发,1作为根,2是1的左子树,4是1的右子树,输出1,然后进入2。
遍历序列:1
2. 进入2后,2作为根,3作为2的左子树,N作为2的右子树,输出2,然后进入3。
遍历序列:1 2
3.进入3后,3作为根,N为3的左子树,N为3的右子树,输出3,然后进入左子树的N。
遍历序列:1 2 3
4.进入N后,遇到了N,就输出N,并返回到根(3)。
遍历序列:1 2 3 N
5.返回3后,根和左子树都已经输出,进入右子树的N。同时遇到了N打印并返回。
遍历序列:1 2 3 N N
6.再次返回到了3,根 左子树 右子树 都已经输出了,所以再次返回3的根(2)。返回2后,2作为根,2的左子树已经输出,所以进入2的右子树(N),因为右子树为N,所以输出N即可。
遍历序列:1 2 3 N N N
7. 2作为根,2的左子树右子树有已经输出了,返回2的根(1)。返回1后,1作为根,1的左子树已经输出,直接进入1的右子树(4)即可,进入4后,4作为根,先输出4,然后在进入4的左子树。
遍历序列:1 2 3 N N N 4
8.进入5后,5作为根,所以先输出5,然后进入5的左子树,左子树为N,输出N,然后进入5的右子树,右子树也为N,输出N。
遍历序列:1 2 3 N N N 4 5 N N
9. 5和他的左子树右子树都已经输出,此时返回到5的根(4),4作为根,4的左子树已经输出,此时进入4的右子树(6) ,进入6后,6作为根,先输出6;输出6后进入6的左子树,左子树为N,输出N。然后进入6的右子树,右子树为N,输出N。
遍历序列:1 2 3 N N N 4 5 N N 6 N N
1.2 中序遍历:
(左根右)
图1 图2
1.首先进入1,1作为根,由于是左跟右,所以还不能输出1,要先进入1的左子树(2),进入2后,2作为根,还要进入2的左子树(3),进入3后,3作为根,要先进入3的左子树(N),3的左子树为N,直接输出N,输出N后,左子树已经输出,3作为根,此时可以输出3,3输出后,在进入3的右子树,3的右子树为N,输出N即可。
遍历序列:N 3 N
2. 3作为根的子树已经全部输出,此时返回到3的根(2),2作为根,2的左子树(3)已经输出,此时输出根(2),输出根后,再输出2的右子树(N),右子树为N,直接输出N。
遍历序列:N 3 N 2 N
3. 2作为根的子树已经全部输出,此时返回到2的根(1),1作为根,1的左子树(2)已经输出,此时输出根(1),输出根后,再进入右子树(4),4作为根,要先进入4的左子树(5),5作为根,5的左子树为N,直接输出N,输出N后再输出根(5),输出5,输出5后再进入5的右子树(N),输出N;
遍历序列:N 3 N 2 N 1 N 5 N
4. 5的子树全部输出,此时返回到5的根(4),4作为根,4的左子树(5)输出,此时可以输出根(4),输出根后,再进入根的右子树(6),6作为根,要先进入6的左子树,左子树为N,输出N,然后返回到根(6),此时输出根(6),输出根后,进入6的右子树,右子树为N,输出N。
遍历序列:N 3 N 2 N 1 N 5 N 4 N 6 N
1.3 后序遍历:
(左右根)
图1 图2
1.首先进入1,1作为根,先进入1的左子树(2),2作为根,先进入2的左子树(3),3作为根,先进入3的左子树(N),输出N并返回到根(3),再进入3的右子树(N),输出N并返回到根(3),3作为根,3的左子树和右子树都已经输出,所以此时输出3,输出3后返回到3的根(2)。
遍历序列:N N 3
2. 进入2后,2作为根,2的左子树已经输出,再进入2的右子树,2的右子树为N, 输出N并且返回到根,2作为根,2的左子树和右子树都已经输出,此时可以输出根(2),输出2并且返回2的根(1)。
遍历序列:N N 3 N 2
3.进入1后,1作为根,1的左子树已经输出,再进入1的右子树(4),4作为根,先进入4的左子树(5),5作为根,先进入5的左子树(N),左子树为N,输出N并且返回到根(5),5作为根,再进入5的右子树,5的右子树为N,输出N并返回到根,5的左子树和右子树都已经输出,此时输出5并且返回到5的根(4)。
遍历序列:N N 3 N 2 N N 5
4. 进入4后,4作为根,4的左子树已经输出,进入4的右子树(6),6左右根,先进入6的左子树N,输出N并返回到根,再进入6的右子树N,输出N并返回到根。6作为根,其左子树和右子树都已经输出,此时输出6并且返回到6的根(4),4作为根,4的左子树和右子树都已经输出,此时输出4并且返回到4的根(1)。
遍历序列:N N 3 N 2 N N 5 N N 6 4
5.进入1后,1作为根,1的左子树和右子树都已经输出,此时输出1。
遍历序列:N N 3 N 2 N N 5 N N 6 4 1
2.二叉树链式结构的实现
2.1 Tree.h
源码:
#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<iostream>
#include<algorithm>
using namespace std;
typedef int TreeType;
typedef struct Tree
{
TreeType val;
struct Tree* left;
struct Tree* right;
}TNode;
void PreOrder(TNode* root);//前序遍历
void InOrder(TNode* Root);//中序遍历
void BacOrder(TNode* Root);//后序遍历
int Treesize(TNode* root);//求节点数
int Leafsize(TNode* root);//求叶子节点数
int Treeheight(TNode* root);//求树高度
int Knum(TNode* root, int k);//第K层结点数
TNode* Treefind(TNode* root, TreeType x);//查找节点为x值所在节点指针
2.2 Tree.cpp
源码:
#include"Tree.h"
void PreOrder(TNode* Root)
{
if (Root == NULL)
{
cout << "N ";
return;
}
cout << Root->val << " ";
PreOrder(Root->left);
PreOrder(Root->right);
}
void InOrder(TNode* Root)
{
if (Root == NULL)
{
cout << "N ";
return;
}
InOrder(Root->left);
cout << Root->val << " ";
InOrder(Root->right);
}
void BacOrder(TNode* Root)
{
if (Root == NULL)
{
cout << "N ";
return;
}
BacOrder(Root->left);
BacOrder(Root->right);
cout << Root->val << " ";
}
int Treesize(TNode* root)//求节点数
{
if (root == NULL)
{
return 0;
}
else
{
return Treesize(root->left) + Treesize(root->right) + 1;
}
}
int Leafsize(TNode* root)//求叶子节点数
{
if (root == NULL) {
return 0;
}
if (root->left == root->right == NULL) {
return 1;
}
return Leafsize(root->left) + Leafsize(root->right);
}
int Treeheight(TNode* root)//求树高度
{
if (root == NULL) {
return 0;
}
int leftnum = Treeheight(root->left);
int rightnum = Treeheight(root->right);
return leftnum > rightnum ? leftnum + 1 : rightnum + 1;
}
int Knum(TNode* root,int k)//二叉树第k层节点个数
{
if (root == NULL)
{
return 0;
}
if (k == 1)
{
return 1;
}
return Knum(root->left,k-1) + Knum(root->right,k-1);
}
TNode* Treefind(TNode* root, TreeType x)//查找节点为x值所在节点指针
{
if (root == NULL) {
return NULL;
}
if (root->val == x) {
return root;
}
TNode* ret1 = Treefind(root->left, x);
if (ret1) {
return ret1;
}
TNode* ret2 = Treefind(root->right, x);
if (ret2) {
return ret2;
}
return NULL;
}
2.2.1 前序遍历 void PreOrder(TNode* Root)
void PreOrder(TNode* Root)
{
if (Root == NULL)
{
cout << "N ";
return;
}
cout << Root->val << " ";
PreOrder(Root->left);
PreOrder(Root->right);
}
1.先输出节点的值,再进行左子树遍历和右子树遍历
2.2.2 中序遍历 void InOrder(TNode* Root)
void InOrder(TNode* Root)
{
if (Root == NULL)
{
cout << "N ";
return;
}
InOrder(Root->left);
cout << Root->val << " ";
InOrder(Root->right);
}
1.先递归左子树,在输出节点值,再递归右子树。
2.2.3 后序遍历 void BacOrder(TNode* Root)
void BacOrder(TNode* Root)
{
if (Root == NULL)
{
cout << "N ";
return;
}
BacOrder(Root->left);
BacOrder(Root->right);
cout << Root->val << " ";
}
1.先递归左子树和右子树,最后输出节点值。
2.2.4 求树的总节点数 int Treesize(TNode* root)
int Treesize(TNode* root)//求节点数
{
if (root == NULL)
{
return 0;
}
else
{
return Treesize(root->left) + Treesize(root->right) + 1;
}
}
1.如果遇到空节点(N),就返回0,其余情况返回左右子树递归+1。
2.2.5 求叶子结点数 int Leafsize(TNode* root)
int Leafsize(TNode* root)//求叶子节点数
{
if (root == NULL) {
return 0;
}
if (root->left == root->right == NULL) {
return 1;
}
return Leafsize(root->left) + Leafsize(root->right);
}
1.遇到空节点就返回0。
2.叶子节点的特点是其左右孩子都为空,则当if (root->left == root->right == NULL)成立时,返回1.
3.其余情况返回左子树递归+右子树递归。
2.2.6 求树的高度 int Treeheight(TNode* root)
int Treeheight(TNode* root)//求树高度
{
if (root == NULL) {
return 0;
}
int leftnum = Treeheight(root->left);
int rightnum = Treeheight(root->right);
return leftnum > rightnum ? leftnum + 1 : rightnum + 1;
}
1.当为空节点时,返回0。
2.用leftnum存储左子树的层数,用rightnum存储右子树的层数,两者返回最大者+1.
2.2.7 求二叉树第K层节点数 int Knum(TNode* root,int k)
int Knum(TNode* root,int k)//二叉树第k层节点个数
{
if (root == NULL)
{
return 0;
}
if (k == 1)
{
return 1;
}
return Knum(root->left,k-1) + Knum(root->right,k-1);
}
1.如果时空节点,则返回0。
2.当k==1时,则此时在第K层的某个节点上,则返回1即可。
3.其余情况返回Knum(root->left,k-1) + Knum(root->right,k-1)。
2.2.8 查找节点为x值所在节点指针 TNode* Treefind(TNode* root, TreeType x)
TNode* Treefind(TNode* root, TreeType x)//查找节点为x值所在节点指针
{
if (root == NULL) {
return NULL;
}
if (root->val == x) {
return root;
}
TNode* ret1 = Treefind(root->left, x);
if (ret1) {
return ret1;
}
TNode* ret2 = Treefind(root->right, x);
if (ret2) {
return ret2;
}
return NULL;
}
1.如果当前节点的值等于要查找的值,则返回该节点的地址。
2.用ret1和ret2接收Treefind(root->left, x)的返回值和Treefind(root->right, x)的返回值,如果其中有一个不为空指针,则说明找到了,就立马返回这个地址。
3.其余情况返回NULL即可。
2.2.9 二叉树的销毁 void TreeDestory(TNode* root)
void TreeDestory(TNode* root)//二叉树的销毁
{
if (root == NULL) {
return;
}
TreeDestory(root->left);
TreeDestory(root->right);
free(root);
}
1.必须遍历左右子树,再释放空间,否则释放节点后就会导致找不到左右子树。
2.2.10 层序遍历 void TreeLeveorder(TNode* root)
void TreeLeveorder(TNode* root)//层序遍历
{
queue<TNode*>q;
if (root) {
q.push(root);
}
while (q.size())
{
TNode* cur = q.front();
q.pop();
cout << cur->val << " ";
if (cur->left)
{
q.push(cur->left);
}
if (cur->right)
{
q.push(cur->right);
}
}
}
2.2.11 判断一棵树是否为完全二叉树 bool JudgeTree(TNode* root)
bool JudgeTree(TNode* root)
{
queue<TNode*>q;
if (root) {
q.push(root);
}
while (q.size())
{
TNode* cur = q.front();
q.pop();
if (cur == NULL)//出现第一个空
{
break;//退出
}
if (cur->left)
{
q.push(cur->left);
}
if (cur->right)
{
q.push(cur->right);
}
}
while (q.size())
{
if (q.front() != NULL) {
return false;
}
q.pop();
}
return true;
}
1.首先层序遍历,遇到队列中第一个空就退出循环,然后判断队列中是否还有非空节点,如果还有非空节点,则不是完全二叉树,反之则为完全二叉树。
2.不可能出现,遇到空时,后面还有非空没进队列,后面非空,一定前面非空的孩子。当层序到空时,前面的非空都出完了,那他的孩子一定进队列了。
本篇完