常见循环结构频度分析

while

代码结构如下, 

while (/* condition */)
{
    /* code */
}

可以分为几个相似的子类,下面分别讨论。 

可以转化为等价的单变量for循环

i = 1;
while (i <= n - 1)
{
    // 分析此处频度
    i++;
}

可以转化为等价的python语句,

for i in range(1, n):
    # 分析此处频度

 容易看出,循环体中的代码将执行 n-1次,复杂度为O(n).

涉及双变量的循环

i = 1;
j = 0;
while (i + j <= n)
{
    // 分析此处频度
    if (i > j)
        j++;
    else
        i++;
}

可以把(i,j)理解为二维平面上点的坐标。经画图分析可知,(i,j)的运动轨迹是一条从(1,0)开始,到直线x+y=n右侧结束的折线(图略)。根据n的奇偶,折线结束时的行为有所不同。将频度与n的关系计算用代码呈现出来,

def my_f6(n):
    if n % 2 == 0:
        return n / 2
    else:
        return n // 2 + 1

涉及科学计算

如,

x = n;
y = 0;
while (x >= (y + 1) * (y + 1))
{
    // 分析此处频度
}

容易看出,

def my_f7(n):
    return int(n ** .5 - 1) + 1

分频器型

x = 91;
y = 100;
while (y > 0)
{
    // 分析此处频度
    if (x > 100)
    {
        x -= 10;
        y--;
    }
    else
        x++;
}

 本来,待分析代码只要执行100次,但由于迟滞变量x的存在,y递减的速度放慢了10倍。

do ... while

代码结构,

do
{
    /* code */
} while (/* condition */);

总是可以将do...while循环转化为等价的while循环,方法是:用while句取代do句,并在while句前添加循环体中的语句。 即,变为,

/* code */
while (/* condition */)
{
    /* code */
}

i = 1;
do
{
    // 分析此处频度
    i++;
} while (i <= n - 1);

 可以转化成等价的while循环,为,

i = 1;
// 分析此处频度
while (i < n) {
    // 分析此处频度
    i++;
}

进一步转化为,

# 分析此处频度
for i in range(1, n):
    # 分析此处频度

 容易看出,此例与前例的差别在于待分析语句在进入循环前已经执行了一次。自然,此例的频度为n.

for

这种循环和求和符号\sum类似,结构为,

for (size_t i = 0; i < count; i++)
{
    /* code */
}

即,

for i in range(n):
    # code

两层嵌套

例如,

for (i = 1; i <= n; i++)
{
    for (j = i; j <= n; j++)
        // 分析此处频度
}

转化为求和式,

\sum_{i=1}^{n} {\sum _{j=i}^{n}{1}}=\frac{n(n+1)}{2}

三层嵌套

如,

for (i = 1; i <= n; i++)
    for (j = 1; j <= i; j++)
        for (k = 1; k <= j; k++)
            // 分析此处频度

转化为求和式,

\sum_{i=1}^{n}{\sum_{j=1}^{i}{\sum_{k=1}^{j}{1}}}=\frac{n(n+1)(n+2)}{6}

注意,这里涉及到,

\sum_{i=1}^{n}{i^2}

计算方法是:考虑如下伸缩级数,

\sum_{i=1}^n{(i+1)^3-i^3}=(n+1)^3-1

两边展开,再利用

\sum_{i=1}^ni=\frac{n(n+1)}{2}

可得

\sum_{i=1}^ni^3=\frac{n(n+1)(2n+1)}{6}

附录

全部测试代码如下,

#!/usr/bin/env python
# coding: utf-8

# In[1]:


import numpy as np
import matplotlib.pyplot as plt


# In[2]:


def f4(n):
    k = 0
    for i in range(1, n + 1):        
        for j in range(i, n + 1):
            k += 1
    return k


# In[3]:


def f5(n):
    x = 0
    for i in range(1, n + 1):
        for j in range(1, i + 1):
            for k in range(1, j + 1):
                x += 1
    return x


# In[4]:


def f6(n):
    i = 1
    j = 0
    while i + j <= n:
        if i > j:
            j += 1
        else:
            i += 1
    return j


# In[5]:


def f7(n):
    x = n
    y = 0
    while (x >= (y + 1) ** 2):
        y += 1
    return y


# In[6]:


def f8(n):
    x = 91
    y = n
    k = 0
    while y > 0:
        k += 1
        if (x > 100):
            x -= 10
            y -= 1
        else:
            x += 1
    return k


# In[7]:


def functionEqual(f1, f2):
    x  = np.random.randint(1000, size=10)
    y1 = np.empty_like(x)
    for i in range(len(x)):
        y1[i] = f1(x[i])
    y2 = np.empty_like(x)
    for i in range(len(x)):
        y2[i] = f2(x[i])
    flag = True
    for i in range(len(x)):
        if y1[i] != y2[i]:
            flag = False
            break
    return flag


# In[8]:


def my_f4(n):
    return n * (n + 1) / 2


# In[9]:


def my_f5(n):
    return n * (n + 1) * (n + 2) / 6


# In[10]:


def my_f6(n):
    if n % 2 == 0:
        return n / 2
    else:
        return n // 2 + 1


# In[11]:


def my_f7(n):
    return int(n ** .5 - 1) + 1


# In[12]:


def my_f8(n):
    return 11 * n


# In[13]:


check = [
    functionEqual(f4, my_f4),
    functionEqual(f5, my_f5),
    functionEqual(f6, my_f6),
    functionEqual(f7, my_f7),
    functionEqual(f8, my_f8)
]
print(check)

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值