求直方图中最大矩形面积(C语言实现)

来源:互联网 发布:网络实名制对言论自由 编辑:程序博客网 时间:2024/05/16 18:07

一个直方图是由许多矩形组成,在给定的直方图中找出最大的矩形面积。同时,为了简化问题,假定所有矩形宽度都为1个单位。例如,下面的直方图中有6个矩形,高度分别是(6,7,8,4,5,3)。最大的矩形面积是18(如下图所示,最大矩形面积用红色方框标出)


下面给出的解决方法时间复杂度为O(n)。矩形面积的计算公式为底*高。对于求直方图中的最大矩形面积。就是以某个矩形的高度为高,确定其左右边界。确定两个边界后就可以得到宽度,从而最终计算出面积。这里最难理解的就是左右边界。如何取得它的左右边界。我们从左向右遍历每个矩形,并通过一个栈来存储这些矩形高度在输入数组中的索引(如定义一个整型数组height[n]={6,7,8,4,5,3}表示直方图中各矩形的高,栈里面保存该数组的下标,即这些矩形高度在数组中的索引)。每个矩形(索引)仅压入栈中一次。当输入的矩形高度大于栈顶矩形的高度,或者当栈为空时,将当前矩形高度的数组索引入栈,当输入的矩形高度小于栈顶矩形的高度,那么栈顶矩形将会被弹出,然后计算矩形面积,其中矩形面积的高为弹出单个矩形条的高。现在得到了高,接下来得到左右边界后便可计算出宽度。由于当前输入的矩形i的高度小于栈顶矩形,那么以栈顶为高的矩形右边界为i。当前栈若非空,那么栈中矩形条的高度一定是小于等于弹出的矩形的高度,因此左边界就确定了。如果栈不为空,则弹出矩形的宽度则为(i-peek()-1).否则,矩形宽度为i.

最终算法步骤归纳为:

  1. 创建一个空栈
  2. 从第一个矩形条开始,对每个矩形条的高度height[i] (i的取值范围是[0,n-1])执行下面两步 
    a) 如果栈为空,或height[i]大于等于栈顶元素,那么将矩形条i压入栈中。 
    b)如果输入的矩形条高度小于栈顶元素高度,那么将栈顶元素在输入数组中的索引top出栈,然后计算矩形面积。矩形的高为height[top],而右边界为i,左边界为当前栈顶元素对应的索引,若栈为空,则宽度就是i。
  3. 经过计算后,栈过非空,然后将栈中元素逐个弹出,并按照步骤2计算矩形面积,并且更新最大值。下面的代码是纯C语言实现。先定义了栈,栈的大小指定为10.实际应用中,可灵活使用,改变其大小。
  4. /*求直方图的最大矩形面积*/#include <stdlib.h>#include <stdio.h>typedef int ElemType;struct StackSq{ElemType *stack;int top;int MaxSize;};void InitStack(struct StackSq *s){s->MaxSize=10;/*置栈空间初始最大长度为10*/s->stack=(int *)malloc(10*sizeof(ElemType));/*动态存储空间分配*/s->top=-1;/*置栈为空*/}//1void Push(struct StackSq* S,ElemType x){//if(S->top==S->MaxSize-1)againMalloc(S);/*若栈空间用完则重新分配更大的存储空间*/S->top++;/*栈顶指针后移一个位置*/S->stack[S->top]=x;/*将新元素插入到栈顶*/}//2ElemType Pop(struct StackSq* S){if(S->top==-1){printf("栈空,无元素出栈!\n");exit(1);}S->top--;return S->stack[S->top+1];}//3ElemType Peek(struct StackSq* s){if(s->top==-1){printf("栈空,无元素出栈!\n");exit(1);}return s->stack[s->top];}int EmptyStack(struct StackSq* S){if(S->top==-1) return 1;else return 0;}int largestRectangleArea(int height[],int n){    struct StackSq s;    InitStack(&s);        int max_area = 0; // 最大矩形面积        int top; // 栈顶        int area_with_top;        int i = 0;        while (i < n) {            if (EmptyStack(&s) || height[Peek(&s)] <= height[i]) {               Push(&s,i++);            } else {                top=Pop(&s);                area_with_top = height[top] * ((EmptyStack(&s) ? i : i -Peek(&s)- 1));//这个非常重要,求宽度。                max_area = max_area>area_with_top?max_area:area_with_top;            }        }        while (!EmptyStack(&s)) {            top=Pop(&s);            area_with_top = height[top] *((EmptyStack(&s) ? i : i -Peek(&s)- 1));            max_area = max_area>area_with_top?max_area:area_with_top;        }        return max_area;    }/*测试*/int main(int argc, char *argv[]){ int height[]={6,7,8,4,5,3}; printf("the area of the Largest Rectangle in Histogram is %d",largestRectangleArea(height,6));}
1 0
原创粉丝点击