前序遍历二叉树

本文详细讲解了如何用栈实现前序遍历二叉树,并在蛋糕体积计算中运用动态剪枝策略,减少计算复杂性。
摘要由CSDN通过智能技术生成

前序遍历二叉树

使用栈进行前序历遍二叉树,在前序遍历中,首先访问根节点,然后递归地前序遍历左子树,最后递归地前序遍历右子树。

struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
};
int* preorderTraversal(struct TreeNode* root, int* returnSize) {
    int* ans = (int*)malloc(sizeof(int) * 100);
    *returnSize = 0;
    struct TreeNode* node = root;
    struct TreeNode* stack[300];
    int top = 0;
    while (top > 0 || node) {
        while (node) {
            ans[(*returnSize)++] = node->val;
            stack[top++] = node;//即为进入更深一层函数。
            node = node->left;
        }//当一次循环终止代表,当前节点位于左子树的左空指针。
        node = stack[--top];//回溯一层,进入关于右子树函数
        node = node->right;
    }
    return ans;
}


在第13行,循环记录根节点数据域到数组,在将根节点存入栈中后,访问根节点的左孩子(每次访问节点时,第一个操作为记录根节点的数据域,以保证前序遍历的正确性)即不断增加深度,直到叶节点的左子树为空。后从栈(注意栈,后进先出)取出叶节点的根节点,访问右子树,后续操作与上面相同,记录数据域,访问更深度位置。

上述为使用栈模拟递归进行前序遍历。

解决实际问题时,与进行遍历二叉树类似,不同的是,在对子树的访问时,常常有更多种情况,并不是简单的左,右孩子,为降低复杂度,对显然错误的根节点及其子树不再访问,称之为剪枝。

这里以实际问题为例:

7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层生日蛋糕,每层都是一个圆柱体。
设从下往上数第i(1 <= i <= M)层蛋糕是半径为Ri, 高度为Hi的圆柱。当i < M时,要求Ri > Ri+1且Hi > Hi+1。
由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积Q最小。
令Q = Sπ
请编程对给出的N和M,找出蛋糕的制作方案(适当的Ri和Hi的值),使S最小。
(除Q外,以上所有数据皆为正整数)

试规定 s i g m a ( 1 , m ) a [ i ] = a [ 1 ] + a [ 2 ] + a [ 3 ] + … a [ m − 1 ] + a [ m ] ; 试规定{sigma(1, m)a[i]} = a[1]+a[2]+a[3]+…a[m-1]+a[m]; 试规定sigma(1,m)a[i]=a[1]+a[2]+a[3]+a[m1]+a[m];
那么体积 N ∗ P I = s i n g m a ( 1 , m ) P I ∗ R i ∗ R i ∗ H i , 那么体积 N*PI = singma(1,m)PI*Ri*Ri*Hi, 那么体积NPI=singma(1,m)PIRiRiHi,

注意蛋糕外表面(最下一层的下底面除外)

所以 Q = S ∗ P I = R 1 ∗ R 1 + s i g m a ( 1 , n ) 2 ∗ P I ∗ R i ∗ H i 所以 Q = S*PI =R1*R1 + {sigma(1,n) 2*PI*Ri*Hi} 所以Q=SPI=R1R1+sigma(1,n)2PIRiHi

考虑到半径不断减少,并且为正整数,第m层最小为1,那么第1层最小为m,第i层最小半径为m-i+1。

类似的,第i层最小高度为m-i+1,那么就有最小体积,侧面积记作min_v[i],。

那么 对于(V[i-1] + min_v[i] > N) 的节点,不再进行访问。

但是该操作为静态操作,我们考虑更动态的剪枝: i在[k,m]区间内,就有Ri>=Rk,变形为:1 >= Ri/Rk

那么k层到m层增加的侧面积:
2 s i g m a ( k , m ) ( R i ∗ H i ) > = 2 s i g m a ( k , m ) [ R i ∗ R i ∗ H i ] / R k = 二倍的剩余体积除以 R k 2sigma(k,m)(Ri * Hi) >= 2sigma(k,m)[ Ri*Ri*Hi] /Rk = 二倍的剩余体积除以Rk 2sigma(k,m)(RiHi)>=2sigma(k,m)[RiRiHi]/Rk=二倍的剩余体积除以Rk
因此 ,我们可以对不符合这该条件的部分进行剪枝。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值