我知道插入排序应该是最坏的情况O(n ^ 2),但是我想知道为什么以下实现不是O(n)。
void main()
{
//insertion sort runs from i = 1 to i = n, thus is worst case O(n)
for (
int i = 1,
placeholder = 0,
A[] = { 10,9,8,7,6,5,4,3,2,1 },
j = i;
i <= 10;
j-- > 0 && A[j - 1] > A[j]
? placeholder = A[j], A[j] = A[j - 1], A[j - 1] = placeholder
: j = ++i
)
{
for (
int x = 0;
x < 10; x++
)
cout << A[x] << ' ';
cout << endl;
}
system("pause");
}
这里只涉及一个for循环,它从1到n。在我看来,这就是O(n)的定义。我到底在这里想念什么?
答案 0 :(得分:0)
那是一种非常奇怪的代码编写方式,但是定义中有2个for循环。不一定总是有嵌套循环才能拥有O(n ^ 2),也可以通过递归来获取它。 简单来说,O(n ^ 2)n只是表示输入大小为n时执行的操作数。
答案 1 :(得分:0)
草率的术语导致许多人得出错误的结论。这似乎是一个例子。
这里只涉及一个for循环,它从1到n。
是的,只有一个循环,但是您所指的“循环”是什么?我确实的意思是让您考虑一下。应该“它”指的是循环吗?这将与相当普遍但草率的术语使用相匹配,但是循环不会求值。因此,循环实际上无法从一个值运行到另一个值。在较简单的情况下可以忽略草率,但在您的情况下则不能。
通常,“ it”实际上是指loop control variable。对于一个简单的循环,例如for (int i = 0; i < 10; ++i)
,循环的迭代与分配给控制变量的值(在我的示例中为i
)之间存在一一对应的关系。因此,存在一个等价关系,当一个人真正表示控制变量时,就可以引用该循环。说一个循环从x到y确实意味着控制变量从x到y,并且每个分配给该控制变量的值都有一个循环迭代 >。此对应关系在您的代码中失败。
在您的循环中,从1到n的是i
。但是,i
不会随着循环的每次迭代而增加,因此“ 不是对您的循环的准确评估是“从1到n”。当i
为1时,最多进行2次迭代。这不是迭代与i
的值之间的一一对应关系。随着i
的增加,一对一的差异也增大。 i
的每个值都可能对应于i+1
迭代,因为j
从i
倒数到0
。最坏情况下n个条目的迭代总数是i
的每个值的潜在迭代总数:2 + 3 +⋯+(n + 1)=(n²+ 3n)/ 2。那是O(n²)。
故事的寓意:编写紧凑的密码不会神奇地改变所实现算法的复杂性。隐秘代码会使复杂性难以确定,但是您所要做的主要事情是使代码更难阅读。
答案 2 :(得分:-2)
给出的代码不是正确的c ++代码,甚至都不接近伪代码。 正确的代码应如下所示:
void main()
{
int i,j,key;
int A[]={10,9,8,7,6,5,4,3,2,1};
//cout<<"Array before sorting:"<<endl;
//for(i=0;i<10;i++)
//cout<<A[i]<<"\t";
//cout<<endl;
for(i=1;i<10;i++)
{
key=A[i];
for(j=i-1;j>=0 && A[j]>key;j--)
{
A[j+1]=A[j];
}
A[j+1]=key;
}
//cout<<"Array after sorting:"<<endl;
//for(i=0;i<10;i++)
//cout<<A[i]<<"\t";
//cout<<endl;
}
看,插入排序有两个循环。外循环用于维护键变量,内循环用于将键变量之前的元素与键变量进行比较。因此,最坏情况下的时间复杂度是O(n ^ 2)而不是O(n),因为插入排序的基本算法包含两个循环,在最坏情况下(即数组反转时),两个循环最终都会迭代n次。 。