zoukankan      html  css  js  c++  java
  • Algs4-1.4.32均摊分析

    1.4.32均摊分析。请证明,对一个基于大小可变的数组实现的空栈的M次操作访问数组的次数和M成正比。
    答:设N为2的幂

    1)连续N次的push操作均摊后每次push操作访问数组的次数

    设数组长度为L,一次延长需要的数组访问次数为:初始化2L长度的数组需要将数组元素置初值,需要2L次写操作。将原数组中L个元素读出,然后写入到新数组各需L次读、L次写操作。那么数组一次延长需要4L次数组元素的访问,也就是上一次数组长度的4倍。

    数组开始长度为1,之后每次延长都是上一次长度的2倍,数组长度最后一次延长是从N/2至N。连续N次push延长数组需要访问数组元素次数为:

      图片

    N次push操作需要对数组元素进行N次写访问,那么最终的数组访问次数=4N-4+N=5N-4,连续N次push操作均摊后每次push操作对数组访问次数=(5N-4)/N。

    2)最坏的连续push操作均摊后每次push操作访问数组的次数

    设栈长度达到N/2+1时数组长度从N/2延长至N。连续的push操作使数组从长度N延长至2N是最坏的连续push情况。栈长度在N/2+2至N区间进行的N/2-1次push操作不会促使数组延长,此区间每次push对应一次数组元素的写访问。栈长度从N变为N+1时需要一次push操作和一次数组延长,一次push操作对应一次数组写操作,一次数组延长对应4N次数组访问。那么栈长度从N/2+1变为N+1需要进行的数组访问次数为N/2+4N,push操作次数为N/2,均摊后每次push操作对应的数组访问次数为(N/2+4N)/(N/2)=9

    3)连续的N次pop操作均摊后每次pop操作访问数组的次数,不考虑pop之前的push

    设数组长度为L,一次收缩需要的数组访问次数为:初始化L/2长度的数组需要将数组元素置初值,需要L/2次写操作。将原数组中L/4个元素读出,然后写入到新的数组各需L/4次读、L/4次写,总的次数为L。那么数组一次收缩需要L次数组访问,也就是收缩后长度的2倍。

    数组开始长度为N,之后每次收缩后新的长度都是原有长度的1/2,每一次收缩需要访问的数组次数为收缩后长度的2,因为在栈长度/数组长度=1/4时才收缩,所以最后一次收缩是在数组长度为4时。连续Npop收缩数组需要访问数组元素次数为:
    图片

    N次pop操作需要对数组元素进行N次读访问,那么最终的数组访问次数=2N-4+N=3N-4,连续N次pop操作均摊后每次pop操作对数组访问次数=(3N-4)/N

    4)最坏的连续pop操作均摊后每次pop操作访问数组的次数,不考虑pop之前的push

    设数组完成最近一次的收缩后数组长度为4N,栈长度为2N,数组长度收缩至2N需要访问的次数为:连续进行N次pop,每次pop需要一次数组元素读访问,经过N次pop后栈长度个数减至N,触发数组收缩至2N的操作,数组收缩至2N时需要初始化新的数组,为数组元素置空操作需要2N次写访问,将原数组中的N个元素读出需要N次读访问,再将N个元素写入新数组需要N次写访问,那么总的访问次数为: N+2N+N+N=5N,pop操作次数为N,均摊成本=数组访问次数/操作次数=5N/N=5

     

    5)连续N次push操作后连续N次pop操作均摊访问数组的次数

    依据上述1)得出连续N次push需要5N-4次访问,依据上述3)连续N次pop需要3N-4次访问,共需要((5N-4)+(3N-4))=8N-8,操作次数N+N=2N,均摊成本=(8N-8)/2N

     

    6)最坏情况下连续的push与pop均摊访问数组的成本

    设数组完成最近一次延长后数组的长度是2N,栈长度是N+1。连续进行N次push后数组延长至4N,栈长度为2N+1,push操作对数组访问的次数为4N次的数组初始化,2N次对旧数组元素读,2N次对新数组写,N次push对应N次写,一共9N次访问。数组长度从4N,栈长度从2N+1使数组收缩一次需要N+1次pop,需要对数组访问的次数为2N次数组初始化,N次对旧数组元素读,N次对新数组写,N+1次pop对应N+1次读,一共4N+1次访问。N次push与N+1次pop的对数组均摊访问次数=(9N+4N+1)/(2N+1)=(13N+1)/(2N+1)

     

    根据以上6种情况的分析,混合操作均摊后对数组访问的次数都是常数,那么M次混合操作在任何情况下对数组的访问次数成正比。

     附1:基于可变数组的栈代码
    import java.util.Iterator;
    public class ResizingArrayStack<Item> implements Iterable<Item>
    {
        private Item[] a=(Item[]) new Object[1];
        private int N=0;
        public boolean isEmpty(){return N==0;}
        public int size(){return N;}
        private void resize(int max)
        {
            Item[] temp=(Item[]) new Object[max];
            for(int i=0;i<N;i++)
                temp[i]=a[i];
            a=temp;
        }//end resize
        public void push(Item item)
        {
            if(N==a.length) resize(2*a.length);
                a[N++]=item;
        }//end push
        public Item pop()
        {
            Item item=a[--N];
            a[N]=null;
            if(N>0 && N==a.length/4) resize(a.length/2);
            return item;
        }//end pop
        public Iterator<Item> iterator()
        {return new ReverseArrayIterator();}
       
        private class ReverseArrayIterator implements Iterator<Item>
        {
            private int i=N;
            public boolean hasNext(){return i>0;}
            public Item next(){return a[--i];}
            public void remove(){}
         }
    }
    附2:求和公式
    图片

  • 相关阅读:
    jQuery ajax解析xml文件demo
    Jquery ajax传递xml方式在ie8下兼容问题
    Ajax 跨域请求
    【leetcode刷题笔记】Maximal Rectangle
    【leetcode刷题笔记】Substring with Concatenation of All Words
    【leetcode刷题笔记】Largest Rectangle in Histogram
    【leetcode刷题笔记】Decode Ways
    【leetcode刷题笔记】3Sum Closest
    【leetcode刷题笔记】3Sum
    【leetcode刷题笔记】Divide Two Integers
  • 原文地址:https://www.cnblogs.com/longjin2018/p/9854502.html
Copyright © 2011-2022 走看看