服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - C#递归算法寻找数组中第K大的数

C#递归算法寻找数组中第K大的数

2021-11-25 14:48张玉彬 C#

首先将向量V从中间位置分开,分成左和右,分好后,中间值的索引如果恰恰等于K,就找到了,否则如果中间元素索引大于K,则在左子表中继续查找,忽略右子表,如果中间值索引小于K,则在右子表中继续查找,如此循环往复。

1.概述

  国人向来喜欢论资排辈的,每个人都想当老大,实在当不成,当个老二,老三,老K也不错,您一定看过这样的争论: 两个人吵架,一个人非常强势,另外一个忍受不住了便说:"你算老几呀?",下面就通过这篇文章就是要解决找出老几的问题!

2.应用场景

  在向量V[first,last)中查找出第K大元素的值

3.分析

  如果利用排序算法将向量V排好序,那么第K大元素就是索引为v.length-k的元素了,这样能解决问题,但效率不高,因为这相当于为了歼灭敌人一个小队而动用了我们全军的力量,得不偿失,回想快速排序中的分表,每次都将目标向量分为两个子表,左子表中全部小于中间元素v[mid],右边都大于中间元素v[mid],这样就可以减小了查找范围,因为我可以只查找左子表或者右子表就能找到目标元素了。如下图所示,我们可以将向量 v划分成如下

 

Left(<=KLargest) KLargest Right(>=KLargest)

 

按照这样的思路,我们仍使用快速排序中的分表策略,首先将向量V从中间位置分开,分成左和右,分好后,中间值的索引如果恰恰等于K,就找到了,否则如果中间元素索引大于K,则在左子表中继续查找,忽略右子表,如果中间值索引小于K,则在右子表中继续查找,如此循环往复。

快速排序中的子表划分函数为:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/// <summary>
/// 交换位置
/// </summary>
/// <param name="v"></param>
/// <param name="index1"></param>
/// <param name="index2"></param>
private void Swrap(int[] v, int index1, int index2)
{
  int temp = v[index1];
  v[index1] = v[index2];
  v[index2] = temp;
}
/// <summary>
/// 将向量V中索引{first,last)划分成两个左子表和右子表
/// </summary>
/// <param name="v">向量V</param>
/// <param name="first">开始位置</param>
/// <param name="last">结束位置</param>
private int PivotIndex(int[] v, int first, int last)
{
  if (last == first)
  {
    return last;
  }
  if (last - first == 1)
  {
    return first;
  }
  int mid = (first + last) / 2;
  int midVal = v[mid];
  //交换v[first]和v[mid]
  Swrap(v, first, mid);
  int scanA = first + 1;
  int scanB = last - 1;
  for (; ; )
  {
 
    while (scanA <= scanB && v[scanA] < midVal)
    {
      scanA++;
    }
    while (scanB > first && midVal <= v[scanB])
    {
      scanB--;
    }
    if (scanA >= scanB)
    {
      break;
    }
    Swrap(v, scanA, scanB);
    scanA++;
    scanB--;
  }
  Swrap(v, first, scanB);
  return scanB;
 
}

设计一个函数,FindKLargest(int[] v,int first,int last,int k);这个函数包括四个参数:向量V,开始位置first,结束位置last,和第k大中的K,则该函数为:

调用FindKLargest后,因为数组是从小到大排序,所以第K大元素的值为V[v.Length-k];

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void FindKLargest(int[] v, int first, int last, int k)
{
 
  //表示分表中值的索引
  int index = 0;
  index = PivotIndex(v, first, last);
  if (index == k)
  {
    //找到了K大
    return;
  }
 
  if (index > k)
  {
    //只在左子表中查找
    FindKLargest(v, first, index, k);
  }
 
  else
  {
    //只在右子表中查找
    FindKLargest(v, index, last, k);
  }
}

4.运行结果:

  原向量 :v  = { 100, 200, 50, 23, 300, 560, 789, 456, 123, 258}
  first = 0; last = v.Length;k=3
  输出:456

5.结论

  利用递归算法可以将比较复杂的问题划分为越来越小的小问题,这样能够使复杂问题简单化,这样的思路在系统设计和架构中同样有着至关重要的作用,一个好的架构师,面对复杂的问题,能庖丁解牛般化腐朽为神奇,而坏的却往往适得其反,他们的特长是简单问题复杂化。

6.项目文件
FindK.rar

延伸 · 阅读

精彩推荐
  • C#如何使用C#将Tensorflow训练的.pb文件用在生产环境详解

    如何使用C#将Tensorflow训练的.pb文件用在生产环境详解

    这篇文章主要给大家介绍了关于如何使用C#将Tensorflow训练的.pb文件用在生产环境的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴...

    bbird201811792022-03-05
  • C#VS2012 程序打包部署图文详解

    VS2012 程序打包部署图文详解

    VS2012虽然没有集成打包工具,但它为我们提供了下载的端口,需要我们手动安装一个插件InstallShield。网上有很多第三方的打包工具,但为什么偏要使用微软...

    张信秀7712021-12-15
  • C#C#微信公众号与订阅号接口开发示例代码

    C#微信公众号与订阅号接口开发示例代码

    这篇文章主要介绍了C#微信公众号与订阅号接口开发示例代码,结合实例形式简单分析了C#针对微信接口的调用与处理技巧,需要的朋友可以参考下...

    smartsmile20127762021-11-25
  • C#SQLite在C#中的安装与操作技巧

    SQLite在C#中的安装与操作技巧

    SQLite,是一款轻型的数据库,用于本地的数据储存。其优点有很多,下面通过本文给大家介绍SQLite在C#中的安装与操作技巧,感兴趣的的朋友参考下吧...

    蓝曈魅11162022-01-20
  • C#三十分钟快速掌握C# 6.0知识点

    三十分钟快速掌握C# 6.0知识点

    这篇文章主要介绍了C# 6.0的相关知识点,文中介绍的非常详细,通过这篇文字可以让大家在三十分钟内快速的掌握C# 6.0,需要的朋友可以参考借鉴,下面来...

    雨夜潇湘8272021-12-28
  • C#深入理解C#的数组

    深入理解C#的数组

    本篇文章主要介绍了C#的数组,数组是一种数据结构,详细的介绍了数组的声明和访问等,有兴趣的可以了解一下。...

    佳园9492021-12-10
  • C#利用C#实现网络爬虫

    利用C#实现网络爬虫

    这篇文章主要介绍了利用C#实现网络爬虫,完整的介绍了C#实现网络爬虫详细过程,感兴趣的小伙伴们可以参考一下...

    C#教程网11852021-11-16
  • C#C#设计模式之Strategy策略模式解决007大破密码危机问题示例

    C#设计模式之Strategy策略模式解决007大破密码危机问题示例

    这篇文章主要介绍了C#设计模式之Strategy策略模式解决007大破密码危机问题,简单描述了策略模式的定义并结合加密解密算法实例分析了C#策略模式的具体使用...

    GhostRider10972022-01-21