基于广义表二叉树字符串递归生成二叉树,各种递归非递归遍历二叉树,查找二叉树操作,求二叉树高度,深度,结点度数,叶子结点度数集合

基本思路都在代码注释里

#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 -
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章