#include <iostream>
#include <algorithm> // max()
#include <queue>
using namespace std;
typedef char ElemType; // 树存储的值得类型
#define STACKMAXSIZE 15 // 创建树中用到栈的最大值
// 树的存储结构
typedef struct Node
{
Node* lchild;
ElemType date;
Node* rchild;
}Node, LinkBTree;
//创建树,将括号表达式转换为树
void CreatBTree(LinkBTree*& Tree, char* str)
{
Node* nodeStack[STACKMAXSIZE];
int top = -1; // 栈顶标志
Node* tmp = NULL;
int leftOrRight; // 用来标记是左孩子(1),右孩子(2)
while (*str != '\0')
{
switch (*str)
{
case '(':
top++;
nodeStack[top] = tmp;
leftOrRight = 1;
break;
case ')':
top--;
break;
case ',':
leftOrRight = 2;
break;
default:
tmp = new Node;
tmp->date = *str;
tmp->lchild = tmp->rchild = NULL;
if (Tree == NULL) {
Tree = tmp;
}
else {
if (leftOrRight == 1)
nodeStack[top]->lchild = tmp;
else if (leftOrRight == 2)
nodeStack[top]->rchild = tmp;
}
break;
}
str++;
}
}
// 销毁树
void destoryTree(LinkBTree*& Tree)
{
if (!Tree)
return;
destoryTree(Tree->lchild); // 销毁左边的树
destoryTree(Tree->rchild); // 销毁右边的树
delete Tree; // 删除当前树的根节点
}
// 找到值为e的结点,返回该地址
Node *findNode(LinkBTree*& Tree, ElemType e)
{
if (Tree == NULL)
return NULL;
if (Tree->date == e)
return Tree;
Node* p = findNode(Tree->lchild, e); // 先搜索做左边的树
if (p != NULL)
return p;
else
return findNode(Tree->rchild, e); // 左边没有就找右边
}
// 求树的深度
int BTNodeDepth(LinkBTree* Tree)
{
if (!Tree)
{
return 0;
}
return max(BTNodeDepth(Tree->lchild), BTNodeDepth(Tree->rchild)) + 1;
}
// 按括号表示法输出树
void displayTree(LinkBTree* Tree)
{
if (!Tree)
return;
cout << Tree->date;
if(Tree->lchild != NULL || Tree->rchild != NULL)
{
cout << '(';
displayTree(Tree->lchild);
if(Tree->rchild != NULL)
cout << ',';
displayTree(Tree->rchild);
cout << ')';
}
}
// 先序遍历
void preOrder(LinkBTree* Tree)
{
if (Tree == NULL)
return;
cout << Tree->date;
preOrder(Tree->lchild);
preOrder(Tree->rchild);
}
// 中序遍历
void inOrder(LinkBTree* Tree)
{
if (Tree == NULL)
return;
inOrder(Tree->lchild);
cout << Tree->date;
inOrder(Tree->rchild);
}
// 后序遍历
void postOrder(LinkBTree* Tree)
{
if (Tree == NULL)
return;
postOrder(Tree->lchild);
postOrder(Tree->rchild);
cout << Tree->date;
}
// 先序遍历(带NULL)
void preOrderWithNULL(LinkBTree* Tree)
{
if (Tree == NULL) {
cout << '^';
return;
}
cout << Tree->date;
preOrderWithNULL(Tree->lchild);
preOrderWithNULL(Tree->rchild);
}
// 中序遍历(带NULL)
void inOrderWithNULL(LinkBTree* Tree)
{
if (Tree == NULL) {
cout << '^';
return;
}
inOrderWithNULL(Tree->lchild);
cout << Tree->date;
inOrderWithNULL(Tree->rchild);
}
// 后序遍历(带NULL)
void postOrderWithNULL(LinkBTree* Tree)
{
if (Tree == NULL) {
cout << '^';
return;
}
postOrderWithNULL(Tree->lchild);
postOrderWithNULL(Tree->rchild);
cout << Tree->date;
}
// 输出结点值为e的左右孩子
void printRightAndLeftSonOf(LinkBTree *Tree, ElemType e) {
Node *node = findNode(Tree, e); // 找值为e的结点
// 没找到
if (node == NULL) {
cout << "树中没有结点的值为" << e << endl;
}
// 输出左右结点
if (node->lchild != NULL)
cout << "左孩子的值是:" << node->lchild->date << endl;
else
cout << "左孩子的值是:NULL" << endl;
if (node->rchild != NULL)
cout << "右孩子的值是:" << node->rchild->date << endl;
else
cout << "右孩子的值是:NULL" << endl;
}
// 返回一棵二叉树的结点个数
int countNode(LinkBTree *Tree) {
if (Tree == NULL)
return 0;
return countNode(Tree->lchild) + countNode(Tree->rchild) + 1;
}
// 返回一棵二叉树的双分支结点的个数
int countDoubleNode(LinkBTree *Tree) {
if (Tree == NULL) {
return 0;
}
if (Tree->lchild != NULL && Tree->rchild != NULL) // 是否同时有左右结点
return countDoubleNode(Tree->lchild) + countDoubleNode(Tree->rchild) + 1;
else
return countDoubleNode(Tree->lchild) + countDoubleNode(Tree->rchild);
}
// 返回一棵二叉树的单分支结点的个数
int countSingleNode(LinkBTree *Tree) {
if (Tree == NULL) {
return 0;
}
if ((Tree->lchild != NULL && Tree->rchild == NULL) || (Tree->lchild == NULL && Tree->rchild != NULL)) // 当前根节点是否只有一个子节点
return countSingleNode(Tree->lchild) + countSingleNode(Tree->rchild) + 1;
else
return countSingleNode(Tree->lchild) + countSingleNode(Tree->rchild);
}
// 返回一棵二叉树叶子结点的个数
int countLeafNode(LinkBTree* Tree) {
if (Tree == NULL) {
return 0;
}
if (Tree->lchild == NULL && Tree->rchild == NULL) {
return 1;
}
return countLeafNode(Tree->lchild) + countLeafNode(Tree->rchild);
}
//求二叉树的宽度
int treeWidth(LinkBTree * Tree) {
if (Tree == NULL)
return 0;
int nLastLevelWidth = 0;//记录上一层的宽度
int nCurLevelWidth = 0;//记录当前层的宽度
queue<LinkBTree*> myQueue;
myQueue.push(Tree);//将根节点入队列
int nWidth = 1;//二叉树的宽度
nLastLevelWidth = 1;
LinkBTree* pCur = NULL;
while (!myQueue.empty())//队列不空
{
while (nLastLevelWidth != 0) {
pCur = myQueue.front();//取出队列头元素
myQueue.pop();//将队列头元素出对
if (pCur->lchild != NULL)
myQueue.push(pCur->lchild);
if (pCur->rchild != NULL)
myQueue.push(pCur->rchild);
nLastLevelWidth--;
}
nCurLevelWidth = myQueue.size();
nWidth = nCurLevelWidth > nWidth ? nCurLevelWidth : nWidth;
nLastLevelWidth = nCurLevelWidth;
}
return nWidth;
}
Node* findLowestCommonAscestor(LinkBTree *Tree, ElemType e1, ElemType e2) {
if (Tree == NULL) {
return NULL;
}
// 存储findNode的结果,减少重复计算
Node* tmp1 = new Node;
Node* tmp2 = new Node;
// 判断左边的树是不是都同时含有e1, e2,是的话就往左边的子树找
tmp1 = findNode(Tree->lchild, e1);
tmp2 = findNode(Tree->lchild, e2);
if (tmp1 != NULL && tmp2 != NULL) {
return findLowestCommonAscestor(Tree->lchild, e1, e2);
}
// 判断右边的树是不是都同时含有e1, e2,是的话就往右边的子树找
tmp1 = findNode(Tree->rchild, e1);
tmp2 = findNode(Tree->rchild, e2);
if (tmp1 != NULL && tmp2 != NULL) {
return findLowestCommonAscestor(Tree->rchild, e1, e2);
}
// 左边、右边的树都不能同时含有e1、e2, 那他们共同的祖先就是当前的根节点
return Tree;
}
int main()
{
ElemType e, e1, e2;
LinkBTree* Tree = NULL;
char Treestr[100];
Node* node;
// "A(B(D(,G)),C(E(H),F(,I))"
cout << "输入你要创建树的括号表示法:";
cin >> Treestr;
CreatBTree(Tree, Treestr);
//1,括号表示法输出该树。
cout << "该树的括号表示法:";
displayTree(Tree);
cout << endl;
//2,输入一个结点的值,输出该结点的左,右孩子的值。(要能测试错误数据)
cout << "输入你要查找的值,我们会输出她的左右孩子" << endl; cin >> e;
printRightAndLeftSonOf(Tree, e);
//3,输出该二叉树的高度。
cout << "该树的高度:" << BTNodeDepth(Tree) << endl;
//4,输出该二叉树结点的个数。
cout << "二叉树结点的个数:" << countNode(Tree) << endl;
//5,输出该二叉树双分支结点的个数。
cout << "二叉树双结点的个数:" << countDoubleNode(Tree) << endl;
//6,输出该二叉树单分支结点的个数。
cout << "二叉树单结点的个数:" << countSingleNode(Tree) << endl;
//7,输出该二叉树叶子结点的个数。
cout << "二叉树叶子结点的个数:" << countLeafNode(Tree) << endl;
//8,输出该二叉树的宽度。(宽度为每层结点数的最大值)
cout << "二叉树的宽度:" << treeWidth(Tree) << endl;
//9,(选做题)任意给定该二叉树的两个结点,输出它们的最近的公共祖先。
//(例:对P247图7.33,输入J,N,它们的祖先是H,E,B,A,最近的祖先是H。)
cout << "输入你要找出他们共同祖先的两个节点的值:"; cin >> e1 >> e2;
node = findLowestCommonAscestor(Tree, e1, e2);
cout << "他们最近的共同祖先是:" << node->date << endl;
//10,销毁该二叉树。
destoryTree(Tree);
return 0;
}
二叉树的基本操作
最新推荐文章于 2021-11-14 11:59:48 发布