二叉树:利用广义表创建二叉树,并实现指定结点的删除

题目:

编写递归算法,对于二叉树中每一个元素值data等于x的节点,删去以它为根的子树,并释放相应的空间。

树的结构以广义表的形式给出。如A(B,)表示一颗有2个节点的树。其中根的data值为A,其左孩子为叶子节点,data值为B,右孩子为空。

输入格式

输入有两行,第一行为以广义表的形式给出的树形结构,长度在区间 [0,30)[0,30) 内,均由大写字母和左右括号组成,每个结点由一个大写字母组成,互不相同。第二行为待删除子树根结点的元素值x,为一个大写字母。

输出格式

输出有一行,为原树删除子树后的广义表达式。

若找不到该元素,则不做删除操作直接输出广义表达式。

样例输入

A(B,C)
B

样例输出

A(,C)

我的解题思路:

本题关键在于用广义表来建立二叉树,所以重点阐述这一部分。
利用递归的思想来建立二叉树。
我先为二叉树的结点定义了一个类,然后将这个函数作为它的成员函数,方便创建。

函数声明:
将该函数命名为build,返回值为结点指针(Node*),参数为一个字符串,该字符串本身应当为一个完整合乎格式的广义表,以此来实现二叉树的递归创建。
函数体:
对于一个完整的二叉树广义表(以下简称广义表),首字符一定为该树的根节点:
Node *p = new Node(input[0]);

若这个结点没有孩子结点,那么直接返回结点指针*p即可。
判断有无孩子结点方法是,看看字符串的第二个位置是否是左括号“(”:
if (input[1] == '(') {

进入花括号内,结点一定有孩子结点。此时该判断它的孩子结点为左子树还是右子树,或者二者兼而有之。
方法是查找‘,’所在的位置:
int comma_pos = input.find(',');
1. 若没有逗号,即返回值为-1
说明肯定没有右子树,那么将左孩子结点赋值为
p -> lchild = build(input.substr(2, input.length() - 2));
2. 若有逗号,逗号在位置2上
则该结点只有右孩子结点,右孩子结点赋值为
p -> rchild = build(input.substr(3, input.length() - 2));
3. 若有逗号,逗号位置大于2
则该结点至少有左子树
此时有两种情况:
第一种是只有左子树,但左子树中有右孩子
第二种是既有左子树,又有右子树
这两种统一的步骤是截取代表左子树的字符串
求取左子树结束位置
截取左子树字符串,赋值左孩子
然后通过判断结束位置+2的位置是否为大写字母,判断有无右孩子
有的话截取右子树字符串,赋值右孩子
方法如下:
if (comma_pos > 2) {    //有左子树
    int i;
    if (comma_pos == 3) {   //左子树为叶子结点
        p -> lchild = new Node(input[2]);
        i = 2;
    } else if (comma_pos > 3) {    //有左子树
        int comma = 1;
        i = comma_pos;
        while(comma > 0) {
            i++;
            if (input[i] == ',') {
                comma++;
            } else if (input[i] == ')') {
                comma--;
            }
        }
        p -> lchild = build(input.substr(2, i));
    }
    if (isupper(input[i + 2])) {    //也有右子树时,无则忽略该步
        p -> rchild = build(input.substr(i + 2));
    }
}

中间出现的问题:

第十个测试输入:
 
A
可见广义表为空,要删除结点A。正确输出应该为空。
但第一行不被读入。
导致我的输出是
A
这个应该考察了scanf,cin等等的用法。
我的方法比较暴力
因为了解到测试输入中只有广义表为空,没有删除结点为空的情况。
我为删除结点的char赋了初值,若初值没有被改变,则输出为空。
若初值改变,则执行代码块。
就这样解决了问题。。

我的解题代码:

#include 
#include 
#include 
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::scanf;
class Node{
public:
    char data;
    Node *lchild, *rchild;
    Node(char _data) {
        data = _data;
        lchild = NULL;
        rchild = NULL;
    }
    ~Node() {
        if (lchild != NULL) {
            delete lchild;
        }
        if (rchild != NULL) {
            delete rchild;
        }
    }
    Node* build (const string input) {
        Node *p = new Node(input[0]);
        if (input[1] == '(') {
            int comma_pos = input.find(',');
            if (comma_pos > 2) {    //有左子树
                int i;
                if (comma_pos == 3) {   //左子树为叶子结点
                    p -> lchild = new Node(input[2]);
                    i = 2;
                } else if (comma_pos > 3) {    //有左子树
                    int comma = 1;
                    i = comma_pos;
                    while(comma > 0) {
                        i++;
                        if (input[i] == ',') {
                            comma++;
                        } else if (input[i] == ')') {
                            comma--;
                        }
                    }
                    p -> lchild = build(input.substr(2, i));
                }
                if (isupper(input[i + 2])) {    //也有右子树时,无则忽略该步
                    p -> rchild = build(input.substr(i + 2));
                }
            } else if (comma_pos == 2) {    //只有右子树
                if (input[4] == '(') {
                    int left = 1;
                    int i = 2;
                    while(left > 0) {
                        i++;
                        if (input[i] == '(') {
                            left++;
                        } else if (input[i] == ')') {
                            left--;
                        }
                    }
                    p -> rchild = build(input.substr(3, i - 3));
                } else {
                    p -> rchild = new Node(input[3]);
                }
            }
        }
        return p;
    }
    void delete_char(char x) {
        if (lchild != NULL) {
            if (lchild -> data == x) {
                lchild = NULL;
            } else {
                lchild -> delete_char(x);
            }
        }
        if (rchild != NULL) {
            if (rchild -> data == x) {
                rchild = NULL;
            } else {
                rchild -> delete_char(x);
            }
        }
    }
    void output() {
        if (data != NULL) {
            cout << data;
            if (lchild != NULL || rchild != NULL) {
                cout << "(";
                if (lchild != NULL) {
                    lchild -> output();
                }
                if (rchild != NULL) {
                    cout << ",";
                    rchild -> output();
                }
                cout << ")";
            }
        }
    }
};

class BinaryTree{
private:
    Node *root;
public:
    BinaryTree() {
        root = NULL;
    }
    ~BinaryTree() {
        delete root;
    }
    void build (const string input) {
        root = root -> build (input);
    }
    void delete_char(char x) {
        if (root -> data == x) {
            root = NULL;
        } else {
            root -> delete_char(x);
        }
    }
    void output() {
        if (root != NULL) {
            root -> output();
        }
    }
};

int main() {
    BinaryTree binarytree;
    char input[31];
    char input_x = '0';
    scanf("%s\n%c", input, &input_x);
    if (input_x != '0') {
        binarytree.build(input);
        binarytree.delete_char(input_x);
        binarytree.output();
    }
    
    return 0;
}


你可能感兴趣的:(计蒜客解题思路)