一 问题描述:
找出m个整数中第k(0<k<m+1)大的整数。
二 举例:
假设有12个整数:data[1, 4, -1, -4, 9, 8, 0, 3, -8, 11, 2, -9],请找出第5大的数(容易知道是0)。
三 算法思路:
一种基于快排思想的算法可以在O(n)复杂度内找到第k大的数,首先要知道partition这个函数,它可以调整一个序列
使小于key的元素都排在key左边,大于key的元素都排在key右边,key可以在这个序列中任意选择,一般选择给定序
列的首元素。
partition函数的一般形式:
int partition(int * data, int low, int high)
其中low和high分别是给定下标的上下边界。
先举例说明,调用partition(data, 1, 8),就是要将data中从data[1]到data[8]之间的序列分为两部分
截取的序列:data[2]--data[8]
4, -1, -4, 9, 8, 0, 3, -8
key选取第一个数:
key = 4
调用partition(data, 2, 8)后,这个序列变为:
-8, -1, -4, 3, 0, 4, 8, 9
需要注意的是,data[1]到data[8]这个序列片段在原来data[0]到data[11]这个大序列中已经发生改变,而其他没有截取到的片段保持不变。
partition的算法步骤如下:
1 设置两个下标left和right,left = low,right = high
此时left指向4,也是key元素,right指向-8
4, -1, -4, 9, 8, 0, 3, -8
2 从right开始寻找一个小于key的数,它是-8,找到后将它赋值给left指向的元素4
4, -1, -4, 9, 8, 0, 3, -8 --找到是-8
-8, -1, -4, 9, 8, 0, 3, -8 --赋值到4的位置,
注意key元素4在这些步骤之前就已经保存
3 从left开始寻找一个比key大的元素,它是9,把它赋值为right指向的元素-8
-8, -1, -4, 9, 8, 0, 3, -8 --找到是9
-8, -1, -4, 9, 8, 0, 3, 9 --赋值到-8的位置
4 重复步骤2,再次从right开始寻找一个小于key的数,它是3,将它赋值为left指向的元素9
-8, -1, -4, 9, 8, 0, 3, -8 --找到是3
-8, -1, -4, 3, 8, 0, 3, 9 --赋值到9的位置
5 重复步骤3,再次从left开始寻找一个大于key的数,它是8,将它赋值到right指向的位置
-8, -1, -4, 9, 8, 0, 3, -8 --找到是8
-8, -1, -4, 3, 8, 0, 8, 9 --赋值到3的位置
6 重复步骤2,再次从right开始寻找一个小于key的数,它是0,将它赋值为left指向的元素
-8, -1, -4, 9, 8, 0, 3, -8 --找到是0
-8, -1, -4, 3, 8, 0, 0, 9 --赋值3的位置
7 重复步骤3,再次从left开始寻找一个大于key的数,现在left指向0,left--后,会发现left == right,所以现在要退出循环,并把key元素赋值为left所在位
-8, -1, -4, 3, 8, 4, 0, 9 --完成了最后一步
排在该算法的主要步骤是:
原文:http://www.cnblogs.com/lovexfr/p/5456730.html