扩展二叉树的程序崩溃问题

代码目的:创建扩展二叉树,然后以后序遍历和中序遍历输出
问题:输入完二叉树的元素后,程序就会立刻崩溃

#include <iostream>

using namespace std;


struct Tree
{
    Tree *left,*right;
    char data;
    double x;
};
 void Create(Tree *p,double a);

    void midOrder(Tree *p);
    void postOrder(Tree *p);
    void clear(Tree *p);

Tree *root=new Tree;
double i;
int main()
{   char *arr=new char [100000];
 cin>>arr;
 i=sizeof(arr);
 double k=1;
    Create(root,k);

    midOrder(root);
    cout<<endl;
    postOrder(root);
    clear(root);
    return 0;
}

 void Create(Tree *p,double a)
 { if(a>i) return;
    if(!p) p=new Tree;
    p->x=a;
    Create(p->left,2*a);
    Create(p->right,2*a+1);
 }


 void midOrder(Tree *p)
 {
     if(!p) return;

     midOrder(p->left);
     if(p->data!='.') cout<<p->data<<' ';
    midOrder(p->right);
 }
  void postOrder(Tree *p)
  {
       if(!p) return;

     postOrder(p->left);
     postOrder(p->right);
      if(p->data!='.') cout<<p->data<<' ';
  }
   void clear(Tree *p)
   {
       if (!p) return;
       clear (p->left);
       clear (p->right);
       delete p;
   }


  • 你可以看下这个问题的回答https://ask.csdn.net/questions/199634
  • 你也可以参考下这篇文章:输入某二叉树的前序遍历和中序遍历的结果,重建二叉树并输出后续遍历的结果!
  • 除此之外, 这篇博客: 二叉树相关算法中的 二、二叉树的路径:输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  •  
    /*
    struct TreeNode {
    	int val;
    	struct TreeNode *left;
    	struct TreeNode *right;
    	TreeNode(int x) :
    			val(x), left(NULL), right(NULL) {
    	}
    };*/
    class Solution {
    public:
        //这类问题可以用带记忆的DFS来解决。分享一个这类问题的典型解法。
        vector<vector<int> > FindPath(TreeNode* root,int expectNumber) {
            vector<vector<int>> ret;
            vector<int> trace;
            if(root)
                dfs(root,expectNumber,ret,trace);
            return ret;
        }
        void dfs(TreeNode* root,int s,vector<vector<int>> &ret,vector<int> &trace) {
            trace.push_back(root->val);
            if(!root->left&&!root->right) {
                if(s==root->val)
                    ret.push_back(trace);
            }
            if(root->left)
                dfs(root->left,s-root->val,ret,trace);
            if(root->right)
                dfs(root->right,s-root->val,ret,trace);
            trace.pop_back();
        }
    };
    

    二叉树的直径: 给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。

    示例 :
    给定二叉树

          1
         / \
        2   3
       / \     
      4   5    
    

    返回 3, 它的长度是路径 [4,2,1,3] 或者 [5,2,1,3]。

    class Solution {
        int ans;
        int depth(TreeNode* root){
            if (root == NULL) return 0;
            int L = depth(root->left);
            int R = depth(root->right);
            ans = max(ans, L + R + 1);
            return max(L, R) + 1;
        }
    public:
        int diameterOfBinaryTree(TreeNode* root) {
            ans = 1;
            depth(root);
            return ans - 1;
        }
    };
    

  • 您还可以看一下 Gardener老师的环境配置和二进制转换课程中的 软件开发的常识小节, 巩固相关知识点
  • 以下回答由chatgpt基于相关博客总结生成:

    对于问题中提到的扩展二叉树代码崩溃的问题,我需要先看一下完整的代码才能确定问题所在。但是,我可以根据提供的参考资料给出一个可能出现的问题和对应的解决方案。

    问题可能出现在二叉链表中存在太多的空指针,导致了空间浪费。为了解决这个问题,可以考虑优化二叉链表的建立过程,尽量避免空指针的产生。具体的做法是,采用动态数组的方式存储二叉树节点,即在建立节点之前先统计出二叉树的大小(节点个数),然后申请一个等大小的动态数组进行存储。这样能够最大限度地避免空间浪费,提高空间利用率。

    以下是示例代码:

    #include <iostream>
    using namespace std;
    
    struct TreeNode {
        int val;
        TreeNode* left;
        TreeNode* right;
        TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    };
    
    TreeNode* createTree(int* vals, int len, int index) {
        if (index >= len || vals[index] == -1) {
            // 数组越界或当前节点为空
            return nullptr;
        }
        TreeNode* node = new TreeNode(vals[index]);  // 动态申请节点
        node->left = createTree(vals, len, 2 * index + 1);
        node->right = createTree(vals, len, 2 * index + 2);
        return node;
    }
    
    void postorderTraversal(TreeNode* root) {
        if (!root) return;
        postorderTraversal(root->left);
        postorderTraversal(root->right);
        cout << root->val << " ";
    }
    
    void inorderTraversal(TreeNode* root) {
        if (!root) return;
        inorderTraversal(root->left);
        cout << root->val << " ";
        inorderTraversal(root->right);
    }
    
    int main() {
        int vals[] = {1, 2, 3, 4, -1, 5, 6, -1, -1, -1, -1, 7, 8, -1, 9};
        int len = sizeof(vals) / sizeof(int);
        TreeNode* root = createTree(vals, len, 0);
        cout << "后序遍历:";
        postorderTraversal(root);
        cout << endl;
        cout << "中序遍历:";
        inorderTraversal(root);
        cout << endl;
        return 0;
    }
    

    在这段代码中,我创建了一个名为createTree的函数,用于动态申请节点并构建二叉链表。在每一层递归中,先判断当前节点是否为空,如果是则返回空指针;否则根据当前节点的值创建新的节点,并递归创建左子树和右子树。这样可以保证每一个动态申请的节点都不是空指针,尽量避免产生空指针,提高空间利用率。

    另外,为了验证程序的正确性,我也提供了后序遍历和中序遍历输出的函数。这样可以方便地检查构建的二叉树是否正确。

仅供参考:

#include <iostream>
#include <stack>
#include <queue>
#include <locale.h>
using namespace std;
typedef struct BiTNode {//二叉树结点
    char data;                      //数据
    struct BiTNode *lchild,*rchild; //左右孩子指针
} BiTNode,*BiTree;
int CreateBiTree(BiTree &T) {//按先序序列创建二叉树
    char data;
    scanf("%c",&data);//按先序次序输入二叉树中结点的值(一个字符),‘#’表示空树
    if (data == '#') {
        T = NULL;
    } else {
        T = (BiTree)malloc(sizeof(BiTNode));
        T->data = data;         //生成根结点
        CreateBiTree(T->lchild);//构造左子树
        CreateBiTree(T->rchild);//构造右子树
    }
    return 0;
}
void Visit(BiTree T) {//输出
    if (T->data != '#') {
        printf("%c ",T->data);
    }
}
void PreOrder(BiTree T) {//先序遍历
    if (T != NULL) {
        Visit(T);               //访问根节点
        PreOrder(T->lchild);    //访问左子结点
        PreOrder(T->rchild);    //访问右子结点
    }
}
void InOrder(BiTree T) {//中序遍历
    if (T != NULL) {
        InOrder(T->lchild);     //访问左子结点
        Visit(T);               //访问根节点
        InOrder(T->rchild);     //访问右子结点
    }
}
void PostOrder(BiTree T) {//后序遍历
    if (T != NULL) {
        PostOrder(T->lchild);   //访问左子结点
        PostOrder(T->rchild);   //访问右子结点
        Visit(T);               //访问根节点
    }
}
void PreOrder2(BiTree T) {//先序遍历(非递归)
//访问T->data后,将T入栈,遍历左子树;遍历完左子树返回时,栈顶元素应为T,出栈,再先序遍历T的右子树。
    stack<BiTree> stack;
    BiTree p = T;//p是遍历指针
    while (p || !stack.empty()) {   //栈不空或者p不空时循环
        if (p != NULL) {
            stack.push(p);          //存入栈中
            printf("%c ",p->data);  //访问根节点
            p = p->lchild;          //遍历左子树
        } else {
            p = stack.top();        //退栈
            stack.pop();
            p = p->rchild;          //访问右子树
        }
    }
}
void InOrder2(BiTree T) {//中序遍历(非递归)
//T是要遍历树的根指针,中序遍历要求在遍历完左子树后,访问根,再遍历右子树。
//先将T入栈,遍历左子树;遍历完左子树返回时,栈顶元素应为T,出栈,访问T->data,再中序遍历T的右子树。
    stack<BiTree> stack;
    BiTree p = T;//p是遍历指针
    while (p || !stack.empty()) {   //栈不空或者p不空时循环
        if (p != NULL) {
            stack.push(p);          //存入栈中
            p = p->lchild;          //遍历左子树
        } else {
            p = stack.top();        //退栈,访问根节点
            printf("%c ",p->data);
            stack.pop();
            p = p->rchild;          //访问右子树
        }
    }
}

typedef struct BiTNodePost{
    BiTree biTree;
    char tag;
} BiTNodePost,*BiTreePost;
void PostOrder2(BiTree T) {//后序遍历(非递归)
    stack<BiTreePost> stack;
    BiTree p = T;//p是遍历指针
    BiTreePost BT;
    while (p != NULL || !stack.empty()) {//栈不空或者p不空时循环
        while (p != NULL) {//遍历左子树
            BT = (BiTreePost)malloc(sizeof(BiTNodePost));
            BT->biTree = p;
            BT->tag = 'L';//访问过左子树
            stack.push(BT);
            p = p->lchild;
        }
        while (!stack.empty() && (stack.top())->tag == 'R') {//左右子树访问完毕访问根节点
            BT = stack.top();
            stack.pop();//退栈
            printf("%c ",BT->biTree->data);
        }
        if (!stack.empty()) {//遍历右子树
            BT = stack.top();
            BT->tag = 'R';//访问过右子树
            p = BT->biTree;
            p = p->rchild;
        }
    }
}

void LevelOrder(BiTree T) {//层次遍历
    if (T == NULL) return;
    BiTree p = T;
    queue<BiTree> queue;//队列
    queue.push(p);//根节点入队
    while (!queue.empty()) {    //队列不空循环
        p = queue.front();      //对头元素出队
        printf("%c ",p->data);  //访问p指向的结点
        queue.pop();            //退出队列
        if (p->lchild != NULL) {//左子树不空,将左子树入队
            queue.push(p->lchild);
        }
        if (p->rchild != NULL) {//右子树不空,将右子树入队
            queue.push(p->rchild);
        }
    }
}
int main() {
    BiTree T;

    setlocale(LC_ALL,"chs");
    CreateBiTree(T);

    printf("先序遍历        :");PreOrder  (T);printf("\n");
    printf("先序遍历(非递归):");PreOrder2 (T);printf("\n");
                                               printf("\n");
    printf("中序遍历        :");InOrder   (T);printf("\n");
    printf("中序遍历(非递归):");InOrder2  (T);printf("\n");
                                               printf("\n");
    printf("后序遍历        :");PostOrder (T);printf("\n");
    printf("后序遍历(非递归):");PostOrder2(T);printf("\n");
                                               printf("\n");
    printf("层次遍历        :");LevelOrder(T);printf("\n");

    return 0;
}
//ABC##DE#G##F###
//先序遍历        :A B C D E G F
//先序遍历(非递归):A B C D E G F
//
//中序遍历        :C B E G D F A
//中序遍历(非递归):C B E G D F A
//
//后序遍历        :C G E F D B A
//后序遍历(非递归):C G E F D B A
//
//层次遍历        :A B C D E F G
//

///       A
///      /
///     B
///    / \
///   C   D
///      / \
///     E   F
///      \
///       G


巧了,我也想问,二叉树还不会呢