c++数据结构与算法之二叉树
二叉树关键点
二叉树相关问题的解法主要就是两个
1.使用递归函数来进行深度优先搜索,比如二叉树的前序遍历、中序遍历、后序遍历以及通过二叉树的两个遍历顺序的结果来恢复出二叉树,这些都是通过递归来进行深度优先搜索来实现的。
2.使用队列来进行宽度优先搜索,比如二叉树的层次输出,以及确定二叉树每一层有多少个节点。
构造二叉树(使用链表来表示二叉树)
链表节点
template<class T>
class binaryTreeNode
{
public:
T element;
binaryTreeNode<T>* leftChild; //左子树
binaryTreeNode<T>* rightChild; //右子树
binaryTreeNode()
{
leftChild = rightChild = NULL;
}
binaryTreeNode(const T& theElement)
{
element = theElement;
leftChild = rightChild = NULL;
}
binaryTreeNode(const T& theElement, binaryTreeNode<T>* theLeftChild, binaryTreeNode<T>* theRightChild)
{
element = theElement;
leftChild = theLeftChild;
rightChild = theRightChild;
}
};
链表构造
binaryTreeNode<int>* root = new binaryTreeNode<int>(1);
root->leftChild = new binaryTreeNode<int>(2);
root->rightChild = new binaryTreeNode<int>(3);
binaryTreeNode<int>* tem_root = root->leftChild;
tem_root->leftChild = new binaryTreeNode<int>(4);
tem_root->rightChild = new binaryTreeNode<int>(5);
tem_root = root->rightChild;
tem_root->leftChild = new binaryTreeNode<int>(6);
tem_root->rightChild = new binaryTreeNode<int>(7);
二叉树遍历
深度优先遍历
前序遍历
//前序遍历输出
template<class T>
void preOrder(binaryTreeNode<T>* theRoot)
{
if (theRoot == NULL)
{
return ;
}
if (theRoot != NULL)
{
cout << theRoot->element << " ";
preOrder(theRoot->leftChild);
preOrder(theRoot->rightChild);
}
}
中序遍历
//中序遍历输出
template<class T>
void inOrder(binaryTreeNode<T>* theRoot)
{
if (theRoot == NULL)
{
return ;
}
if (theRoot != NULL)
{
inOrder(theRoot->leftChild);
cout << theRoot->element << " ";
inOrder(theRoot->rightChild);
}
}
后序遍历
//后序遍历输出
template<class T>
void postOrder(binaryTreeNode<T>* theRoot)
{
if (theRoot == NULL)
{
return ;
}
if (theRoot != NULL)
{
postOrder(theRoot->leftChild);
postOrder(theRoot->rightChild);
cout << theRoot->element << " ";
}
}
宽度优先遍历(层次遍历)
//层次遍历,也就是宽度优先搜索
template<class T>
void levelOrder(binaryTreeNode<T>* theRoot)
{
if (theRoot == NULL)
{
cout << "The tree is empty " << endl;
return ;
}
queue<binaryTreeNode<T>*> tem;
tem.push(theRoot);
while(!tem.empty())
{
binaryTreeNode<T>* tempRoot = tem.front();
cout << tempRoot->element << endl;
if (tempRoot->leftChild != NULL)
{
tem.push(tempRoot->leftChild);
}
if (tempRoot->rightChild != NULL)
{
tem.push(tempRoot->rightChild);
}
tem.pop();
}
}
复制二叉树
前序遍历复制
//前序复制二叉树
template<class T>
void preCopyTree(binaryTreeNode<T>* theRoot, binaryTreeNode<T>* &goalRoot)
{
if (theRoot == NULL)
{
return ;
}
if (theRoot != NULL)
{
goalRoot = new binaryTreeNode<T>(theRoot->element);
cout << goalRoot->element << endl;
preCopyTree(theRoot->leftChild, goalRoot->leftChild);
preCopyTree(theRoot->rightChild, goalRoot->rightChild);
}
}
后序遍历复制
//后序复制二叉树
template<class T>
void postCopyTree(binaryTreeNode<T>* theRoot, binaryTreeNode<T>* &goalRoot)
{
if (theRoot == NULL)
{
return ;
}
if (theRoot != NULL)
{
goalRoot = new binaryTreeNode<T>();
postCopyTree(theRoot->leftChild, goalRoot->leftChild);
postCopyTree(theRoot->rightChild, goalRoot->rightChild);
goalRoot->element = theRoot->element;
cout << goalRoot->element << endl;
}
}
二叉树层数与每一层的节点数目
//确定二叉树的哪一层具有最多的节点个数
template<class T>
pair<int, int> maxNode(binaryTreeNode<T>* theRoot)
{
if (theRoot == NULL)
{
cout << "The tree is empty " << endl;
}
map<int, int> level;
queue<pair<binaryTreeNode<T>* , int>> tem;
tem.push(make_pair(theRoot, 1));
while(!tem.empty())
{
pair<binaryTreeNode<T>*, int> tem_node = tem.front();
if(level.find(tem_node.second) == level.end())
{
level.insert(make_pair(tem_node.second, 1));
}
else
{
level[tem_node.second] += 1;
}
if (tem_node.first->leftChild != NULL)
{
tem.push(make_pair(tem_node.first->leftChild, tem_node.second + 1));
}
if(tem_node.first->rightChild != NULL)
{
tem.push(make_pair(tem_node.first->leftChild, tem_node.second + 1));
}
tem.pop();
}
int maxLevel = 0;
int nums = 0;
for (auto iter = level.begin(); iter != level.end(); iter++)
{
if (iter->second > nums)
{
nums = iter->second;
maxLevel = iter->first;
}
}
return make_pair(maxLevel, nums);
}
二叉树总的节点数目
//二叉树节点数目
template<class T>
int nums(binaryTreeNode<T>* theRoot)
{
if (theRoot == NULL)
{
return 0;
}
int num;
num = nums(theRoot->leftChild) + nums(theRoot->rightChild) + 1;
return num;
}
使用前序和中序遍历的结果恢复二叉树
#include <iostream>
#include <vector>
#include <unordered_map>
#include <queue>
#include "binaryTreeNode.h"
using namespace std;
template<class T>
binaryTreeNode<T>* restoreTree(unordered_map<T,int> &hash, vector<T> &pre, int pre_left, int pre_right, int in_left, int in_right);
//层次遍历,也就是宽度优先搜索
template<class T>
void levelOrder(binaryTreeNode<T>* theRoot);
int main()
{
vector<char> pre = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'};
vector<char> in = {'c', 'b', 'd', 'a', 'g', 'f', 'e', 'h'};
unordered_map<char, int> hash;
for (int i = 0; i < in.size(); i++)
{
hash.insert(make_pair(in[i], i));
}
binaryTreeNode<char> *root;
root = restoreTree(hash, pre, 0, pre.size()-1, 0, in.size()-1);
levelOrder<char>(root);
return 0;
}
//层次遍历,也就是宽度优先搜索
template<class T>
void levelOrder(binaryTreeNode<T>* theRoot)
{
if (theRoot == NULL)
{
cout << "The tree is empty " << endl;
return ;
}
queue<binaryTreeNode<T>*> tem;
tem.push(theRoot);
while(!tem.empty())
{
binaryTreeNode<T>* tempRoot = tem.front();
cout << tempRoot->element << endl;
if (tempRoot->leftChild != NULL)
{
tem.push(tempRoot->leftChild);
}
if (tempRoot->rightChild != NULL)
{
tem.push(tempRoot->rightChild);
}
tem.pop();
}
}
template<class T>
binaryTreeNode<T>* restoreTree(unordered_map<T,int> &hash, vector<T> &pre, int pre_left, int pre_right, int in_left, int in_right)
{
if (pre_left == pre_right || in_left == in_right)
{
return new binaryTreeNode<T>(pre[pre_right]);
}
if (pre_left > pre_right || in_left > in_right)
{
return NULL;
}
binaryTreeNode<T>* root;
binaryTreeNode<T>* root_left, *root_right;
int center = hash[pre[pre_left]];
root_left = restoreTree(hash, pre, pre_left + 1, pre_left + center - in_left, in_left, center - 1);
root_right = restoreTree(hash, pre, pre_left + center - in_left + 1, pre_right, center + 1, in_right);
root = new binaryTreeNode<T> (pre[pre_left], root_left, root_right);
}
完整代码
binaryTreeNode.h
#pragma once
#include <iostream>
using namespace std;
template<class T>
class binaryTreeNode
{
public:
T element;
binaryTreeNode<T>* leftChild; //左子树
binaryTreeNode<T>* rightChild; //右子树
binaryTreeNode()
{
leftChild = rightChild = NULL;
}
binaryTreeNode(const T& theElement)
{
element = theElement;
leftChild = rightChild = NULL;
}
binaryTreeNode(const T& theElement, binaryTreeNode<T>* theLeftChild, binaryTreeNode<T>* theRightChild)
{
element = theElement;
leftChild = theLeftChild;
rightChild = theRightChild;
}
};
主文件
#include "binaryTreeNode.h"
#include <iostream>
#include <queue>
#include <utility>
#include <map>
using namespace std;
template<class T>
void deleteTree(binaryTreeNode<T>* theRoot)
{
if (theRoot == NULL)
{
return ;
}
if (theRoot != NULL)
{
deleteTree(theRoot->leftChild);
deleteTree(theRoot->rightChild);
delete theRoot;
}
}
//前序遍历输出
template<class T>
void preOrder(binaryTreeNode<T>* theRoot);
//中序遍历输出
template<class T>
void inOrder(binaryTreeNode<T>* theRoot);
//后序遍历输出
template<class T>
void postOrder(binaryTreeNode<T>* theRoot);
//层次遍历,也就是宽度优先搜索
template<class T>
void levelOrder(binaryTreeNode<T>* theRoot);
//复制二叉树
template<class T>
void preCopyTree(binaryTreeNode<T>* theRoot, binaryTreeNode<T>* &goalRoot);
//后序复制二叉树
template<class T>
void postCopyTree(binaryTreeNode<T>* theRoot, binaryTreeNode<T>* &goalRoot);
//二叉树节点个数
template<class T>
int nums(binaryTreeNode<T>* theRoot);
//确定二叉树的哪一层具有最多的节点个数
template<class T>
pair<int, int> maxNode(binaryTreeNode<T>* theRoot);
int main()
{
binaryTreeNode<int>* root = new binaryTreeNode<int>(1);
root->leftChild = new binaryTreeNode<int>(2);
root->rightChild = new binaryTreeNode<int>(3);
binaryTreeNode<int>* tem_root = root->leftChild;
tem_root->leftChild = new binaryTreeNode<int>(4);
tem_root->rightChild = new binaryTreeNode<int>(5);
tem_root = root->rightChild;
tem_root->leftChild = new binaryTreeNode<int>(6);
tem_root->rightChild = new binaryTreeNode<int>(7);
//前序遍历输出
cout << "前序遍历输出 : " << endl;
preOrder(root);
cout << endl;
//中序遍历输出
cout << "中序遍历输出 : " << endl;
inOrder(root);
cout << endl;
//后序遍历输出
cout << "后序遍历输出 : " << endl;
postOrder(root);
cout << endl;
//层次遍历,也就是宽度优先搜索
cout << "宽度优先输出 : " << endl;
levelOrder(root);
cout << endl;
cout << "前序复制二叉树 : " << endl;
binaryTreeNode<int>* preCopyRoot;
preCopyTree(root, preCopyRoot);
levelOrder(preCopyRoot);
cout << endl;
cout << "后序复制二叉树 : " << endl;
binaryTreeNode<int>* postCopyRoot;
postCopyTree(root, postCopyRoot);
levelOrder(postCopyRoot);
cout << endl;
cout << "二叉树节点数目 : " << endl;
int num = nums(root);
cout << num << endl;
cout << "查看哪一层节点数目最多 : " << endl;
pair<int, int> level = maxNode(root);
cout << "第" << level.first << "层节点数目最多,有" << level.second << "个节点" << endl;
//释放树
deleteTree<int>(root);
deleteTree<int>(preCopyRoot);
deleteTree<int>(postCopyRoot);
return 0;
}
//前序遍历输出
template<class T>
void preOrder(binaryTreeNode<T>* theRoot)
{
if (theRoot == NULL)
{
return ;
}
if (theRoot != NULL)
{
cout << theRoot->element << " ";
preOrder(theRoot->leftChild);
preOrder(theRoot->rightChild);
}
}
//中序遍历输出
template<class T>
void inOrder(binaryTreeNode<T>* theRoot)
{
if (theRoot == NULL)
{
return ;
}
if (theRoot != NULL)
{
inOrder(theRoot->leftChild);
cout << theRoot->element << " ";
inOrder(theRoot->rightChild);
}
}
//后序遍历输出
template<class T>
void postOrder(binaryTreeNode<T>* theRoot)
{
if (theRoot == NULL)
{
return ;
}
if (theRoot != NULL)
{
postOrder(theRoot->leftChild);
postOrder(theRoot->rightChild);
cout << theRoot->element << " ";
}
}
//层次遍历,也就是宽度优先搜索
template<class T>
void levelOrder(binaryTreeNode<T>* theRoot)
{
if (theRoot == NULL)
{
cout << "The tree is empty " << endl;
return ;
}
queue<binaryTreeNode<T>*> tem;
tem.push(theRoot);
while(!tem.empty())
{
binaryTreeNode<T>* tempRoot = tem.front();
cout << tempRoot->element << endl;
if (tempRoot->leftChild != NULL)
{
tem.push(tempRoot->leftChild);
}
if (tempRoot->rightChild != NULL)
{
tem.push(tempRoot->rightChild);
}
tem.pop();
}
}
//前序复制二叉树
template<class T>
void preCopyTree(binaryTreeNode<T>* theRoot, binaryTreeNode<T>* &goalRoot)
{
if (theRoot == NULL)
{
return ;
}
if (theRoot != NULL)
{
goalRoot = new binaryTreeNode<T>(theRoot->element);
cout << goalRoot->element << endl;
preCopyTree(theRoot->leftChild, goalRoot->leftChild);
preCopyTree(theRoot->rightChild, goalRoot->rightChild);
}
}
//后序复制二叉树
template<class T>
void postCopyTree(binaryTreeNode<T>* theRoot, binaryTreeNode<T>* &goalRoot)
{
if (theRoot == NULL)
{
return ;
}
if (theRoot != NULL)
{
goalRoot = new binaryTreeNode<T>();
postCopyTree(theRoot->leftChild, goalRoot->leftChild);
postCopyTree(theRoot->rightChild, goalRoot->rightChild);
goalRoot->element = theRoot->element;
cout << goalRoot->element << endl;
}
}
//二叉树节点数目
template<class T>
int nums(binaryTreeNode<T>* theRoot)
{
if (theRoot == NULL)
{
return 0;
}
int num;
num = nums(theRoot->leftChild) + nums(theRoot->rightChild) + 1;
return num;
}
//确定二叉树的哪一层具有最多的节点个数
template<class T>
pair<int, int> maxNode(binaryTreeNode<T>* theRoot)
{
if (theRoot == NULL)
{
cout << "The tree is empty " << endl;
}
map<int, int> level;
queue<pair<binaryTreeNode<T>* , int>> tem;
tem.push(make_pair(theRoot, 1));
while(!tem.empty())
{
pair<binaryTreeNode<T>*, int> tem_node = tem.front();
if(level.find(tem_node.second) == level.end())
{
level.insert(make_pair(tem_node.second, 1));
}
else
{
level[tem_node.second] += 1;
}
if (tem_node.first->leftChild != NULL)
{
tem.push(make_pair(tem_node.first->leftChild, tem_node.second + 1));
}
if(tem_node.first->rightChild != NULL)
{
tem.push(make_pair(tem_node.first->leftChild, tem_node.second + 1));
}
tem.pop();
}
int maxLevel = 0;
int nums = 0;
for (auto iter = level.begin(); iter != level.end(); iter++)
{
if (iter->second > nums)
{
nums = iter->second;
maxLevel = iter->first;
}
}
return make_pair(maxLevel, nums);
}