选择问题的线性期望时间算法
来源:互联网 发布:销售软件使用心得 编辑:程序博客网 时间:2024/04/27 16:00
由于我们能够以O(NlogN)时间给数组排序,因此可以期望为选择问题得到一个更好的时间界。我们这里介绍的查找集合S中第k个最小元的算法几乎与快速排序相同。事实上,其前三步是相同的。我们把这种算法叫做快速选择(quickselect)。令|Si|为Si中元素的个数,快速选择的步骤如下:
1)如果|S|=1,那么k=1并将S中的元素作为答案返回。如果正在使用小数组的截止方法且|S|≤CUTOFF,则将S排序并返回第k个最小元。
2)选取一个枢纽元v∈S。
3)将集合S-{v}分割成S1和S2,就像快速排序中所做的那样。
4)如果k≤|S1|,那么第K个最小元必然在S1中。在这种情况下,返回quickselect(S1,k).如果k=1+|S1|,那么枢纽元就是第k个最小元,将它最为答案返回。否则,第k个最小元就在S2中,他是S2中的第(k-|S1|-1)个最小元。我们进行一次递归调用并返回quickselect(S2,k-|S1|-1).
与快速排序对比,快速选择只进行了一次递归调用而不是两次。快速选择的最坏情形和快速排序的相同,也就是O(N2)。直观看来,这是因为快速排序的最坏情形发生在S1和S2有一个是空的时候;于是,快速选择也就不是真的节省一次递归调用。不过平均运行时间是O(N)。具体分析类似快速排序的分析。
快速排序的实现甚至比抽象描述还要简单,其程序如下。当算法终止时,第k个最小元就在位置k-1上(因为数组开始于下标0)。这破坏了原来的排序;如果不希望这样,那么需要做一份拷贝。
/**//**
* Simple insertion sort.
*/
template <typename Comparable>
void insertionSort( vector<Comparable> & a )
...{
for( int p = 1; p < a.size( ); p++ )
...{
Comparable tmp = a[ p ];
int j;
for( j = p; j > 0 && tmp < a[ j - 1 ]; j-- )
a[ j ] = a[ j - 1 ];
a[ j ] = tmp;
}
}
/**//**
* Return median of left, center, and right.
* Order these and hide the pivot.
*/
template <typename Comparable>
const Comparable & median3( vector<Comparable> & a, int left, int right )
...{
int center = ( left + right ) / 2;
if( a[ center ] < a[ left ] )
swap( a[ left ], a[ center ] );
if( a[ right ] < a[ left ] )
swap( a[ left ], a[ right ] );
if( a[ right ] < a[ center ] )
swap( a[ center ], a[ right ] );
// Place pivot at position right - 1
swap( a[ center ], a[ right - 1 ] );
return a[ right - 1 ];
}
/**//**
* Internal selection method that makes recursive calls.
* Uses median-of-three partitioning and a cutoff of 10.
* Places the kth smallest item in a[k-1].
* a is an array of Comparable items.
* left is the left-most index of the subarray.
* right is the right-most index of the subarray.
* k is the desired rank (1 is minimum) in the entire array.
*/
template <typename Comparable>
void quickSelect( vector<Comparable> & a, int left, int right, int k )
...{
if( left + 10 <= right )
...{
Comparable pivot = median3( a, left, right );
// Begin partitioning
int i = left, j = right - 1;
for( ; ; )
...{
while( a[ ++i ] < pivot ) ...{ }
while( pivot < a[ --j ] ) ...{ }
if( i < j )
swap( a[ i ], a[ j ] );
else
break;
}
swap( a[ i ], a[ right - 1 ] ); // Restore pivot
// Recurse; only this part changes
if( k <= i )
quickSelect( a, left, i - 1, k );
else if( k > i + 1 )
quickSelect( a, i + 1, right, k );
}
else // Do an insertion sort on the subarray
insertionSort( a, left, right );
}
* Simple insertion sort.
*/
template <typename Comparable>
void insertionSort( vector<Comparable> & a )
...{
for( int p = 1; p < a.size( ); p++ )
...{
Comparable tmp = a[ p ];
int j;
for( j = p; j > 0 && tmp < a[ j - 1 ]; j-- )
a[ j ] = a[ j - 1 ];
a[ j ] = tmp;
}
}
/**//**
* Return median of left, center, and right.
* Order these and hide the pivot.
*/
template <typename Comparable>
const Comparable & median3( vector<Comparable> & a, int left, int right )
...{
int center = ( left + right ) / 2;
if( a[ center ] < a[ left ] )
swap( a[ left ], a[ center ] );
if( a[ right ] < a[ left ] )
swap( a[ left ], a[ right ] );
if( a[ right ] < a[ center ] )
swap( a[ center ], a[ right ] );
// Place pivot at position right - 1
swap( a[ center ], a[ right - 1 ] );
return a[ right - 1 ];
}
/**//**
* Internal selection method that makes recursive calls.
* Uses median-of-three partitioning and a cutoff of 10.
* Places the kth smallest item in a[k-1].
* a is an array of Comparable items.
* left is the left-most index of the subarray.
* right is the right-most index of the subarray.
* k is the desired rank (1 is minimum) in the entire array.
*/
template <typename Comparable>
void quickSelect( vector<Comparable> & a, int left, int right, int k )
...{
if( left + 10 <= right )
...{
Comparable pivot = median3( a, left, right );
// Begin partitioning
int i = left, j = right - 1;
for( ; ; )
...{
while( a[ ++i ] < pivot ) ...{ }
while( pivot < a[ --j ] ) ...{ }
if( i < j )
swap( a[ i ], a[ j ] );
else
break;
}
swap( a[ i ], a[ right - 1 ] ); // Restore pivot
// Recurse; only this part changes
if( k <= i )
quickSelect( a, left, i - 1, k );
else if( k > i + 1 )
quickSelect( a, i + 1, right, k );
}
else // Do an insertion sort on the subarray
insertionSort( a, left, right );
}
- 选择问题的线性期望时间算法
- 期望为线性时间的选择算法
- 期望时间为线性时间的选择算法(C++)
- 期望为线性时间的选择算法randomizedSelect
- Java 期望为线性时间的选择算法
- CLRS 9.2期望为线性时间的选择算法
- 期望为线性时间的选择算法(c语言)
- 期望为线性时间选择算法
- 线性期望时间选择问题C语言
- 线性期望时间选择问题C语言
- 期望线性时间选择
- 算法之分治——期望线性时间的选择(基础版本的选择)
- 期望为线性的选择算法
- 算法导论程序19-期望为线性时间的选择算法(Python)
- 算法--顺序统计-期望线性时间做选择
- 小白进阶之期望为线性时间的选择算法
- 线性时间的选择算法
- 算法导论:第9章 中位数和顺序统计量_1期望为线性时间的选择算法
- 一个老程序员的工作经历
- NET数据提供程序
- 世界著名大学开放课程
- 写文章
- 有关字符串转换(大写转换为小写,小写换大写)
- 选择问题的线性期望时间算法
- 导线辐射预估
- 通讯行业多媒体信息发布系统方案
- 大三了,要找工作了……
- C#实现常用的数据结构(一):链表
- 如何对const TDesC&数据类型进行Trim
- Torque的编译工具
- Windows系统管理24招
- 中文搜索引擎技术揭密:中文分词