繁体   English   中英

分类算法的复杂性

[英]Complexity of sorting algorithm

这是一种排序算法,而不是聪明的算法。 在此版本中,当元素为非负数且最多出现一次时,它将很好地工作。 我对其时间的复杂性感到困惑。 是O(n)吗? 因此,就该符号而言,它比快速排序更好吗? 谢谢。 这是代码:

public int[] stupidSort( int[] array ){

// Variables
int max = array[0];
int index = 0;
int[] lastArray = new int[array.length];

// Find max element in input array
for( int i = 0; i < array.length; i++ ){
  if ( array[i] > max )
    max = array[i];
}

// Create a new array. In this array, element n will represent number of n's in input array
int[] newArray = new int[max + 1];

for ( int j = 0; j < array.length; j++ )
  newArray[array[j]]++;

// If element is bigger than 0, it means that number occured in input. So put it in output array
for( int k = 0; k < newArray.length; k++ ){
  if( newArray[k] > 0 )
    lastArray[index++] = k;
}
return lastArray;
}

您写的是计数排序 ,它确实具有O(n)复杂度。 但是,它不能与QuickSort进行比较,因为QuickSort是一种基于比较的算法。 这两种算法属于不同的类别(您是非比较类,quicksort是比较算法)。 您的算法(计数排序)假设数组中数字的范围是已知的,并且所有数字都是整数,而QuickSort则适用于每个数字。

您可以在此处了解更多有关排序算法的信息 在该链接中,您可以看到排序算法的复杂性分为两类:比较和非比较。

编辑

正如保罗·汉金(Paul Hankin)所指出的那样,复杂度并不总是O(n)。 它是O(n + k) ,其中k是输入数组的最大值。 下面引用的是时间复杂度,如Wikipedia文章所述,用于计数排序

由于该算法仅使用简单的for循环,而没有递归或子例程调用,因此分析起来很简单。 计数数组的初始化以及第二个for循环在计数数组上执行前缀求和,每个循环最多重复k + 1次,因此需要O(k)时间。 其他两个for循环以及输出数组的初始化各自花费O(n)时间。 因此,整个算法的时间就是这些步骤的时间之和,即O(n + k)。

给定的算法与Count sort非常相似。 QuickSort是一种基于比较模型的排序算法。 只有在最坏的情况下, QuickSort才会给出O(n ^ 2)的时间复杂度,否则为O(nlogn)。 QuickSort也与它的随机版本一起使用,它是枢轴随机选择的,因此,这种情况最经常避免的是最坏的情况。

编辑:更正,如paulhankin在评论复杂度= O(n + k)中指出的那样:

您提出的代码使用的是基于计数的排序,即计数排序,您的代码的时间复杂度为O(n + k)。 但是您必须意识到,该算法取决于输入范围,并且该范围可以是任意值。 此外,该算法不是InPlace而是Stable 在许多情况下,您要排序的数据不仅是整数,而且数据可以是任何带有键的数据,而这些键需要借助键进行排序。 如果不使用稳定算法,则在这种情况下排序可能会出现问题。

万一有人不知道,以防万一:

就地算法 :是一种其中所需的额外空间不依赖于给定输入的算法。

稳定算法 :例如,如果在排序之前数据集中有两个5,则排序之前排在第一的5排在第二,即使排序之后排在第二。

编辑:(关于aladinsane7的评论):是的, countSort的正式版也可以处理此方面。 如果您看看CountSort,那将是很好的。 其时间复杂度为O(n + k) 其中K代表数据范围,n是剩余算法的复杂度。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM