基本思路都在代码注释里
#include <string>
#include <iostream>
#include <algorithm>
#include <stack>
using namespace std;
struct treeNode {
string data;
treeNode *leftChild{};
treeNode *rightChild{};
int leftTag;
int rightTag;
};
//返回的是中点逗号的位置
//1.当inputData为“C(D,E),F”时,返回“6”,
//2.当inputData为“C,D”时,返回“1”
//3.当inputData为“,A(B,C)”时,返回“0”
//4.当inputData为“C(D,E)”时,返回“-1”
int findMiddlePosition(string inputData) {
int result = -1;
int leftK = 0;
int rightK = 0;
int position = 0;
while (inputData[position]) {
if (inputData[position] == '(') {
++leftK;
} else if (inputData[position] == ')') {
++rightK;
} else if (leftK == rightK && inputData[position] == ',') {
result = position;
break;
}
++position;
}
return result;
}
//提取出数据
//1.当left为true时,提取的是左边的值
// 1.当inputData为“C(D,E),F”时,返回“C(D,E)”,
// 2.当inputData为“,A(B,C)”时,返回空字符串
// 3.当inputData为“C(D,E)”时,返回“C(D,E)”
//2.当left为false时,提取的是右边的值
// 1.当inputData为“C(D,E),F”时,返回“F”
// 2.当inputData为“C(D,E)”时,返回空字符串
string getString(const string &inputData, bool left) {
string result;
int middlePosition = findMiddlePosition(inputData);
if (left) {
if (middlePosition == -1) {
result = inputData;
} else if (middlePosition != 0) {
result = inputData.substr(0, middlePosition);
}
} else {
if (middlePosition != -1) {
result = inputData.substr(middlePosition + 1, inputData.length() - middlePosition - 1);
}
}
return result;
}
//对字符串进行处理
//inputData会有两种输入情况
// 1.输入的只是一个字符,此时直接返回空字符串
// 2.输入的是一个形如A(B(C,D),E)的形式,去掉第一,第二,最后一个字符,将返回B(C,D),E字符串
string eraseString(const string &inputData) {
string result;
if (inputData.length() != 1) {
result = inputData.substr(2, inputData.length() - 2 - 1);
}
return result;
}
//返回第一个字符
string getData(const string &inputData) {
return inputData.substr(0, 1);
}
//函数返回的是根节点
treeNode *buildTree(const string &inputData) {
auto *node = new treeNode;
node->data = getData(inputData);
string newInputData = eraseString(inputData);
if (newInputData.empty()) {
node->leftChild = nullptr;
node->rightChild = nullptr;
} else if (getString(newInputData, true).empty()) {
node->leftChild = nullptr;
node->rightChild = buildTree(getString(newInputData, false));
} else if (getString(newInputData, false).empty()) {
node->leftChild = buildTree(getString(newInputData, true));
node->rightChild = nullptr;
} else {
node->leftChild = buildTree(getString(newInputData, true));
node->rightChild = buildTree(getString(newInputData, false));
}
return node;
}
//使用递归进行遍历二叉树
void firstTravelTree(treeNode *treeNode) {
if (!treeNode) {
return;
}
cout << treeNode->data << " -> ";
firstTravelTree(treeNode->leftChild);
firstTravelTree(treeNode->rightChild);
}
//使用递归进行遍历二叉树
void middleTravelTree(treeNode *treeNode) {
if (!treeNode) {
return;
}
middleTravelTree(treeNode->leftChild);
cout << treeNode->data << " -> ";
middleTravelTree(treeNode->rightChild);
}
//使用递归进行遍历二叉树
void lastTravelTree(treeNode *treeNode) {
if (!treeNode) {
return;
}
lastTravelTree(treeNode->leftChild);
lastTravelTree(treeNode->rightChild);
cout << treeNode->data << " -> ";
}
//非递归先序遍历二叉树
void specialFirstTravelTree(treeNode *node) {
stack<treeNode *> s;
treeNode *p = node;
treeNode *q;
while (p || !s.empty()) {
if (p) {
cout << p->data;
cout << " - ";
s.push(p);
p = p->leftChild;
} else {
q = s.top();
s.pop();
p = q->rightChild;
}
}
}
//非递归中序遍历二叉树
void specialMiddleTravelTree(treeNode *node) {
stack<treeNode *> s;
treeNode *p = node;
treeNode *q;
while (p || !s.empty()) {
if (p) {
s.push(p);
p = p->leftChild;
} else {
q = s.top();
s.pop();
cout << q->data;
cout << " - ";
p = q->rightChild;
}
}
}
//非递归后序遍历二叉树
//1、申请一个栈s1,然后将头节点压入栈s1中。
//2、从s1中弹出的节点记为cur,然后依次将cur的左孩子节点和右孩子节点压入s1中。
//3、在整个过程中,每一个从s1中弹出的节点都放进s2中。
//4、不断重复步骤2和步骤3,直到s1为空,过程停止。
//5、从s2中依次弹出节点并打印,打印的顺序就是后序遍历的顺序。
void specialLastTravelTree(treeNode *node) {
stack<treeNode *> s1;
stack<treeNode *> s2;
s1.push(node);
while (!s1.empty()) {
treeNode *cur = s1.top();
s2.push(cur);
s1.pop();
if (cur->leftChild) {
s1.push(cur->leftChild);
}
if (cur->rightChild) {
s1.push(cur->rightChild);
}
}
//显示s2
while (!s2.empty()) {
cout << s2.top()->data;
cout << " - ";
s2.pop();
}
}
//寻找二叉树,输出左右节点的值,采用递归的方法
void searchNode(treeNode *treeNode, const string &nodeData) {
if (!treeNode) {
return;
}
if (treeNode->data == nodeData) {
if (treeNode->leftChild) {
cout << " 左子节点的值为:" << treeNode->leftChild->data << endl;
} else {
cout << " 无左子节点!" << endl;
}
if (treeNode->rightChild) {
cout << " 右子节点的值为:" << treeNode->rightChild->data << endl;
} else {
cout << " 无右子节点!" << endl;
}
return;
}
searchNode(treeNode->leftChild, nodeData);
searchNode(treeNode->rightChild, nodeData);
}
//输出二叉树的节点个数
int countNode(treeNode *treeNode) {
static int countNum = 0;
if (!treeNode) {
return 0;
}
++countNum;
countNode(treeNode->leftChild);
countNode(treeNode->rightChild);
return countNum;
}
//输出二叉树的叶子数
int countLeaf(treeNode *treeNode) {
static int countNum = 0;
if (!treeNode) {
return 0;
}
if (!treeNode->rightChild && !treeNode->leftChild) {
++countNum;
}
countLeaf(treeNode->leftChild);
countLeaf(treeNode->rightChild);
return countNum;
}
//输出二叉树的度
int countDegree(treeNode *treeNode) {
static int countNum = 0;
if (!treeNode) {
return 0;
}
if (treeNode->rightChild && treeNode->leftChild) {
countNum = 2;
} else if (treeNode->rightChild || treeNode->leftChild) {
countNum = countNum == 2 ? 2 : 1;
}
countDegree(treeNode->leftChild);
countDegree(treeNode->rightChild);
return countNum;
}
//输出二叉树的高度
//思路,找出左括号和右括号差值的最大值
int countHeight(const string &inputData) {
static int height = 0;
int *heightData = new int[200];
height = {0};
int leftK = 0;
int rightK = 0;
int heightDataCount = 0;
int i = 0;
while (inputData[i]) {
if (inputData[i] == '(') {
++leftK;
heightData[heightDataCount] = leftK - rightK;
++heightDataCount;
} else if (inputData[i] == ')') {
++rightK;
}
++i;
}
height = *max_element(heightData, heightData + 200);
++height;
return height;
}
//中序遍历线索化二叉树
treeNode *pre = new treeNode;
void treatingTree(treeNode *node) {
if (node) {
treatingTree(node->leftChild);
if (!node->leftChild) {
node->leftTag = 1;
node->leftChild = pre;
} else {
node->leftTag = 0;
}
if (!pre->rightChild) {
pre->rightTag = 1;
pre->rightChild = node;
} else {
node->rightTag = 0;
}
pre = node;
treatingTree(node->rightChild);
}
}
//中序遍历转换为字符串
string data;
string toString(treeNode *treeNode) {
if (!treeNode) {
return data;
}
toString(treeNode->leftChild);
data = data + treeNode->data;
toString(treeNode->rightChild);
return data;
}
void showFrontAndNext(string data, string target) {
int position = data.find(target);
if (!position) {
return;
}
cout << data[position - 1];
cout << " 、 ";
cout << data[position + 1];
}
int main() {
treeNode *tree1 = nullptr;
cout << "(1)请输入要构造的二叉树广义表:";
string inputData;
cin >> inputData;
tree1 = buildTree(inputData);
string data = toString(tree1);
cout << "(2)输出二叉树" << endl;
cout << " 先序遍历得到的二叉树字符串为:";
firstTravelTree(tree1);
cout << endl;
cout << " 中序遍历得到的二叉树字符串为:";
middleTravelTree(tree1);
cout << endl;
cout << " 后序遍历得到的二叉树字符串为:";
lastTravelTree(tree1);
cout << endl;
cout << "(3)输出‘H’节点的左、右孩子结点值" << endl;
searchNode(tree1, "H");
int nodeNum = countNode(tree1);
int leafNum = countLeaf(tree1);
int treeDegree = countDegree(tree1);
int height = countHeight(inputData);
cout << "(4)输出该二叉树的结点个数、叶子结点个数、二叉树的度和高度" << endl;
cout << " 结点数:" << nodeNum << endl;
cout << " 叶子结点数:" << leafNum << endl;
cout << " 二叉树的度:" << treeDegree << endl;
cout << " 二叉树的高度:" << height << endl;
cout << endl;
cout << "(5)非递归先序遍历二叉树:";
specialFirstTravelTree(tree1);
cout << endl;
cout << " 非递归中序遍历二叉树:";
specialMiddleTravelTree(tree1);
cout << endl;
cout << " 非递归后序遍历二叉树:";
specialLastTravelTree(tree1);
cout << endl;
cout << "(6)进行线索化二叉树..." << endl;
treatingTree(tree1);
cout << " 线索化完成..." << endl;
cout << " 根据线索化二叉树找到的根节点的前驱:";
if (tree1->leftTag == 1) {
cout << tree1->leftChild->data;
} else {
cout << "没有前驱!";
}
cout << endl;
cout << " 根据线索化二叉树找到的根节点的后继:";
if (tree1->rightTag == 1) {
cout << tree1->rightChild->data;
} else {
cout << "没有后继!";
}
cout << endl;
cout << "(7)查找到根节点的前驱后继分别为:";
showFrontAndNext(data, tree1->data);
cout << endl;
return 0;
}
输入和输出如下:
(1)请输入要构造的二叉树广义表:A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))
(2)输出二叉树
先序遍历得到的二叉树字符串为:A -> B -> D -> E -> H -> J -> K -> L -> M -> N -> C -> F -> G -> I ->
中序遍历得到的二叉树字符串为:D -> B -> J -> H -> L -> K -> M -> N -> E -> A -> F -> C -> G -> I ->
后序遍历得到的二叉树字符串为:D -> J -> L -> N -> M -> K -> H -> E -> B -> F -> I -> G -> C -> A ->
(3)输出‘H’节点的左、右孩子结点值
左子节点的值为:J
右子节点的值为:K
(4)输出该二叉树的结点个数、叶子结点个数、二叉树的度和高度
结点数:14
叶子结点数:6
二叉树的度:2
二叉树的高度:7
(5)非递归先序遍历二叉树:A - B - D - E - H - J - K - L - M - N - C - F - G - I -
非递归中序遍历二叉树:D - B - J - H - L - K - M - N - E - A - F - C - G - I -
非递归后序遍历二叉树:D - J - L - N - M - K - H - E - B - F - I - G - C - A -