一步一步写算法(之挑选最大的n个数)

简介: 原文: 一步一步写算法(之挑选最大的n个数) 【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com】    从一堆数据中挑选n个最大的数,这个问题是网上流传的比较广的几个问题之一。
原文: 一步一步写算法(之挑选最大的n个数)

【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com】


    从一堆数据中挑选n个最大的数,这个问题是网上流传的比较广的几个问题之一。具体来说,它的意思就是:假设我们有100个数据,我们需要挑选出最大的n个数据(n < 100),那么有没有办法实现这样一个目标呢?在这里,我想从排序的角度看看有没有什么办法可以实现这样一个目标。

    在前面的博客当中,我们实现的排序算法有下面几种:

    (1) 冒泡排序插入排序希尔排序

    (2) 快速排序

    (3) 合并排序

    (4) 堆排序

    (5) 选择排序

    (6) 基数排序

    那么是不是这8种算法都适合今天的题目呢?我简单的对它们进行了分析和归类:

    a)不到最后无法求出最大数据的算法,(插入算法合并算法基数排序

    这些算法的特点就是可以保证局部的数据基本有序,但是无法保证全局的数据有序。在全部数据得到正确地排序之前,没有人知道最大的数据是什么。所以针对这个题目而言,要想知道最大的n个数,那就等于要对所有的数据全部排序一遍。

    b)每次求出一个最大的数据,依次类推,直到所有的数据都已经排序。(冒泡排序希尔排序选择排序堆排序

    这些算法的特点就是,排序的时候,所有的数据都是按照从大到小排列出来的。按照冒泡排序来说,首先我们选出最大的数据,然后是第二大的数据,依次类推,直到第n大的数据找到为止。堆排序也是这样,我们在构建堆之后,也是每次从堆顶获得一个数据,不断调整堆,再接着获得第二大、第三大......第n大的数据的。我们以冒泡排序为例,看看这一次的算法应该怎么写?

void find_n_max_number(int array[], int length, int number)
{
	int inner ;
	int outer;
	int median;

	if(NULL == array || 0 == length)
		return;

	if(number > length)
		return;

	for(outer = length -1; outer > (length - 1 - number); outer --){
		for(inner = 0; inner < outer; inner ++){
			if(array[inner] > array[inner +1]){
				median = array[inner];
				array[inner]  = array[inner + 1];
				array[inner + 1]= median;
			}
		}
	}
}
    c)迭代搜索,首先对数据进行分类,小于于数组第一个数据的排在左边,大于的排在右边。如果右边的数据小于n,为m,那么在左边数组继续寻找剩下的(n-m)个数据;如果右边的数据大于n,那么在右边的数据继续寻找。( 快速排序
    不知道上面的解释说明白了没,没有清楚的同学可以看一看下面这个代码。

int partion(int array[], int start, int end, int swap[])
{
	int loop;
	int left = 0;
	int right = end - start;
	int value = array[start];

	for(loop = start +1; loop <= end; loop++){
		if(array[loop] < value)
			swap[left ++] = array[loop];
		else
			swap[right --] = array[loop];
	}
	swap[left] = value;
	memmove(&array[start], swap, sizeof(int) * (end - start +1));
	return left + start;
}

void _quick_sort(int array[], int start, int end, int swap[], int number)
{
	int middle;

	if(start < end){
		middle = partion(array, start, end, swap);

		if((number - 1) > (end - middle))
		    _quick_sort(array, start, middle -1, swap, number - (end - middle + 1));
		else
		    _quick_sort(array, middle + 1, end, swap, number);
	}
}

void find_n_max_number(int array[], int length, int number)
{
	int* swap ;
	if(NULL == array || 0 == length)
		return;

	swap = (int*)malloc(sizeof(int) * length);
	_quick_sort(array, 0, length-1, swap, number);
	free(swap);
}

总结:

    至于这些算法的结果怎么样,各位朋友们可以自己利用自己的电脑好好测试一下。

目录
相关文章
|
3月前
|
算法 测试技术 C#
区间合并|LeetCode2963:统计好分割方案的数目
区间合并|LeetCode2963:统计好分割方案的数目
|
11天前
|
算法
Acwing.786 第k个数(图解快速选择算法)
Acwing.786 第k个数(图解快速选择算法)
|
3月前
|
算法 测试技术 C#
C++双指针算法:统计点对的数目
C++双指针算法:统计点对的数目
|
4月前
|
算法 测试技术 C#
C++前缀和算法的应用:得到连续 K 个 1 的最少相邻交换次数 原理源码测试用例
C++前缀和算法的应用:得到连续 K 个 1 的最少相邻交换次数 原理源码测试用例
|
6月前
|
机器学习/深度学习 算法 测试技术
C++算法前缀和的应用:得分最高的最小轮调的原理、源码及测试用例
C++算法前缀和的应用:得分最高的最小轮调的原理、源码及测试用例
|
8月前
|
算法 索引
算法训练Day36|435. 无重叠区间 ● 763.划分字母区间 ● 56. 合并区间
算法训练Day36|435. 无重叠区间 ● 763.划分字母区间 ● 56. 合并区间
|
10月前
|
算法 前端开发
前端算法-寻找重复数
前端算法-寻找重复数
|
10月前
|
存储 算法 前端开发
前端算法-除自身外数组的乘积
前端算法-除自身外数组的乘积
给定一个数值,计算最合适的行列数量的代码
给定一个数值,计算最合适的行列数量的代码
71 0